Friday, 15 December 2006

Pretending to have written code

This technique is all about writing code based on code you pretend you have already written. TDD uses of this technique to great effect. The idea is you write a test based on code that doesn't exist yet. So, you invent code that you need in order to express the test. Then, once you have the test, you create the real code for the stuff you pretended to have and make it do what it needs to in order to make the test pass.

Great stuff.

However, the idea of pretending that code exists extends beyond simply expressing a test. It also works well for writing the code itself. Write the body of a method assuming that the objects, methods and variables you need are already there. This allows you to play with solving the problem without worrying about having the infrastructure to actually make the code work. This is powerful.

Some of the problems you see when you don't do this....

You start solving a problem, and you figure you need a method in order to solve the problem, so you go build the method, then you go back and try to complete the problem only to find you didn't really need that method, you actually need something quite different. Basically, when your solving something at the specification perspective write the code imagining you have all the things at the implementation perspective.

You ponder a problem and start putting in a bunch of variables that you think you need in order to solve the problem. This can cause all sorts of grief. Firstly, you tend to build infrastructure that you don't necessarily need, and secondly, and probably the worst effect, you can start constraining yourself about how to solve a problem in terms of the variables you have created. This can be massively limiting and can mislead you for a long time especially if you are resistant to throwing code out. This is one of the more common mistakes I have witnessed.

There is an idea in lean manufacturing that you delay decisions to the last possible moment. Or flipping that around, you leave your options open as long as possible. You want to do this in code also, if you make your mind up too early about something it can constrain your thinking and close out alternative solutions before you need to.

By pretending you can express your thoughts faster which tends to give you quicker feedback about whether you understand an idea or there are gaps in your knowledge. ie, quicker learning. As you learn you conceptulise what you need from the implementation perspective without actually writing it till you have conceptually solved enough of the problem that you need the implementation in order to pass a test.

The counter argument I have heard for not doing this is "It's not the way I think", but I think this is a hangover from when you first start programming. When you first start programming in a language your not entirely sure what's possible and what's not. If you write a "pretend method" your often unsure whether you can build the infrastructure or not. example "I wonder if I can hold arrays of strings?" So you investigate whether you can build the infrastructure you think you need. However, once you get proficient at a language/coding you generally know what's possible and what's not. You know what concepts you can express. Sometimes you don't, so its worth going off and investigating. But in general you know.

The constraint to this idea is that you don't want to pretend for very long. You want to work in reasonably tight cycles of writing tests, writing code. And by no means is this a "rule" it's just a thinking tool that can help you write good code faster. It's possible that pretending can constrain your thinking also, so it's good to have other thinking tools you can use too.

1 comment:

I have been doing "Design by Use" for many years. It is applicable at some many levels. At an inner-function, inner-module, or inner-class level it is very effective. While you are designing your solution you write the code as if the underlying code already exists. It is definitely a type of top down design. Test Driven Development also derives its design power by doing the same thing. Another aspect of Design by Use (DBU) is that it is applicable at high levels. Teams can write code as if functionality already exists, functionality that will be created by another team. I explain that dimension of DBU in a web paper: