Jon Kruger -
  • About Me
  • Blog
  • Values
  • Presentations
About Me
Blog
Values
Presentations
  • About Me
  • Blog
  • Values
  • Presentations
Jon Kruger
TDD, unit testing

TDD Lunch & Learn – Thursday, July 23

Someone asked me the other day what new tool or technique they should learn, and the first thing that came to my mind was test-driven development. Test driven development is a proven technique that will help you write well tested and well designed code by writing your tests before you write your implementation code.

The best way to learn TDD is to watch someone do it. So on Thursday, July 23 from 12:00-1:00, I’ll be doing a lunch & learn presentation on TDD at the Quick Solutions office at Polaris (440 Polaris Pkwy, Suite 500 (5th floor), Westerville).

Lunch is provided (awesome!), so if you’re coming, please email amorey at quicksolutions dot com and let us know that you’ll be there.

I’ll show you the tools and techniques that I use to do test driven development and we’ll walk through the TDD process for some simple features. We’ll cover such tools and topics as NUnit, Rhino Mocks, behavior driven development with NBehave, and dependency injection, and I’ll give you the base code that I use on all projects to help write unit tests so that you can hit the ground running.

Can’t make it? I can come out to your place of work if you’re in the Columbus area and give this presentation again. If you’re interested, send me an email and we’ll set something up.

July 15, 2009by Jon Kruger
Uncategorized

Facilitating change

We’ve all worked with people who are adverse to change. Getting people to change and helping them to change is very difficult. The challenge is to convincing people of the need to change without tearing them down.

People always have a reason for doing things the way that they do them. I personally love ASP.NET MVC and I think that it makes software development much easier and must faster. Other people are scared of MVC because they are very comfortable with WebForms. I write tests all the time, but other people have no desire to write tests. But we all have a reason (whether good or bad) that we do things the way that we do them. The challenge is finding a way to give people a reason to change.

The fact of the matter is that many people are adverse to change. This could be for several reasons.

1. They don’t know change is an option. Every year I look back at how I wrote software a year ago and there is always something that I can’t believe that I did a year ago. A year ago I thought I was a good developer. Was I a good developer a year ago? I think I was, but there is always something that you aren’t aware of that can help you. Everyone is at different stages, and not everyone is at the same place as you. This does not necessarily mean that they are stupid or ignorant or that they don’t care, maybe they just haven’t come across something yet.

2. They don’t know why they should choose change. If you’ve been doing WebForms for the last 5 years, you probably feel that you’re pretty good at it. So why should you adopt ASP.NET MVC? I mean, is ASP.NET MVC really beneficial or just another technology that you have to learn? That is a completely legitimate question to ask, and many people are asking it these days.

If you’re trying to get someone to adopt ASP.NET MVC (or any other technology that is new to someone), you need to become a salesman. You need to sell that person on why said technology or way of doing things is going to help them. “This is the right way to do it” is not going to work. That doesn’t tell them how it’s going to help them. You need to convince them that the new way will make their life easier and then show them how to do it.

3. They don’t know how to go about changing. The best example of this is teaching people how to write unit tests. First you have to write your code so that it is testable, which means that you need to understand dependency injection and some DI container like StructureMap. Then you have to learn how to use a mocking framework like Rhino Mocks. You have to learn the difference between a unit test and an integration test, and ideally you will also learn how to write tests first. Yikes, that’s a lot of stuff to learn! The only way that I learned it all was by working with other people that knew how to do it and taught me how. So your colleagues may be willing to change, but they might just need some guidance (or a lot of guidance). They also have deadlines and don’t want to risk being late because they were trying to learn something new. This is where you need to convince them that writing tests will same them time and make their life easier because they will write less bugs and it will be easier to make changes to their code.

4. They don’t want to change. Many people are adverse to change and that’s just their personality. Other people are stubborn and don’t like people telling them that they’re wrong. These people are the difficult ones to deal with. Sometimes all of your efforts with these kinds of people will not succeed, but at least you can make an effort. I think it goes back to showing people why they should change — that there is another way to do things that will make their lives better. But getting them to this point will take a lot of patience and encouragement along the way.

