Orthogonality in Programming and Software Engineering
Orthogonality is a critical concept when aiming to produce systems that are easy to design, build, test, and extend [1]. Orthogonality comes from geometry, where two lines are orthogonal if they intersect at a 90-degree angle, making them suitable for placement on a graph’s axes. In terms of vectors, they are independent of each other. Although the concept is not new in the world of computer science [3][6], it remains highly relevant.
In computer science or programming, it has come to mean independence or decoupling. In a well-designed system, the database code will be orthogonal to the user interface code: the interface can be changed without affecting the database, and the database can be changed without affecting the interface. Therefore, in a purely orthogonal system [2], operations have no side effects; each action only changes one thing without affecting others (another good example is a monitor, which has orthogonal controls: changing brightness does not affect contrast, and vice versa).
This article is based on the book “The Pragmatic Programmer,” so if you enjoyed it, I highly recommend purchasing it.
(Originally published in Spanish for Linkedin at: 01 May, 2023.)
Index:
- A non-orthogonal system
- Benefits
- Ways to apply orthogonality
- Testing
- Living with orthogonality
- Bibliographic References
1. A non-orthogonal system
Let’s say you have to handle a helicopter because the pilot has just passed out in front of you, and quickly identify four controls, naively thinking that each one controls only one aspect of the helicopter.
However, life is not that simple, and you discover that each control has a side effect. You pull down the left lever, but you also have to pull back the right lever and press the right pedal to stabilize the helicopter. Within seconds, you have a complex system where every change affects the other controls.
The controls of a helicopter are not orthogonal.
2. Benefits
As demonstrated by the helicopter, non-orthogonal systems are inherently more complex to change and control. It is necessary to design components that are self-contained, independent, and with a single, well-defined purpose.
When components are isolated from each other, it is known that changing one component does not require worrying about the rest. There are two major benefits to developing orthogonal systems: increased productivity and reduced risk.
Productivity: Changes are localized, reducing development and testing time. Additionally, this approach promotes component reuse and their combination.
Risk: “Sick” code sections are isolated, resulting in a less fragile system, along with faster and simpler testing with decoupled components.
3. Ways to apply orthogonality
Systems should be composed of cooperative modules, each implementing functionality independent of the others. This leads us to use layers, with each layer providing a level of abstraction. However, every time we write code, there is a risk of reducing the orthogonality of the application. There are several techniques to maintain orthogonality:
- Keep your code decoupled: Write modest code that does not reveal unnecessary details to other modules and does not rely on implementations of other modules (Law of Demeter [4]).
- Avoid global data: Whenever global data is referenced, the code becomes tied to other components that share that data. In general, your code is easy to understand and maintain if any required context is explicitly passed. The Singleton pattern [5] is a way to ensure that only one instance of an object of a particular class exists.
- Avoid similar functions: We often come across similar functions with different central algorithms at the beginning and end of their code. Duplicated code is a symptom of structural problems. Make it a habit to constantly critique your code, find opportunities to reorganize its structure and orthogonality, in other words: refactor.
4. Testing
Writing unit tests is itself an interesting test of orthogonality. What does it take to prepare and execute a unit test? Do you need to import a large portion of the rest of the system’s code? If so, you have just found a module that is not well decoupled from the rest of the system.
Resolving bugs is a good time to evaluate the orthogonality of the system.
When facing a problem, assess whether the solution changes a module or if the changes spread throughout the system. When a change is applied, does it resolve everything, or do other mysterious problems arise?
5. Living with orthogonality
Orthogonality is closely related to the DRY (Don’t Repeat Yourself) principle. With DRY, the goal is to minimize duplication within a system, while orthogonality aims to reduce the interdependence of system components.
By applying the principle of orthogonality, closely combined with the DRY principle, you will find that the developed systems are more flexible, understandable, and easier to debug, test, and maintain.
If you find yourself in a project where people struggle desperately to make changes, and each change seems to cause four other things to fail, remember the metaphor of the helicopter. The project is likely not orthogonal, and it’s time to refactor.
6. Bibliographic References
[1] Thomas, D., & Hunt, A. (2019). The Pragmatic Programmer, 20th Anniversary Edition. Addison-Wesley Professional. ISBN: 9780135957059.
[2] “Compactness and Orthogonality”. http://www.catb.org/~esr/writings/taoup/html/ch04s02.html#orthogonality (Accessed 30 April, 2023).
[3] Denvir, B. T. (1979). On orthogonality in programming languages. ACM SIGPLAN Notices, 14(7), 18–30.
[4] Caballero, C. (2019). Demeter’s Law: Don’t talk to strangers. https://betterprogramming.pub/demeters-law-don-t-talk-to-strangers-87bb4af11694. (Accessed 30 April, 2023)
[5] Gamma, E., Helm, R., Johnson, R., Johnson, R. E., & Vlissides, J. (1995). Design patterns: elements of reusable object-oriented software. Pearson Deutschland GmbH.
[6] Bhargav, N. (2022). Orthogonality in Computer Programming. https://www.baeldung.com/cs/orthogonality-cs-programming-languages-software-databases (Accessed 30 April, 2023).