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.
Every year, thousands of software development projects are developed. In most of these applications (especially line-of-business applications) you will see a lot of the same UI patterns:
- When the value in one dropdown changes, the list in another dropdown needs to change
- Two list boxes with arrow buttons that allow you move items between the lists
- A grid with add/edit/delete buttons that allow you to manipulate the list
Most applications have other common characteristics, like:
- The concept of a User that has to log in, reset their password, and change their password
- Some concept of security roles
- Loading objects from a database by ID
Every project also has housekeeping tasks, like:
- Setting up automated builds
- Copying files to a QA site after a build
- Coming up with a way to create a development copy of the database
The problem is that on every project, it seems that way too much time is spent getting this stuff to work. Why??
These are solved problems. We’ve all solved them before. But we end up re-implementing the same stuff over and over.
This is a problem. Making an AJAX call to update the list in a child dropdown when the parent dropdown changes is not rocket science. I don’t want to write this code ever again. I want to write stuff like this:
State: <%= this.Select(model => model.State)
.Options(Model.StateOptions, opt => opt.Id, opt => opt.StateCode)
.UpdateOptionsFor(model => model.County)
County: <%= this.Select(model => model.County) %>
(I’m using the MvcContrib HTML Helpers here.)
You write the code to implement this fluent interface once, and you don’t ever have to write it again. That’s the way that it should be. Every time you do something, you should be trying to find a better way to do it so that you can do it better next time.
A lot of people have already done lots of work for you, and you should take advantage of it. I’m talking about things like this:
- Using the built-in ASP.NET Membership stuff instead of rolling your own code to do Forms Authentication
- Using Rails scaffolding to create your website
- Using styling and controls from jQuery UI
- Using convention-based MVC frameworks (e.g. Rails or ASP.NET MVC + MVCContrib)
- Using the auto-mapping capabilities of Fluent NHibernate instead of writing mapping files or CRUD stored procedures
- Use S#arp Architecture as the framework for your application
Every developer should have a toolbox of code that he/she can draw from so that you can avoid being a plumber and spend your time doing valuable things, like writing business logic, designing user interfaces, and other things that you are being paid to do.
As if I needed any more convincing, I ran into another situation where TDD saved me from a lot of pain.
On my current project, we have a lot of client-side Ajax-y goodness. The feature that I was working on was dragging something from one part of the page and dropping it on another part of the page. I was using jQuery UI’s Draggables and Droppables to do this. I got most of the way done, and then realized that jQuery UI draggable/droppable support does not work completely in IE because of some IE bugs that they apparently have not worked around yet. (A newer version of the jQuery UI has come out since I wrote this so it’s probably fixed now.)