Much of my life as a developer has been spent reading through someone else’s code to try to fix a defect or add some new behaviour. As a result I have some heartfelt pleas to make to my fellow developers to make life easier for those who follow them.
Give tests names that describe what they test
The worst test methods I’ve come across in this regard were called “Test1”, “Test2” and “Test3”. Together with the way the tests were written it made it very difficult to work out what behaviour was being tested. Not only would more descriptive names have made it easier to fix the tests when they broke, but the tests could have provided documentation of the expected behaviour of the subject class. The Growing Object Oriented Software book suggests the use of TestDox, which generates documentation from tests using the test method names. Another way of providing documentation from tests is suggested by Phil Haack in his post on Structuring Unit Tests. By having a test class for each individual method on the class being tested you can read the collapsed methods like a spec and also see which methods are under test from the class dropdown in Visual Studio.
Show how to use the class
The best tests I have seen in this respect are the SimpleTests for the MarkdownSharp project, which are sufficiently clear to provide a demonstration of the formatting to apply in order to achieve the desired effect. For classes requiring lots of setup I’ve found it useful when the setup code has been extracted into separate (clearly-named!) methods.
Give methods descriptive names
And remember to update them if you change the code! One of the worst pieces of code I’ve had the misfortune to set eyes on was an 800-odd-line monster method called ‘Make[X]’. Although the method itself did eventually produce X, there were dozens of nested calls to other methods also called ‘Make[X]’ which, of course, just performed steps in the process (one of them actually generated the filepath to a control). I suspect that in many cases like this the name was originally descriptive of what the method did, but code was gradually added or removed until the name no longer described the behaviour. My suggestion is that in the first instance you describe everything that the method does in its name. If you end up with a name with lots of ‘and’, ‘or’ or ‘buts’ you may find you want to split the method up.
Write comments – and make them useful
I used to work with a guy who found it terribly frustrating that the rest of us, in his eyes, didn’t comment our code properly – he thought it essential to prefix every if statement with the comment ‘check if [variable name] is true’. Sadly none of his comments ever explained the relevance of the check to the behaviour. Of course, careful naming of variables goes a long way towards expressing their role (don’t use comments instead of sensible names), but it can’t always make things completely clear. (See Jeff Atwood’s post Code Tells You How, Comments Tell You Why.) If you have an instance variable, put a comment on it explaining what it’s used for, and likewise remember summaries on your methods explaining what the parameters are for. Comments and regions can also provide useful signposts when you’re skimmming through a large file of unfamiliar code. Of course, remember to update the comments if you’re changing the code.