Design Patterns: DRY

A while ago, I was working with a younger man and as I was doing a code review, I came across some code that looked kind of like this:

readColumnA () {
      columnA = columnReader("columnA");
      processColumn(columnA);
}

readColumnB () {
      columnB = columnReader("columnB");
      processColumn(columnB);
}

It isn’t really important what was in the file, or what the processing being done was.  These two methods are basically identical, the only difference is the value passed to columnReader.

I suggested that he change this code to look more like this:

columnProcessor (String columnName) {
      column = columnReader(columnName);
      processColumn(column);
}

Then, you could call it for each column you need to process.

When you remove duplication like this you are making your code DRY.  DRY stands for don’t repeat yourself.  In the first example you can see that we repeated the algorithm for processing the columns for each column we needed to process.  We can see that the only thing that changed was the column name, and extract that part out, and then have a generic method to process columns.

My colleague had heard of DRY, but thought that he shouldn’t use it here since he was pretty sure that we would change and want to process columnA differently than columnB in the future.  While this argument makes a certain amount of sense, we need to remember that we are not psychic, and while we can speculate on how a software project might evolve, we are never really sure.  The requirements and priorities change under our feet, and our guesses are often wrong.

In my opinion, and in my experience it is always better to keep your code clean because you want to be able to make changes easily.  If, at some point, in the example above, column A and column B processing diverge, then (and only then) you should change the code to accommodate this.

 

Advertisements

Unit Testing – Part 1

I’m fairly new to writing automated unit tests. I’ve read about it and I’ve tried it out and we even have a handful of java classes (10 to 20) that have full coverage from unit tests. But now it looks like we might be changing our view of testing and diving in head first.
So here are some things that I’ve learned that I didn’t really pick-up on when reading the books about JUnit.

Step 1 – Write Testable Code
Something that I missed when reading books about unit testing is that you have to change the way you write the code in the first place. This is generally a good thing, but something that is difficult to do across an entire development team.
Long methods – are very difficult to test – We have some methods that are over 1000 lines, it’s not easy (maybe not even possible) to test a method that is this big.

Dependency Injection – methods that create their own database connections, or create any new objects directly are very difficult to test well. For legacy code, I’ve found that a good way to handle this is updating the method to take these objects as parameters, and then creating a new method with the old signature that simply creates the objects and passes them in. This allows you to create mock objects for database connections, etc. which lets you test all the code in the method without needing a database to connect to.
ex:
public User buildUser() {
Connection conn = getConnection();
return buildUser(conn);
}
public User buildUser(Connection conn) {
... existing/old code to read user object from databse ...
return user;
}

References to Static Methods – Static methods are easy to test. Code that calls static methods are VERY hard to test, because you can’t mock/stub out the static methods. So you end up having to test all the code in the static method along with the code in the method you actually want to test. I don’t think small methods that take few or no parameters from well tested libraries are much of an issue. For example, if your code calls Math.random(), it’s still fairly easy to test. But if you have a lot of “utility” methods that take large objects as parameters or that do complicated logic it’s difficult to mock-up the test data to get those static methods to return all the different scenarios that allow you to run through all the code in the method under test.

If developers are writing code that is difficult to test, they will hate writing unit tests. It is time consuming, the tests will break often from small changes in the code, and code coverage will be low. They need to change the way they write the code in the first place before you can be successful in implementing unit tests.

In general, testable code is better quality code anyway. Having short methods that “Do one thing”, and creating methods that use Object Oriented Design (ie: not static) are easier to maintain, easier to read, and much nicer to work with. This is a side benefit of implementing unit tests.

I’ll continue with my lessons learned in later posts. Something I’m still not sure how we are going to handle is all the existing legacy code that doesn’t fall into the category of “testable” or at least not “easily testable”.