Most people don’t change overnight. Even if someone wants to adopt all kinds of new technologies and practices, it may take them a long time. So give them something small to change. Instead of trying to totally rewrite their entire codebase, show them how to take a feature and write tests for it. Show them how their tests give them peace of mind because they know their code is working. Now hopefully you’ve won some more trust and can move on to bigger problems.

If you’re one of the people who is nervous about change, realize that in this industry things are constantly changing. No one can keep up with it all and know everything, so we need to rely on the expertise of others and learn whatever we can from whomever we can. It may require checking your ego at the door and realizing that you may not know the best way of doing something.

Changing might be hard work. It’s much more comfortable to do something that you know well. But nothing worthwhile is ever achieved without hard work. I promise you, you will be much better off in the end and you’ll be glad that you changed.

July 13, 2009by Jon Kruger
Uncategorized

Pulling others up

If there’s one thing that everyone in software development can agree on, it’s that everyone has an opinion on what the best way is to do things. We have lots of books, blogs and articles touting “best practices” and telling us how to do things (and how not to do things).

Often times as a consultant, you are brought into an IT shop where the native developers aren’t using the latest and greatest technology and might not be using the so-called “best practices” that you subscribe to. Usually in these situations, the people that brought you in are bringing you in for your expertise and are expecting you to do things the right way. This can lead to the native developers feeling somewhat threatened.

Recently a friend of mine started at a new client and noticed that the developers there were do most of their data access through dynamic SQL written in their C# code. When he questioned why they did it that way, the developers got defensive, saying things like, “We’ve been doing it that way for years and it’s been working for us.”

While the “best practices” would not recommend you doing all of your data access this way, it dawned on me, this guy is exactly right. He’s been writing his dynamic SQL for years, and he’s been succeeding in delivering working software. So in his mind, he’s not doing anything wrong.

There are two ways of handling this situation. The one that many people choose it to rip on the guy for being so stupid for ever thinking of doing it that way, while saying things like, “No one does it that way anymore”. All this does is alienate the developer and turn them off from trying to learn something new.

The preferred method is to show them that there is a better way. I once asked Andy Hunt how to get people who don’t write unit tests to start writing unit tests. His answer was that I needed to show them what was in it for them. I don’t think he could’ve been more correct. No one wants to do something just because it’s a “best practice” or some smart person said you should do it that way. We’ve all worked with people or seen projects where some “smart” person made something way more complicated than it needed to be and no one else could understand what they did or how to write code using their framework. No one cares if those people used “best practices”, you just hate having to come to work and deal with the mess that they made.

So if you’re working with someone and you think that there is a better way than how they’re doing something, show them the better way. Acknowledge the fact that what they are doing is working for them (they probably wouldn’t be doing it if it wasn’t). Just don’t belittle them for doing it that way, because they may be doing the best that they can.

June 30, 2009by Jon Kruger
LINQ

LINQ to SQL is NOT dead!

Ever since Microsoft announced that the Entity Framework was their ORM of choice, people everywhere have been saying, “LINQ to SQL is dead!” A lot of people feel like they’re not allowed to use LINQ to SQL anymore and that they have to use Entity Framework instead.

In fact, LINQ to SQL is not only alive and well, Microsoft has even announced LINQ to SQL improvements in .NET 4.0, including finally adding using ITable<T> for tables instead of Table<T>, which makes it much easier to test. Combine that with this open source tool that will create an IDataContext interface for you and you’re on your way to testable LINQ to SQL. So no, LINQ to SQL is not dead!!

Look, just because Microsoft says you should do something a certain way doesn’t mean that you have to do everything that they say. For example, Microsoft will almost never recommend using an open source software package over something that they’ve built (I say almost never because I’m sure they’ve done it at some point, but I’ve never seen it done). That certainly doesn’t mean that the Microsoft product is better than every open source tool.

