When I asked professional software developers in companies what software development and design principles, they follow I oftentimes get a blank stare. Our industry has not matured enough to be able to extract out the major principles of constructing software the way civil engineering has been able to extract out the major principles of constructing physical structures. However, we are a young industry.
Perhaps the best-known principles in software development are the SOLID principles that were described by Robert C Martin in his book Agile Software Development. I find these principles are invaluable, especially the first two: The Single Responsibility Principle (SRP) and The Open-Closed Principle (OCP). The other three SOLID principles are still valuable, but I find the first two give me the biggest bang for the buck. Let’s take a look at them.
The Single Responsibility Principle is perhaps the best advice for building accurate and resilient domain models. It simply says that each responsibility in the system should be encapsulated within its own entity. This may be a module or function, or it could be a class or method in an object-oriented system. Every programming paradigm provides some mechanism for encapsulation and the Single Responsibility Principle is saying to use it to encapsulate responsibilities in a system.
But what is a responsibility? It’s a thing. Something that you can name. Software development is after all a linguistic activity and being able to name something accurately and precisely is a strong indicator of its cohesion. The Single Responsibility Principle is saying that software should be cohesive, that each encapsulated entity should be about one thing–something that we can easily name.
Bob Martin describes a responsibility as a “reason to change” and I find that a useful definition. We want to spread out the reasons to change our code for any possible situation so that it has a minimal impact on the program that we are changing. In order to do this, we spread the responsibilities out across classes so that every class is about one thing. This also helps clarify the domain model because you can see the groups of classes and the relationship to each other and that should give you insight as to the design of your system, what it’s resilient to in terms of changes, and where it’s rigid and inflexible.
This leads us to the second principle, the O in SO. This stands for the Open-Closed Principle and to me, it is the guiding light in software development. Bertrand Myers defines the Open-Closed Principle as “…software entities should be open for extension but closed for modification.” What this means is that we should construct software in such a way that when we go to extend it we are minimally changing existing code. To do this we typically don’t write code in the most expeditious way instead, we come up with an appropriate design that encapsulates the right things to minimize the future impact on the system.
Indeed, these principles reinforce each other so a system that is following the Single Responsibility Principle is also more open for extension. Whenever I think about a design or a piece of code I asked myself where is it open for extension and where is it close for modification. This is a valuable question to ask when evaluating a design so that you understand its strengths and weaknesses.
Flexibility is great but it often comes at a cost. Performance, clarity, and flexibility can end up at odds with each other, so we have to make trade-offs. The trick is making the right trade-offs. To me, these two principles, The Single Responsibility Principle and The Open-Closed Principle represent the core of a disciplined software development practice. They are lenses by which I can view software and evaluate their strengths and weaknesses so that I can make the best tradeoffs in each situation I’m in.
{2 Comments }
Previous Post: « Still XP After All These Years
Next Post: Core Developer Practices »
Unfortunately, there isn’t a lot of practical guidance on how to use the SOLID principles. Most resources I’ve seen show simple examples but nothing real-world. The best examples I’ve seen are in “Adaptive Code via C#,” but I wish there were more.
For instance, how is the Open-Closed Principle supposed to be supported by our code? Does it mean we need to make more of our methods virtual? Does it mean we need to deal more with interfaces rather than concrete classes? If you have recommendations for specific examples that support OCP, I’d love to know.
Hi Carlos,
Thank you for your comment. I agree, I haven’t seen many good examples of the SOLID principles in action. I haven’t seen many examples of good code in general that is publicly available.
The Open-Closed Principle basically says that we want to write our code in such away that when we have to add new features we are minimally changing existing code. There are many techniques and practices that support this: using abstractions correctly, design patterns, automated regression testing, cohesively managing instantiation, etc.
There is no single recipe for writing good code, it comes from having accurate mental models for what software is and how it has to change over time. There are many good books that have come out since Uncle Bob Martin wrote about OCP in Agile Software Development (including my book) that address writing extensible code. There are also hundreds of blog posts on this blog that address that very issue.
I hope this helps.
David