Tuesday, 11 December 2007

Code Should Mean Something

Dear Junior
There are always many discussions on the aesthetics of code and coding.
I thoroughly believe that code should have a meaning. By that, I mean that the code does not only execute something. Rather, it should go beyond that and try to reflect the idea of the programmer that wrote the code. As a reader, I should be able to reconstruct the most crucial ideas that lead to the solution I see in front of me.
In other words, the main purpose of the code is to explain your idea across time and space to another programmer, which might be yourself when you have forgotten all that extra information you have in your head. To your help you have a very restricted (programming) language in which you should make all your important ideas clear. Apart from that, you are only allowed to annotate (documentation) the solution with text in natural language.
In this respect, programming is a pedagogical trait.
Yours
Dan

Wednesday, 5 December 2007

Don't Test Your Code

Dear Junior

From time to time I get asked how to test a specific piece of code (EJB2:s or Action classes being nasty examples). Most of the times I spontaneously do not want to answer the question at all, because I think it lead us in the wrong direction.

I do not want to test my code; I want to test the behaviour of my code. The distinction might seem like hair-splitting, but I think it makes an important point. For example, if I have some order payment service I want to check that the payment information is well-balanced, that a payment request is sent to the bank, and a lot of other stuff. If we "test the code" we want to ensure all of these things as they are written.

However, if we focus on testing the behaviour we want to make sure that one idea ("generated book-keeping transaction is well-balanced") is correctly realised by the code. This approach enables us to focus on one aspect of the behaviour at a time and ask: How can I make it possible to test this behaviour. And the natural answer is to restructure to obtain testability.

So, phrasing the test-question "how do I test my code" leads us to build really elaborate testing frameworks to feed test data into the database, and then running our components in a production-like environment (e g Cactus tests). On the other hand, phrasing the question "how do I test the behaviour of my code" leads us to refactor until we have separated concerns to such a degree that each idea is possible to test in isolation.

So, don't test your code; test its behaviour.

Yours

Dan

ps One thing you can do if you redesign for testability, is that you can refactor your code to require less cumbersome and awkward mocking.

Thursday, 22 November 2007

Programs as Simulations

Dear Junior
I think I might have read it somewhere, or else I have introduced it myself, but one of my favourite metaphors about programming is:"All computer programs are simulations".
Some are obviously simulations of what happens in reality: aerodynamic flow around an airplane wing, or heat transfer in a nuclear reactor. However, other programs can also be viewed as simulations, but in a more subtle way. I here must exclude games, embedded systems, and real-time systems because I have too little experience to talk about them. However, I think the metaphor really applies to enterprise information systems.
Information systems are not simulations of what actually happens in reality, rather they are simulations of what would have happened had not the system been there. Let us take accounting as an example. In days of yore, the accountant was sitting with a physical leather-bound book, the ledger, and wrote down the transactions - one on each row. Today we have an accounting system that does this for us, so we do not have to do it ourselves. How, we can imagine that inside the box, there sit a little accountant and write those transaction-rows in a little ledger.
In reality, there is of course no little leather-bound ledger inside the computer. Instead there is some List-object on the heap, and other objects calling the add-method of that List, sending transaction data as argument.
However, I have found it most fruitful to embrace the "fantasy world" of a small leather-bound ledger. Because, that List on the heap, it is not any old List. It is a very special kind of List for which there are rules about what data it may contain, rules about what data can go in, and routines of how to handle it: check whether it is balanced, compute turn-over etc. It is not any List, it is a ledger. So, let us view it in that way, and build the class Ledger.
Suddenly it becomes so much easier to think about the code, to actually see if it does what it ought to do, and to see if client objects handle the ledger data in a sound way. Not to mention how much easier it becomes to talk about requirements.
As a result, I try to avoid returning "primitives" (such as int:s, doubles, Strings, and Lists or Maps thereof) from my public methods. Instead I create a class that someway represent this data in the fictive "fantasy world", and return an instance of that instead. My experience is that those methods are more easily understood and that the returned data has a higher chance of getting treated the right way.
It is not a coincidence that this "fantasy world" is very close to what we in Domain Driven Design refer to as our domain model of chosen abstractions.
So, of course not all programs are simulations. But I like to think of them that way; and it has helped me.
Yours
Dan

Tuesday, 20 November 2007

Letters

Dear Junior

Programming is a tough art, craft, and science. I guess I could ramble for ever about each and every of those aspects. I have thoroughly enjoyed our chats and conversations on the topic, and I hope that you have learned some things inbetween my monologues and half-structured answers to your questions. I certainly have learned a lot myself by trying to formulate thoughts and feelings I have had during my professional life. Often I have felt that the adequate, well-formulated answers have popped up in my head at a later occasion. I apologise for confusions I have caused.

However, as I would like to share with you as much of my experiences and thoughts as possible, I realise I cannot rely on our discussions alone. To complement them, I thought I will make an attempt to write you letters. The issues will be the same as our discussions: on how to build software systems, what I call ‘programming’ – both about what we build, and about the things we do to build them.

Of course, these thoughts will neither be totally adequate, nor totally well-formulated, but the goal is not to build a ‘theory about programming’ but rather to share my intuitive feelings and ideas.

I hope you will find these letters interesting. Hopefully some of the ideas will resonance against something in your own experience; you will bounce them around for a while, change them, and make them into your own.

Yours

Dan