For example, if you’re going to use an ORM, LINQ to SQL can get the job done for you, but if you’re looking for an ORM with more features, you owe it to yourself to check out Fluent NHibernate.

June 6, 2009by Jon Kruger
ASP.NET MVC

Why ASP.NET MVC is better than WebForms: Repeatability

A lot of people out there are asking, “Why is ASP.NET MVC better than WebForms?” or “Why should I switch from WebForms to MVC?” Usually the response includes these items:

  • Clear separation of concerns
  • Testability – support for Test-Driven Development
  • Fine-grained control over HTML and JavaScript

This doesn’t always mean much if people don’t do TDD and are fine without fine-grained control over HTML and JavaScript.

I’d like to add one more thing to the list: repeatability. Most of us are writing line-of-business applications, and when you write these kinds of web sites, there are common UI patterns that emerge:

  • A grid that contains a list of data, and might have Add/Edit/Delete buttons above it.
  • A screen that contains a bunch of input fields and Save and Cancel buttons.
  • If you save a screen with input fields and a validation error occurs, go back to the same screen and show the validation errors at the top of the screen.

Here’s where the repeatability comes in. Let’s take the Add/Edit/Delete grid screen as an example. I should be able to write code to handle this pattern once and never have to do it again. The next time I do this screen, I should only have to write code to do the following:

  • Tell the grid what data to display
  • Tell the grid which buttons to show (if any)

The code looks like this:


    <%= Html.JQueryGrid()
        .LoadDataFromUrl("/customers/GetCustomerData")
        .AddEditDeleteButtons()
        .Caption("Customers")
        .ExpandToFitAllRows()
        .Columns(columns =>
        {
            columns.For(x => x.Id).Visible(false);
            columns.For(x => x.CompanyName).AsEditLink();
            columns.For(x => x.Address);
            columns.For(x => x.City);
            columns.For(x => x.State).Width(50);
            columns.For(x => x.Zip).Width(50);
            columns.For(x => x.CompanyEmail);
            columns.For(x => x.PhoneNumber).Width(100);
            columns.For(x => x.FaxNumber).Width(100);
            columns.For(x => x.Salesperson).Width(100);
        }) %>

Pretty clear what that does, right?

Notice what I’m not writing:

  • Code that tells the site what to do when Add, Edit, or Delete are clicked
  • Code that enables/disables the buttons based on what is selected in the grid
  • Grid paging code (other than stored proc or LINQ code that handles this, if necessary)
  • Any JavaScript code (it’s all spit out by the code that renders the grid HTML)

I could write the code to do these things, but I’m not going to unless I have to because I need to do something different than the norm. I’m going to let my conventions and HTML helpers do the work.

So why is MVC better at this than WebForms? Because of separation of concerns. In this case, separation of concerns does not mean having a presentation layer, business layer, and data access layer. I’m talking about separation of concerns within the UI layer (your business layer and data access layer will be the same regardless of whether you use MVC or WebForms).

Let’s say that I have a screen with a grid with a list of data. The grid has a pager and Add/Edit/Delete buttons. Here are all of the pieces and parts that go into implementing this in MVC:

  • HTML code for the page – View
  • Code that writes out HTML and JavaScript for grid – HTML helper fluent interface + HTML renderer + jQuery grid
  • Get data for the view – controller method
  • Store data for the view – view model, populated with very little or no code using AutoMapper
  • Handle AJAX requests from the grid pager – model binder, which passes data to controller
  • Return data in a format the grid pager can understand – method on base controller class (lets MVC convert data to JSON and call Response.Write())
  • Verify security permissions – action filter attributes on controller methods
  • Handle Add/Edit/Delete button clicks – JavaScript written out by HTML grid render
  • Determine which screen to show when button is clicked – action filter attribute
  • Get data for Add/Edit/Delete screens – controller method

