One of the maxims of Object Oriented Design and use of Design Patterns is to Program to an interface, not an implementation. This is one of those maxims that provides enormous benefit when applied, but it is not necessarily obvious the benefits to be had when you first encounter it. I had a couple of recent experiences that makes it quite obvious to me that this principle is so vital to creating great products. I'll explain.
Quite a few years ago, I took Organic Chemistry and the professor was horrible and should never have been teaching. He was unkind and ineffective. I was having difficulties with a certain type of problem. At a particular point in Organic Chemistry, you are given a problem to work out the steps to synthesize (make from scratch) a particular compound. Some of these problems were not too tough, but more than a few seemed all but impossible. The professor was absolutely no help. Finally, I was talking to the Department Head (different professor) and he told me you need to work the problem backwards. That is, start with the compound you are trying to synthesize, and then proceed backwards one step at a time. This made a whole lot of sense. For starters, when you start at the result, you have fewer permutations to look at and you are starting with one datum that has 100% certainty (the product).
Many computer problems can also be worked this way. My software often has engineering applications and you may know a particular scenario (test data, for example) that should provide the correct answer. Well, you can start with the result and work back one step at a time. The way I do this is to use interfaces for the various objects and then create mock objects, many of which will simply return a value. So if the result is determined from an equation that is comprised of 10 other values, each of which are calculated by their own algorithm, I can substitute all 10 with 10 mock objects right off that bat. By doing this, I am able to test my final result algorithm and get that working by focusing only on the final algorithm. When I next replace a single mock object with a single concrete object, any errors that appear are clearly in the new concrete object and only that code. This reduces debugging time enormously. Development continues by substituting each of the 10 mock objects with concrete ones, and always testing the final result after making one and only one change from a mock to concrete object.
The benefits of this approach are many. The design stays very flexible, because it is interface-based. The code produces correct results from the very start. When the result suddenly is incorrect, there is so little code to check that the debugging exercise is trivial. You gain a lot of sanity from this.
I also notice that when code gives me trouble, my productivity plummets. I start thinking about other things. I don't enjoy it. It is not fun to figure out something that is a dog's breakfast. I surf the Internet. I play a game of Tetris. I make some phone calls. I take a walk. I turn on the TV. So while doing development by working backwards, or by using Test-drive Development principles may seem to take longer, it actually is much faster, because you get rid of your low productivity periods.
The other thing I like about this style of development, is you are very early on getting a result. It lacks the specific mechanics because of all the mock objects, but it is always in a working condition. It's analogous to doing Daily Builds. The other approach is horrible. You work days (or weeks) and you have yet to get a full working example to run. When you are ready to try it and it doesn't run, well where do you look for the errors? You may have dozens of objects, any of which could be in error. And more than likely, you have multiple errors and debugging code with multiple errors can take a very long time. And that is not much fun at all. I hope this is of some use.
Comments