For this week, I'm going to be analyzing two things: the first part of Refactoring to Patterns by Joshua Kerievsky and the code of JUnit. This is a very interesting reflection for myself, though it may not be as interesting to readers. I would highly recommend your own such reflections, though.

Refactoring to Patterns

Oh joy! Refactoring; it is sweet music to my passionate programming ears. Patterns; they are what should be put next to "elegant (n.)" in the dictionary. Merging these two things just blows my mind. This book is very dense in insight, knowledge and wisdom. I've had to read the book very slowly, very carefully in order to make sure that I'm not missing anything. It is just that good.

"I'm delighted with the result, and I think you will be too."

Martin Fowler wrote Refactoring; and Refactoring is a really, really good book. As a test of its greatness, it still stands as extremely relevant and powerful 11 years after he wrote it. However, Martin Fowler's understanding of refactoring was still in its infancy when he wrote the book; he was still learning about refactoring and how it should fit into the developer's toolkit. He knew that he had stumbled on to something really cool, really productive, really powerful. He attempted, and somewhat succeeded in laying that out in Refactoring.

He did miss the mark a little, though. He loosely defined how refactoring would fit into a craftsman's tool belt. He didn't seem to have any strong insight or knowledge about that. His book, though awesome, failed to define the Grand Unifying Theory of Everything (in Software Development).

"Now the connection between software patterns and agile development is finally told."

What Ward Cunningham was saying was: Joshua Kerievsky has presented to us a rendition of the Grand Unifying Theory of Everything (in Software Development).

You see, as in physics software development, there has been these two seemingly opposing 'theories' that I knew were a Good Thing™. First was the structure, logical Theory of Gravity Pattern Languages. These patterns seemed to suggest that design first development was the way to go. We could use patterns like lego blocks and put together loosely coupled, high cohesion architectures that just made sense. But, then, there were the other practices that were a Good Thing™ and were at odds with design first development. Test driven development, Agile management, Extreme Programming, Quantum mechanics and refactoring were all crazy, bottom up development practices that declared design first development was not the way to go (Note: When I say design first, I mean architectural design). This two were incompatible.

Along comes Josh and declares that he has the solution. Pattern languages are meant to provide a means of communication, abstraction and goals to refactor towards or to. They are not, instead, meant to encourage design first development (though, under very special circumstances, Josh argues that they are useful in that capacity). Instead of opposing the principles encouraged by Agile and Extreme Programming, pattern languages now complement them.

I realize that I'm gushing here and that my enthusiasm is a little over the top. However, the reason is that I've personally struggled with the fact that I love writing good code and I love writing good architectures. Both of these loves seemed to discourage the other--as if I had to pick one over the other. Josh has shown me a way to resolve that conflict. His way may not be the Right Way but it excites me to no end because no one else has been able to so elegantly and so simply connect those two.

JUnit

Switching gears, I want to take some time to analyze JUnit. JUnit was created by Kent Beck and Erich Gamma, both of which are leaders in the industry that I follow very closely. I expected to open up JUnit and just behold the magic that occurs within its confines. Surprisingly, I immediately started seeing some things that I did not like.

Now, let me be clear; I'm a student of programming right now. I'm still very much learning. I could be, and probably am, very wrong about the following statements. I'm not presuming to know more than Kent Beck, Erich Gamma and the contributors to JUnit. So, take all of this with that statement in mind.

All code can be found on Kent Beck's Github fork.

TestCase inheritance

The first place that I looked at was the TestCase class. It is most interesting to me because, when writing JUnit tests for Java programs, this is the class that a particular TestCase inherits. This all makes sense to me. However, the first real line of interesting code is the class declaration:

public abstract class TestCase extends Assert implements Test {

That is a dense piece of declaration but the part that interested me was extends Assert. That means that each TestCase is a subclass of Assert. The class Assert is, predictably, a class full of static assertions. So, I asked myself, "How is a TestCase a particular type of Assertion?"

First, I argued, there is the fact that on a larger scale you could look at each test case, which is itself a collection of tests, as an assertion. But, this isn't really true. A common test case pattern is to create a single test case for each class in the project: Foo is tested by FooTest. FooTest doesn't come to mind as a particular type of Assert, but rather a collection of Assertions that tests Foo.

So that didn't work. Let us do a mental exploration of what ramifications it would mean to refactor TestCase to NOT subclass Assert. That would result in TestCase having to implement the methods on Assert in order to maintain the current API and that those methods would forward the calls to Assert.assertX(). This would definitely increase the lines of code in TestCase but it would also break the Assert from the highest coupling that exists--inheritance.

Assert API

This may be being too nit picky, but I think that the argument order in the Assert methods is off. For example, consider the following method signatures

static public void assertEquals(String message, Object expected, Object actual)
static public void assertEquals(Object expected, Object actual)

The first signature, I would argue, is less than optimal. I think that in cases like this, where there is a parameter that may or may not be specified, that the parameter is the last parameter. The reason for that is quite simple: if for whatever reason I wanted to specify a message when I hadn't before, I know where to start. I don't start at the beginning, or the middle.. I start at the end. Even more specifically, in many IDEs there is an autocompletion tool. This autocomplete usually filters using type information and parameter orders. In the case of prepending, it is potentially more difficult to see what options are available to you. In the case of appending, the use of a comma will give you nearly all the options for overloading that you could need.

There is another reason, too. This one is a bit more flimsy because it is a personal preference but I think its valid. Parameter ordering is very important and there are a lot of factors that can go into it. Chief among them, though, is the importance of that particular parameter. For example, if I am writing an Assert statement, the two most important pieces of information are the expected and actual values. They are what I truly case about. However, if I'm force to stop my thought process to enter in a message string instead of focusing on what I care about, I become more error prone and/or slower.