How would you do this in WebForms?

  • HTML code for the page – View
  • Code that writes out HTML and JavaScript for grid – 3rd party grid control
  • Get data for the view – code behind (calling into business layer)
  • Store data from the view – copied into controls in code behind
  • Handle AJAX requests from the grid pager – web service, configured to accept AJAX requests
  • Return data in a format the grid pager can understand – some method + JSON formatter + Response.Write()
  • Verify security permissions – code behind
  • Handle Add/Edit/Delete button clicks – custom JavaScript
  • Determine which screen to show when button is clicked – code behind
  • Get data for Add/Edit/Delete screens – code behind (calling into business layer)

Notice the pattern? In WebForms the code behind is doing a lot (not to mention the fact that you can’t easily unit test code behind files). Big code behind files do not lend themselves to repeatability — but small classes that have specific responsibilities are very reusable. This is why separation of concerns matter. In my MVC screen, I deal with a view, controller, view model, model binders, HTML helpers, grid renders, and action filter attributes. In WebForms, I have a view and a code behind.

Having these small classes leads to reusability. I can use the HTML helper that renders the grid for my page on another page that renders a grid. I can create a controller attribute that will check to see if a user is logged in, or in a certain role. I now never have to write code to check that again – I just put an attribute on a controller method and I’m done with security.

It’s also amazingly easy to write code when you’re working with small, specific classes. Can you tell me what this attribute does?

[RequiresPermission(Permissions.AddUser)]

How about this one?

[RedirectWhenGridToolbarButtonClicked]

All of this leads to reusability, less bugs, code that is easy to read and write, and less development time. The ultimate goal is less development time and better quality. By reusing code, you get things done faster (because you write less code) and you have fewer bugs (because you write less code).

On my current project, development time is way down. The screen that I’ve been talking about with the grid and Add/Edit/Delete buttons and paging, and all that? Done in 2 hours. Basic input screen with validation – 4 hours. The first screen with a grid took a few days, but I wrote all the HTML helpers and renderers that write out the HTML and JavaScript for the grid, wrote the model binder that takes HttpRequest form inputs and calls controller methods (based on conventions), and wrote all the code to receive AJAX requests and send back a response. On the next screen, I call my HTML helper methods that write out the grid HTML and pass it some configuration parameters, create some controller methods that load and save data, and I’m done.

This post didn’t cover MVC basics, like what controllers, view models, and model binders are. There are plenty of posts that explain that. I’m just hoping to explain that the reusability of ASP.NET MVC can drastically reduce development time and make things a lot easier for you.

May 26, 2009by Jon Kruger
.NET, ASP.NET MVC, unit testing

Hiding Thread.CurrentPrincipal from your code

You can get information about the current user who is logged in using Thread.CurrentPrincipal. The problem with this is that it’s difficult to work with it in tests. It forces you to set the current principal in your test setup so that your code will work correctly, and this can be difficult if not impossible in situations where you’re using Windows Authentication (if you’re using Forms Authentication, it’s not quite as painful, but it’s still a pain).

I don’t like to actually have calls to Thread.CurrentPrincipal scattered throughout my code. It makes my code less readable. Usually if I’m checking the principal, I want to know what user is logged in. That leads to code like this:

var currentUser = null;
var principal = Thread.CurrentPrincipal as MyCustomPrincipal;
if (principal != null)
    currentUser = ((MyCustomPrincipal) Thread.CurrentPrincipal).User;

Ick. I don’t want to write this over and over throughout my code. What if I had a class called PrincipalFactory that dealt with everything having to do with the principal? My class could look like this:

public class PrincipalFactory : IPrincipalFactory
{
    public MyCustomPrincipal GetCurrent()
    {
        return Thread.CurrentPrincipal as MyCustomPrincipal;
    }

    public User GetCurrentUser()
    {
        var principal = GetCurrent();
        return (principal != null ? principal.User : null);
    }

    public void SetCurrentUser(User user)
    {
        Thread.CurrentPrincipal = new MyCustomPrincipal(user);
    }
}

Now when I want to know who the current user is, I can write…

var currentUser = _principalFactory.GetCurrentUser();

Isn’t that much easier on the eyes?

It’s much easier to test too. I always use dependency injection and StructureMap, which also makes testing easier. Let’s say I had a class like this:

