Software engineering, really?
It’s typical of software engineers to feel a little apart in the company of engineers of other specialties. Why? Because engineering and software don’t really get along that nicely. Engineers who build a house, a bridge or even an electronic circuit have little margin of error. That makes the process a little more constrained than say the typical write-build-run cycle we are used to. Being more constrained requires self discipline and a lot of book reading which usually makes you grow big spectacles and makes you lose hair. Software engineers, on the other hand, have compilers and unit tests. That frees software engineers from discipline and introduces one single constraint, that of a comfortable chair. That does not have a proved influence on your hair, but surely a comfortable massage chair is more forgiving of a few extra calories in your diet. So if the standard picture of an engineer is a square, that of a software engineer will be more like a circle. If there’s a lot of discipline in bridge engineering, there’s a lot of make-break in software engineering. Finally, a bridge engineer could use its books as construction material. Honestly, how many of you developers could name a book you must keep by your side while you develop?
We are going to fix this empty spot by your side, now and forever. All the knowledge you need, the light you’ve been waiting for, is coming in the following lines. To be fair, there have been attempts in the past. One of the most notable is the arch-famous “Design patterns” from the Gang of Four, the book of all software pattern books. I argue that the Gang of Four is not the theory, but rather a well organized set of common practices instead. Does the Gang of Four contain equations? Nope. Full of pictures, so it can’t be an engineering book. Is there one common formula, one law that rules them all? nope, just some common solutions to common problems.
In order to extract the one law (well, one or two) we need to go back to the basic action of software design. In a previous post I stated that software engineer is the art of copying data. I will rectify: software programs are artistic ways of copying data. How do we make this software programs?
The GOF pictures contain a lot of UML boxes with many connections, but the simple beginning of it all is one problem we need to solve. Software engineering is the process of splitting that problem in parts to manage its complexity. The GOF pictures are not the basic rules because they represents systems where the problem has already been split in many, many parts. This splitting has to start from somewhere, and that’s where we will find the grounding rule of software enineering.
Rule number 1: If a problem is too big, split it in two problems
By splitting you get two little problems instead of one. The immediate advantage is that the two little problems might be more tractable. If each of the two little problems by themselves fit in your brain, you might be able to cook a solution for each and combine.
If not, you could buy coffee for a colleague who knows how to solve part A, and pizza for another colleague who’s an expert in dealing with part B.
The split gives you more tractable problems, and the ability to replace one part of the system (the dependent part) without touching the rest of the components.
Rule number 2: the way of the dependency
It seems that by applying the rule Nr 1 we could design all possible software architectures. We split A in B and C, then C in D and E. If all dependencies go the same way what we achieved is that the first component depends on the entire chain. Only the last one is a self standing entity. Rule number 1 is thus enough only as a beginning.
In order to be a successful split, the dependency between the two parts of the split needs to be one directional. That is, if you split A in B and C, it should be that B depends on C and not viceversa.
If you have a two-way dependency, you are specifying a chat between two parties rather than a software design. If B depends on C and viceversa, you cannot use any of the two entities independently, thus looking from far away, those two entities could very well be one. By the same transitive logic, the dependency chain b->c->d from above is no better than two components.
The rule nr 2 generates this super useful corollary: if you split A in B, C and D, make sure that the there is no chain. In practice this means B and D both depend on C, which acts as the contract or interface between the two.
And that was it. The book of software engineering is composed of two atomic rules from which all patterns derive.
Side note: I have taken the admittely very biased approach of making software design coincide with object oriented design. I’ll explain why in another post.