Only the engineers who work on a large software system can meaningfully participate in the design process. That’s because you cannot do good software design without an intimate understanding of the concrete details of the system. In other words, generic software design advice is typically useless for most practical software design problems.
Generic software design
What is generic software design? It’s “designing to the problem”: the kind of advice you give when you have a reasonable understanding of the domain, but very little knowledge of the existing codebase. Unfortunately, this is the only kind of advice you’ll read in software books and blog posts. Engineers love giving generic software design advice for the same reason that all technical professionals love “talking shop”. However, you should be very careful about applying generic advice to your concrete day-to-day work problems.
When you’re doing real work, concrete factors dominate generic factors. Having a clear understanding of what the code looks like right now is far, far more important than having a good grasp on general design patterns or principles. For instance:
In large codebases, consistency is more important than “good design”. I won’t argue that point here, but I wrote about it at length in Mistakes engineers make in large established codebases.
Real codebases are typically full of complex, hard-to-predict consequences. If you want to make your change safely, that typically constrains your implementation choices down to a bare handful of possibilities.
Large shared codebases never reflect a single design, but are always in some intermediate state between different software designs. How the codebase will hang together after an individual change is thus way more important than what ideal “north star” you’re driving towards.
In a world where you could rewrite the entire system at will, generic software design advice would be much more practical. Some projects are like this! But the majority of software engineering work is done on systems that cannot be safely rewritten. These systems cannot rely on “software design”, but must instead rely on internal consistency and the carefulness of their engineers.
Concrete software design
What does good software design look like, then?
... continue reading