public class AccountController : Controller
{
    private IPrincipalFactory _principalFactory;

    public AccountController(IPrincipalFactory principalFactory)
    {
        _principalFactory = principalFactory;
    }

    [Authorize]
    public ActionResult Index()
    {
        var model = new IndexViewModel();
        model.WelcomeMessage = "Hello, " + _principalFactory.GetCurrentUser().Username;
        return View(model);
    }
}

In my test code, I’m going to use Rhino Mocks to stub out the IPrincipalFactory. So the test will essentially pretend that a user named “Jon” is the current user and then we’ll make sure that the Index() method does the right thing.

using System;
using NUnit.Framework;
using Rhino.Mocks;

[TestFixture]
public class When_displaying_the_index_view()
{
    [Test]
    public void Should_display_the_welcome_message_for_the_current_user()
    {
        // Arrange
        var principalFactory = MockRepository.GenerateStub();
        principalFactory.Stub(pf => pf.GetCurrentUser()).Return(new User { Username = "Jon" });

        var controller = new AccountController(principalFactory);

        // Act
        controller.Index();

        // Assert
        Assert.IsTrue(((IndexViewModel)_controller.ViewData.Model).WelcomeMessage, Is.EqualTo("Welcome, Jon"));
    }
}

This is much easier and cleaner than having to deal with Thread.CurrentPrincipal all over the place. If you didn’t hide Thread.CurrentPrincipal inside the PrincipalFactory class, you could still test it by setting Thread.CurrentPrincipal in the beginning of your test. I’ve been on projects that did it this way, and inevitably someone forgets to set Thread.CurrentPrincipal back to what it was before the test, or an exception happens and somehow the code that sets it back to the original value doesn’t run, and now tests will have different outcomes depending on what order you run them and which ones you run. This is usually a real pain to debug because you don’t know which test is causing the problem. Not fun.

April 13, 2009by Jon Kruger
SQL, TDD, unit testing

Writing tests for stored procedures

With all of the talk about unit tests and test driven development, there is little talk about writing tests for stored procedures and other database code. I would argue that testing stored procs is just as important (if not more important) than testing .NET code because (a) you don’t recompile all of your SQL code when you change something and (b) bugs in stored procs can lead to really bad things like data corruption that are hard to fix.

Writing tests for database code is not rocket science. There are no SQL testing frameworks to learn (at least I don’t know of any), but that’s fine because you can do just fine with plain ol’ T-SQL.

Let’s say I have a database that looks like this:

create table Users
(
    UserId int not null primary key identity(1,1),
    Username varchar(255)
)

create table Roles
(
    RoleId int not null primary key identity(1,1),
    RoleName varchar(255)
)

create table UsersInRoles
(
    UserId int not null, -- foreign key to Users
    RoleId int not null, -- foreign key to Roles
)

And let’s say that we were going to write a stored proc that looks like this:

create procedure [dbo].[IsUserInRole]
(
    @UserId int,
    @RoleId int
)
as
begin

if exists (select 1 from UsersInRoles where UserId = @UserId and RoleId = @RoleId)
    return 1
return 0

end

We can easily write a test for this. The test might look like this:

create procedure [dbo].[unittest_IsUserInRole]
as
begin

begin transaction

-- set stuff up
declare @UserId int
declare @AnotherUserId int
declare @RoleId int
declare @AnotherRoleId int

insert into Users (Username) values ('test')
set @UserId = scope_identity()

insert into Users (Username) values ('another user')
set @AnotherUserId = scope_identity()

insert into Roles (RoleName) values ('test role')
set @RoleId = scope_identity()

insert into Roles (RoleName) values ('another test role')
set @AnotherRoleId = scope_identity()

insert into UsersInRoles (UserId, RoleId) values (@UserId, @RoleId)

-- test stuff
declare @result int

-- should return true if the user is in the role
exec @result = IsUserInRole @UserId, @RoleId
if @result <> 1
raiserror('Test failed: should return true if the user is in the role', 16, 1)

