When developer works through a particular systems, a variety of modules being developed: user interface, filters, generators, controllers, models, and so on. In this variety and plurality often lies a danger of connecting and making separate modules dependent on each other. There is a healthy degree of dependence where a module can request an object of a particular interface to work with. And that is called dependency injection. But when the change in one module affects change in others that’s the time to rethink the design of modules involved.
When that happens one important concept to pay attention to is the concept of orthogonality. This term is taken from geometry initially. When two lines are orthogonal, they meet at right angles. In vector terms, they are independent. That’s the main meaning it has in programming. This independence, or decoupling, is very important to pay attention to when engineering the code. In a well-designed system, two modules that have different purposes will not be intertwined: change in one of them will not affect the change in the other. Unrelated things do not have effect on each other. The system is designed in a way that unless you are changing the interface of the particular class, the changes will not produce any extra unexpected behavior.
Once a developer adopts an approach of creating an orthogonal code, several things happen:
- Development and testing times are getting reduced due to simpler and more clear overall structure. If a developer adds unit tests on top of that – they’re set. That’s when those small functions can be forgotten completely and just used here and there.
- Orthogonal code becomes easy to reuse. Since the modules are decoupled, and not highly dependent on other components, they are ready to be potentially used in other projects too. If you create a log function that does not depend highly on the context, you would surely be able to use it elsewhere without the need to import the context with it.
- Debugging is much easier because it is pretty easy to pinpoint the problematic location in code as modules are developed with loose coupling and high cohesion in mind
- Particular modules won’t be tightly connected with particular vendors of 3rd party libraries.
- Fellow developers will be very thankful for concise and clear code. It will be easy to navigate and look through, and if changes are necessary, quick implementation without consequences will take place.
If you are not sure whether your system is orthogonal or not, ask yourself a question: “If I completely change requirements behind a certain function, how many modules will get affected?” You can obviously see that if the change in UI makes you change database, it is clearly not orthogonal, and design should be reconsidered. Strive for making the most with the least amount of change at any point in time.
When writing a code, keep in mind several things:
- Make your code decoupled. Make sure that your classes don’t reveal anything unnecessary to other modules. Keep the logic and structure encapsulated.
- Avoid globals. That makes you rely on that global state. That introduces a whole other level of potential problems. Instead, explicitly pass any context required for a given class or function. Or consider using singletons.
- If the functions are too similar, look into merging them in one function.
Keep your code clean and organized in a neat way, designing it to be as independent as possible. There are many long and short term benefits of applying orthogonality to your code. Refactor early and often. And make sure not to repeat yourself.
