Last week I gave a domain driven design course and one slide I put up was titled “Coding for Friends” with a single message “Avoid conceptual corruption”. In other words “Code so I can understand you and you don’t screw up my mind”. I did not realise the significance until I started working through the practical exercises with the groups and kept on referring back to this simple idea.
So often we write code in isolation and the code reflects our personal interpretation of the problem and a personalised solution too. We easily forget that other people will execute this code, modify it, and, at the very least, read it. Coding is a social exercise first, then a technical exercise. We have a responsibility towards increasing the probability of success for the next person or team that will work this code.
We can write code in isolation that is of high quality, focusing on self and metaphysics of quality, etc. That’s a zen view and it is about you. I like to think (believe?) that Ubuntu is zen for a group, not for an individual.
In Zulu, the Ubuntu philosophy is summed up as
Umuntu ngumuntu ngabantu
which roughly translates to
A person is a person through (other) persons
And in geek-speak it is
A developer is a developer through (other) developers
I get better because you make me better through your good actions. And the opposite also holds true: You get worse at what you do when I am bad at what I do.
How do we write ubuntu code? It’s not hard. It’s based on “old” principles and wise words of many people. It’s old material but worth revisiting with ubuntu glasses on: when you think about what the effect is on other developers and what the reciprocal effect will be, back onto yourself.
Reveal your intention, not your implementation. If you have designed a project management app with tasks and decided to implement it as a graph, call the class Task and give it a method called resolveCyclicDependencies(). Don’t create a class Node with a method called topologicalSort().
Avoid side effects. Let a method do one thing, and one thing only. It’s frightening how many developers don’t do this. For example, if you add a line item to an invoice, don’t update the total. Have something else that calculates the total. Basically, be boring and predictable. I long time ago a SQL guru looked at my code and said “The optimizer does not like fancy code”. Same thing.
Broken metaphors. Metaphors exist for conceptual understanding. Once you get the conceptual break through, leave it. It’s ok! Trying to build an economic model with a metaphoric model of fluid flows (or bears and bulls!) will just create havoc downstream.
Where am I? Figure out where you are in the bigger picture. Are you upstream or downstream? Is someone going call my code to create that Book object? Am I going to call someone else’s code to get the Customer object? In other words, know what you supply and what you consume.
Fail fast. Assert! It’s allowed in production code too. I would rather fail quickly and dramatically than delay the effect until it is obscure. More importantly, when I read an assert then I know that the particular condition is critical. It is an invariant that must be honored.
Pairing. Programming in pairs is an active exercise, not a case of a second syntax checker. I see many teams that pair mechanically and it does nothing for increasing code quality at all. If you practice active pairing, you are closer to ubuntu coding.
There are other techniques which increase the collective responsibility of your design and code such as context maps in strategic design, values and attitudes such as responsibility and feedback. I’ll deal with those on another day.
But for now, I think that
Code is code through (other) code!
Do you have any other ubuntu coding techniques? Attitudes?