-- should return false if user is not in the role but is in another role
exec @result = IsUserInRole @UserId, @AnotherRoleId
if @result <> 0
raiserror('Test failed: should return false if user is not in the role but is in another role', 16, 1)

-- should return false if user is not in the role but another user is in the role
exec @result = IsUserInRole @AnotherUserId, @RoleId
if @result <> 0
raiserror('Test failed: should return false if user is not in the role but another user is in the role', 16, 1)

-- should return false if the user does not exist
declare @NonExistantUserId
select @NonExistantUserId = max(UserId) + 1 from Users
exec @result = IsUserInRole @NonExistantUserId , @RoleId
if @result <> 0
raiserror('Test failed: should return false if the user does not exist', 16, 1)

-- should return false if the role does not exist
declare @NonExistantRoleId
select @NonExistantRoleId = max(RoleId) + 1 from Roles
exec @result = IsUserInRole @UserId, @NonExistantRoleId
if @result <> 0
raiserror('Test failed: should return false if the role does not exist', 16, 1)

rollback transaction

end

Notice that I’m beginning a transaction at the beginning of the test procedure and I’m rolling it all back at the end. That way all of the test objects that I insert into the tables won’t be left around after the test is done. If one of my assertions fails, the test will throw an error (but everything will still get rolled back).

The last step is to call the test proc from a standard .NET unit test using your favorite testing framework, which might look like this:

[TestFixture]
public class When_checking_to_see_if_a_user_is_in_a_role
{
    [Test]
    public void Run_IsUserInRole_tests()
    {
        // call the test stored procedure here
    }
}

That’s it! Now you can have peace of mind when you write T-SQL code too!

April 13, 2009by Jon Kruger
JavaScript

Strict equality operators in JavaScript: === and !==

The first time you see this, you think it’s a typo. But yes, === and !== are valid operators in JavaScript.

These operators do a strict comparison of equality by comparing both the type and the value. It’s easier to explain if I show you an example.

// This line will return true because both things mean 2
'2' == 2 

// This line will return false because on one side you have a string and
// on the other side you have a number.
'2' === 2 

Here’s another example:

var x = null;

if (x == undefined) // true
{
    // do something
}

if (x === undefined) // false!
{
    // do something
}

The first if statement evaluates to true because JavaScript says that null means the same as undefined, but the second if statement evaluates to false because null is not exactly the same as undefined.

Why would you care about this? Well, for the simple JavaScript that we write to manipulate stuff on a page of HTML, it probably doesn’t matter. But if you’re writing a complicated JavaScript library, this may be something that you might use. If anything, it’s good to know what it means so that you don’t freak out when you see it in someone else’s code.

April 7, 2009by Jon Kruger
ASP.NET MVC

ASP.NET MVC: Pass parameters when redirecting from one action to another

In ASP.NET MVC, it’s common to have a situation where you post to one controller action and then redirect to another controller action. Let’s say that you want to pass values from the first controller method to the other. The problem is that in out-of-the-box ASP.NET MVC, there is no way to redirect to another action and pass a parameter into the action that you are redirecting to. Here is one way you can get around this problem:

public class AccountController : Controller
{
    [AcceptGet]
    public ActionResult Index(IndexViewModel model)
    {
        model.Message = (string) TempData["Message"];

        return View(model);
    }

    [AcceptPost]
    public ActionResult Save(SaveUpdateModel model)
    {
        // save the information
        TempData["Message"] = model.Message;
        return RedirectToAction("Index");
    }
}

The reason that you would do a redirect in this case is so that (a) you can reuse the code in the Index method and (b) you are redirecting to a GET operation, so if the user clicks Refresh in their browser, it won’t try to re-post the previous page.

I don’t really like how that code works, for various reasons:

  • I’m using hardcoded strings (“Index” and “Message”). These might not get caught by refactoring tools if I want to change names, and I don’t get compile time checking on them.
  • In the Index() method, I have to grab the value out of TempData. That works fine if you’re being redirected from the Save() action, but what if I’m being redirected from another action? What if I’m not being redirected from anywhere and the user is accessing the action directly? Ideally, when the Index() method is called, it should have everything that it needs in its parameters at the beginning of the method.

