Okay, so in Part #2 we talked about the Law of Demeter, and how you should think about it and follow it as if it were the Word of God when building classes.
One of the main reasons to follow the Law of Demeter is to write code and code modules that are loosely coupled. Loosely coupled modules have minimal interactions with other modules and thus have minimal affect on those other modules. Change something in a loosely coupled module and the chances of breaking something in another module are slim. If you have a minimal connection to another module, then you can only cause minimal bugs in that module.
And “minimal bugs” is a phrase to warm the heart of us all, no?
But the Law of Demeter even goes farther than that. Using the LOD principles means that you can write “testable code”.
So I think we’d all agree that the best way to avoid bugs in your application is to never check them in to your source control system in the first place. (And you are using a source control system, aren’t you?) And the best way to do that is to write lots and lots of unit tests. Unit tests are the first line of defense against bugs, as they can root out problems in your code as you write them. They can discover trouble at the very lowest level before it becomes a system level problem. Writing unit tests is the profound and solemn duty of every software developer. If you do “true” test-driven development, you’ll write your test first so that the bugs never even show up at all as you write your code to make your tests pass.
But when it comes to writing unit tests, a common refrain I hear is “I can’t test my code” or “My code is too complicated to test.” And my response to that is this:
If your code can’t be easily unit tested, you’re doing it wrong.
In fact, this is kind of getting to be our mantra around here at Gateway Ticketing.
Now there are exceptions, of course, such as code for directly manipulating your GUI, etc. But if you are writing anything other than that -- i.e. the vast majority of the code you do write -- then you should be writing code that is testable. But I’ll make the point again – if you can’t write unit tests for your code, then you need to change the way you are writing your code. That is, you should be writing code that is “testable”.
Code that is “testable” has a number of familiar qualities. The most noticeable of those is – surprise! – code that adheres to the Law of Demeter. LOD code is easy to test because the classes you write stand alone and have limited dependencies. Code with limited dependencies is easy to test.
A common refrain is this – “My code isn’t testable because it hooks up to too many other things like a database or a scanner or some other thing that can’t be attached to the test suite”. And my answer to this is: change your code to remove those dependencies and write mock objects for the instances that you can’t.
Code that is hard to test has dependencies. Creating an instance of a given class can result in the creating of a host of other classes – even classes that you don’t know about or can’t foresee. As noted above, heavily coupled code creates these dependencies. Consider the diagram below:
Here, you have a class that you want to test, but when you create it, it creates, in turn, three other classes that then can create yet more classes, including dependencies on external devices and other systems. Such classes are hard to test, because testing them brings in all those dependencies.
What we need is a way to limit and even remove those dependencies in order to make a class easily testable. And the way you do that is to find the “seam” in your class. The seam is the point where the dependencies are “attached” to the class to be tested. Once you find that “seam”, you can reduce and/or eliminate those dependencies. In the diagram below, the Class Under Test is made more testable by creating classes that don’t create dependencies – a better designed class that itself uses the LOD, a “stub” class that does nothing (say, a logging class that actually doesn’t log anything) or a Mock class that merely pretends to be the external dependency without actually being the external dependency.
Creating classes for which you can find this “seam” and substitute classes that don’t create the dependencies is key to creating a “testable” class. Remember, it is hard to introduce bugs into systems that are made of up easy-to-test classes. So, we should write easy to test classes, right?
The critical thing to remember here is that the class need not completely avoid the dependency – at some point your code is going to have to connect up and talk to that Oscillation Over-thruster – but rather your classes should be able to limit those dependencies as much as possible, and where they can’t, they should be easily able to “fake” having the dependency so the class can be tested without the real dependency.
And just how will that be done? You’ll have to tune in for the next episode!