Big Software Contradiction
One of the famous books in software industry is "The Pragmatic Programmer: From Journeyman to Master". This book contain set of practical advises how to create better software. For every section I read I have thought about how I'll follow this advise and how it will looks like.
When I came to "The Evils of Duplication" section which suggest to follow the DRY (don't repeat yourself) principle (also known as "one point of truth") I thought in order to implement this principle I need to create some functionality only once and then use it whenever this functionality required. It will obviously help to maintain this functionality more easily, in case a problem will be found with the implementation there will be only one place to fix it.
The following section in this book was about "Orthogonality" concept. It explained that in many cases fixes in our software code unintendedly change functionality in places we did not want to change. Orthogonality means that changes over some dimension will not lead to changes in other (orthogonal) dimension. In other words we need to try to create software in such a way where implementation of some functionality will be independent from implementation of other functionality in system. When I thought about how I will write my code to make it orthogonal, I found that the best way is to make each part of system self contained, where everything it required is implemented locally. For instance if two different subsystems need a function that calculate square root of number each subsystem will have it's own function for it. In case I'll make some change in one of the functions these changes will not be affected on other subsystem.
When I thought about how I practically follow orthogonality principle I suddenly found that orthogonality suggest me to do exactly opposite of what DRY principle suggest me to do. I tried to find a way how to follow both DRY and Orthogonality principles and found that it's not so simple. If I'll make my code DRY it will not be Orthogonal and if I'll make my code Orthogonal it will not be DRY.
I familiar with TRIZ for many years and I knew exact word for such situations - "Contradiction" (I can recommend my presentation about "TRIZ and Software" where you can find how "Software Contradictions" looks like). I started to think about this problem, is it really contradiction? Maybe we can combine these two principles without problem? I found that it's possible to resolve this problem in same way like we resolve contradictions, it does not fully eliminate problem, it just make it less harmful. It's same like we cannot achieve "Ideal Final Result", but still try to resolve problem.
In my opinion all software methodologies (like imperative programming, functional programming, object-oriented programing, ...) try to resolve exactly this problem. It's very interesting that software engineers already tried to resolve problem in a way very close to TRIZ methodology. In object-oriented domain we have some kind of table similar to "Contradiction Matrix", it called "Design Patterns". Those two even share some names in title of their elements, for instance there is "Mediator" principle in "Contradiction Matrix" and "Mediator" design pattern.
This problem is not just another problem in software like many others. It's actually the "core" of other problems. That's why I call it "Big Software Contradiction". Many times when you try to solve some software problem you finally find that what prevent you find good solution is exactly that: "make code reusable and independent" or in other words "to reuse and not to reuse".
I'll try to illustrate it. Every programmer that write code for "long enough" time is familiar with such situation. Lets think in some software firm two programmers from two different teams meet in kitchen for coffee break.
programmer 1: what your team is working on?
programmer 2: we are trying to implement <some> functionality
programmer 1: Oh, really? We've already implemented it a year ago, and build it as reusable library. Don't waste your time on it. I'll give you access to this library, just use it.
programmer 2: Great! It will save us a lot of time!
Same two programmers some months later in working space.
programmer 1: Who changed code in my library? Now all of our tests are failing! Nothing works!
programmer 2: We made some small improvements in this library because of changes in the requirement of our system.
programmer 1: But you cannot change it! It's wrong change for our system!
programmer 2: But this what we need for our system!
Both programmers understand that it was bad idea to use same library in both systems.
Every big software project goes into one of the two bad states (many times into both of them):
- in case project reuse a lot of code it became "spaghetti" code and whole project became totally unchangeable
- in case project do not reuse code at all it leads to situation where required changes are spread all over big system and any change (even very small) require a lot of work, and there is danger that some code change will be missed and this part will stay buggy
From my experience I can say that most of programmers are not aware about this contradiction. While DRY principle is very known, Orthogonality is rarely mentioned by programmers. Most programmers try to write generic well designed abstract code (DRY) and start to decouple (Orthogonality) code and subsystems much later and not from the very beginning.
I think if programmers will be aware of this contradiction it will make them more creative, they will find better solution for their problem and will better understand harmful effects of their solution.
I thought a lot about "Big Software Contradiction" and in my opinion there is deeper contradiction (about contradictions levels you can read in Logic of ARIZ by dr. Vladimir Petrov), contradiction that is relevant not only for software systems but also for any technical system. I'll talk about it in next post.