Personally, I don’t like to see TempData or ViewData anywhere in my controller methods. Don’t get me wrong, I need them and I’m going to use them, but I want it all done under the covers. I favor the “One Model In, One Model Out” pattern, where each controller action method takes in one model parameter (or none) and returns another model. Doing it this way allows me to avoid the use of magic strings and hashtables. I want my code to look like this:

[PassParametersDuringRedirect]
public class AccountController : Controller
{
    [AcceptGet]
    public ActionResult Index(IndexPresentationModel model)
    {
        return View(model);
    }

    [AcceptPost]
    public ActionResult Save(SaveUpdateModel model)
    {
        // save the information

        var presentationModel = new IndexPresentationModel();

        presentationModel.Message = model.Message;

        return this.RedirectToAction(c => c.Index(presentationModel));
    }
}

This code does exactly what I want. Now…

  • I don’t have any magic strings.
  • Everything is strongly typed.
  • The parameter passed to the Index() method will always be complete. I don’t have to load anything out of TempData to get it to work.

One thing I love about ASP.NET MVC is that it is very extensible, so you can usually make it do what you want. This is the purpose of the MVCContrib project — people extending ASP.NET MVC to make it even better.

You may notice that in the code snippet above, I decorated my controller class with the [PassParametersDuringRedirect] attribute. Now, any parameters that I pass into RedirectToAction() will get passed into the action that I redirected to.

One slight problem… this new version of RedirectToAction() is an extension method on the Controller class, which means to call it, you would have to write “this.RedirectToAction()”. If you don’t want to have to write “this.” every time, you can just create a base controller class that has this method:

protected RedirectToRouteResult RedirectToAction(Expression> action) 
    where T : Controller
{
    return ControllerExtensions.RedirectToAction(this, action);
}
April 6, 2009by Jon Kruger
Design, Quality

Don’t cheat on those small apps!

At some point, we all have to write some small apps. I’m talking about things like…

  • Some small utility or diagnostic app
  • Something to help with your deployment process
  • Other small applications or websites (i.e. something that takes a month or less)

In these cases, we often throw good software design principles out the window. We say that we don’t need to write unit tests, we don’t need dependency injection, we can put data access code in our code-behinds, and things like that. Since it’s a small app, we think we can get away with it.

Just because your app didn’t take you long to write doesn’t mean that you get off easy. The consequences of your decisions just aren’t as severe, but that doesn’t mean that the pain is gone!

How many times have you written some small utility to help with something and then your boss sees it and really likes it, and then he asks you to add more functionality to it. Eventually you’ve spent a couple months on the app. If you cheated at the beginning, that code is going to hard to change and it’s going to start becoming more of a pain.

Maybe you’re writing a console app to help with your deployment process. Now this code better work, because if it doesn’t, your app might not deploy correctly. This is very important code! Doesn’t code this important warrant some extra attention (i.e. tests)?

Look, I’m not saying that every little app has to be this big, blown-out, enterprise application. I’m just saying that you should be careful when you cheat, because you don’t want that to come back to haunt you.

Many times you can take simple steps to make things easier to change. Take dependency injection, for example. It is really easy to set up an IoC container like StructureMap, it doesn’t overly complicate your code, and you don’t have to write tons of extra code to use it. But if you want to write tests for you code, dependency injection will make it a lot easier. You’re just putting code in better places.

Again, there are times to use dependency injection and there are times where it’s superfluous. There are times when unit testing is essential and times when you can get away with it (personally I always like writing tests if I can, that way I know my code works). But you need to be careful. Software is software, and many of the same development principles that apply to big apps still apply to small apps.

March 31, 2009by Jon Kruger
Page 19 of 24« First...10«18192021»...Last »

About Me

I am a technical leader and software developer in Columbus, OH. Find out more here...

I am a technical leader and software developer in Columbus, OH, currently working as a Senior Engineering Manager at Upstart. Find out more here...