When Good Code Goes Bad

Most systems start off with a nice clean design, but over time software starts to rot.

Does Design Matter?

  • Software design is about managing the complexity of a system. Unmanaged complexity leads to difficulty in making changes to the system, which is important because all software development is change.
  • Poor design leads to lower quality systems, less functionality to clients, higher costs (for everyone), loss of business and misery for developers.

Why Do People Tolerate Poor Design?

  • Business pressures:
    • Developers are often encourages to working software fast, so “quick and dirty” solutions go into production
  • Lack of knowledge:
    • Introductory courses / texts tend to focus on syntax rather than design
    • People learn from what they see, and there are a lot of poorly designed systems to learn from
  • Scale effects:
    • Larger systems benefit from good design more than smaller systems
    • It takes more effort to design larger systems well
    • Fewer developers have experience developing larger systems

What are Design Principles?

Design principles help us to understand the “rules” about the best way to manage complexity, and therefore maintiain and increase the value that is delivered by our code. They are best viewed as guidelines. They shouldn’t be followed blindly, as there are costs involved in using them.

What is Design Rot?

Most systems start of with a nice clean design, but over time, “software starts to rot”. As “Uncle Bob” Martin says:

At first it isn’t so bad. An ugly wart here, a clumsy hack there, but the beauty of the design still shows through. Yet, over time as the rotting continues, the ugly festering sores and boils accumulate until they dominate the design of the application. The program becomes a festering mass of code that the developers find increasingly hard to maintain.Robert C Martin, Clean Code

What are the Symptoms of Design Rot?

Martin identifies 4 symptoms of rot:

  1. Rigidity: Software becomes difficult to change, and changes cause other changes in dependent modules. Simple changes become expensive, developers become fearful, unknowns increase.
  2. Fragility: The tendency of the software to break in many places every time it is changed, sometimes in areas that have no conceptual relationship with the area that was changed. Fixes introduce new bugs. Developer credibility is lost.
  3. Immobility: The inability to reuse software from other projects or from parts of the same project. Drawing on existing modules is impossible because of they bring in too many dependencies.
  4. Viscosity: Design Viscosity occurs when the design-preserving approaches are harder to use than hacks, i.e. it is easier to do the wrong thing than the right thing. Environmental Viscosity occurs when the development environment is slow and inefficient, leading to the temptation to take short cuts.

These issues tend to be more of a problem as the size of a software base increases.

What are the Causes of Design Rot?

Each of these symptoms is mainly caused by improper dependencies between the modules of the software. Therefore, managing dependencies between modules is at the core of good design. This applies at several levels: framework, library, package, class and method.

Where Does it Happen

At all levels of abstraction:

  • Function / method level
  • Class / module level
  • Package level
  • API level
  • In the interfaces between systems

How Do We Avoid Design Rot?

Some of the general principles are:

  • Value design and pay attention to it
  • Iteratively improve design
  • Improve design at each layer of abstraction
  • Desgin modules that are small and focused (high cohesion)
  • Reduce dependencies between modules (low coupling)
  • Remove redundancy and repetition
  • Keep learning about design and architecture

One thought on “When Good Code Goes Bad

Leave a Reply

Your email address will not be published.