How to Best Organise Your Code - Balancing Coupling, Cohesion, and Cognitive Coherence
In the realm of system design, the key limitation we face is our human cognitive capacity. We have a finite ability to comprehend and manage complexity.
To effectively manage complexity, we must organise systems into manageable components - be it classes, functions or modules, or larger parts.
There are many principles that can help guide how to group these components, but in my personal experience I have found two that stand above the rest: coupling and cohesion, and cognitive coherence.
Coupling and Cohesion: These concepts revolve around the idea of modularity. Coupling measures the strength of relationships between components, while cohesion quantifies the degree to which elements within a component are related or serve a common purpose. These principles help us create modular, maintainable systems by balancing interdependence and internal consistency.
Cognitive Coherence: This concept focuses on communication, both with others and with our future selves. Achieving cognitive coherence means designing systems that are intuitively understandable. It involves ensuring that the structure and organisation of the software align with our cognitive processes, facilitating comprehension and decision-making.
Both coupling and cohesion, and conceptual coherence are vital principles in software design, guiding the creation of modular, maintainable, and understandable systems.
But what if there is a conflict? If these principles pull in different directions?
Conflict between Cohesion and Conceptual Coherence: Sometimes, improving conceptual coherence may necessitate sacrificing cohesion. For example, consider the standard library header file math.h. While it provides a diverse range of mathematical functions, its cohesion may suffer due to the broad scope of functionality it encompasses. However, sacrificing cohesion in favour of improved conceptual coherence can still be justified if it enhances overall system understanding and usability.
High Coupling and Conceptual Model Mismatch: High coupling can indicate a mismatch between the conceptual model and the system’s requirements. In my personal experience, encountering high coupling has often been a sign that my conceptual model was flawed. For instance, when designing a complex system, if the components exhibit excessive interdependencies, it may be time to reassess the underlying conceptual model to better align with the system’s needs.
While there may be instances where one must be prioritised over another, I strongly believe we can, and should, use both these principles and create systems that are not only modular and maintainable but also conceptually coherent and intuitively understandable.
Andreas Olsson