Software development is a complex process that involves addressing complex problems. The complexity arises not only from the problem itself but also from the choices we make during the design and development of a solution.
In his influential paper (1986) “No Silver Bullet—Essence and Accident in Software Engineering”, Fred Brooks outlines two types of software complexity: accidental and essential.
Accidental Complexity
Accidental complexity is the non-essential complexity we add to a solution that is not inherent to the problem we are trying to solve. It arises from decisions we make, such as selecting a particular framework or making assumptions about the problem without adequate verification.
It is like shooting ourselves in the foot by adding more complexity. Neal Ford articulates it very well by Neal Ford: “Developers are drawn to complexity like moths to a flame - frequently with the same result.”
There are several reasons why additional complexity may be added to a software solution, including:
- Attempting to make the design or code more “generic”
- Making assumptions without adequately verifying them within the problem domain
- Insufficient understanding of the problem
- The desire to utilize some new, cutting-edge technology
- Falling victim to the frozen caveman anti-pattern
- Inadequate expertise with the technology and tools being employed in the solution
Accidental complexity is often associated with over-engineering. Over-engineering is a common cause of accidental complexity, it is not the only one.
Essential Complexity
Essential complexity is the complexity inherent in the problem we are trying to solve, regardless of the tools, technologies, or approaches we use. Essential complexity cannot be reduced but must be managed properly to enable flexibility in responding to change.
Our choice of technology can sometimes transform essential complexity into accidental complexity. Technological advances can also render yesterday’s essential complexity into today’s accidental complexity.
Tackling the Complexity
Understanding the sources of the complexity is crucial in tackling the complexity. To better understand these sources, we can classify them into three categories:
- domain
- architectural choice
- implementation choice
This categorization helps to differentiate essential complexity from accidental complexity and address them appropriately.
In order to deliver effective solutions, it is necessary to comprehend the complexity, and strive for simplicity in design.
Achieving simplicity requires deliberate intention and action. Pursuing simplicity amidst complexity can lead to more elegant solutions that are easier to manage, maintain, and scale.