Getting a SOLID start.
Posted by Uncle Bob on 02/12/2009
I am often asked: “How should I get started with SOLID principles?” Given the recent interest and controversy about the issue, it’s probably time I gave a written answer.
First things first.
You can read about the Solid principles here. This is a paper I wrote nearly a decade ago. It uses a somewhat dated form of UML, and examples are in C++. Also the concepts are severely abbreviated. This is the Cliff Notes. Still, it should give you an initial notion of the names, definitions, and concepts.
There are quite a few papers here that explain the principles in much more detail. Just click on the “Design Principles” topic to see them all. Though I think you’ll find the other topics pretty interesting too.
Finally, the principles are definitively described in two books: Agile Software Development: Principles, Patterns, and Practices, and Agile Principles Patterns, and Practices in C#. You can see descriptions of these books here
What do I mean by “Principle”
The SOLID principles are not rules. They are not laws. They are not perfect truths. The are statements on the order of “An apple a day keeps the doctor away.” This is a good principle, it is good advice, but it’s not a pure truth, nor is it a rule.
The principles are mental cubby-holes. They give a name to a concept so that you can talk and reason about that concept. They provide a place to hang the feelings we have about good and bad code. They attempt to categorize those feelings into concrete advice. In that sense, the principles are a kind of anodyne. Given some code or design that you feel bad about, you may be able to find a principle that explains that bad feeling and advises you about how to feel better.
These principles are heuristics. They are common-sense solutions to common problems. They are common-sense disciplines that can help you stay out of trouble. But like any heuristic, they are empirical in nature. They have been observed to work in many cases; but there is no proof that they always work, nor any proof that they should always be followed.
Following the rules on the paint can won’t teach you how to paint.
This is an important point. Principles will not turn a bad programmer into a good programmer. Principles have to be applied with judgement. If they are applied by rote it is just as bad as if they are not applied at all.
Having said that, if you want to paint well, I suggest you learn the rules on the paint can. You may not agree with them all. You may not always apply the ones you do agree with. But you’d better know them. Knowledge of the principles and patterns gives you the justification to decide when and where to apply them. If you don’t know them, your decisions are much more arbitrary.
So how do I get started?
“There is no royal road to Geometry” Euclid once said to a King who wanted the short version. Don’t expect to skim through the papers, or thumb through the books, and come out with any real knowledge. If you want to learn these principles well enough to be able to apply them, then you have to study them. The books are full of coded examples of principles done right and wrong. Work through those examples, and follow the reasoning carefully. This is not easy, but it is rewarding.
Search your own code, and the code of others, for applications and violations of the principles. Determine whether those applications and violations were justified. Improve the designs by applying one or more principles, and see if the result is actually better. If you’d like to study a code base that was written by people who’ve been immersed in these principles for years, then download the source for FitNesse from fitnesse.org.
Conduct or join a discussion group at work. Do brown-bags, lunch-n-learns, reading-groups, etc. People who learn in groups learn much more, and much more quickly, than people who study alone. Never underestimate the power of the other guy’s viewpoint.
By the same token, join a user group with people from different companies. Attend monthly meetings and listen to the speakers, or participate in the discussions. Again, you’ll learn an awful lot that way.
Practice, practice, practice, practice. Be prepared to make lots of mistakes.
And, of course, apply what you’ve learned on the job, and ask your peers to review your work. Pair program with them if at all possible. “As iron sharpens iron, so one man sharpens another.” (Proverbs 27:17)
Comments
Maxim about 3 hours later:
Exactly my feeling on this. You nailed it pretty good.
Principles are not to be applied like a check list or a law. They are their to give you guidelines on how to write good code.
craig about 3 hours later:
The paint can metaphor actually came from Atwood on codinghorror. But I think its misused. What we do is not like painting a wall. Maybe its a bit like painting a portrait. In which case the rules on the paint can aren’t what are important, but more artistic principles like color shading or background light.
In any case, I think we could all learn from Uncle Bob and the SOLID principles. Atwood and Spoelsky did the development community a disservice.
Mike about 3 hours later:
Thanks for saying what everyone else has been trying to say. Based on the crazy strong opinions on both sides of the recent controversy, I unfortunately don’t think we’re all going to agree on anything anytime soon.
Kyle Szklenski about 3 hours later:
I found this line interesting: This is an important point. Principles will not turn a bad programmer into a good programmer. Principles have to be applied with judgement. If they are applied by rote it is just as bad as if they are not applied at all.
I agree that they will not turn a bad programmer into a good programmer, but I think it’s far more likely that if we DO follow them by rote, it will at least make it less likely that we’ll create a piece of garbage product. Could an argument be made for that, in your opinion? I think Chad Myers at least would agree with me on that, if not others.
Having said that, of course, you can still follow the principles by rote and definitely write a piece of garbage. I would just argue that it’s less likely to be as bad as the code of a bad coder if that coder had not followed the principles at all.
Steve Py about 4 hours later:
Nice cool-headed post akin to Clean Code… Reading some of the more recent posts had me wondering if this was the same guy. ;)
Jay Kimble about 21 hours later:
Uncle Bob,
As someone who more or less sits on the other side and who has talked people who adhere more to the direction you are coming from. I read the Atwood, Spoelsky comments about your podcast (I have read numerous articles by others on SOLID… and don’t listen to that many podcasts). Honestly Atwood and Spoelsky said what I had been thinking (a lot harsher than I would have, but nonetheless… I get hung up on the word “ALWAYS” because I know there is ALWAYS an exception).
The whole reaction/flaming that happens after these things turns me off and it makes me reconsider some of the friendships I am beginnning to establish within the Agile community…
Thank you for proving at least to me that some of you really are practical in your application of all this… maybe it will rub off on others… Thank you…
Your comments have made me open to hear your ideas now (and will have to go back into the archives…)
Jay Kimble
—The Dev Theologian
PS. I’m sure somehow I will get flamed for this….
Jay Kimble about 21 hours later:
Uncle Bob,
As someone who more or less sits on the other side and who has talked people who adhere more to the direction you are coming from. I read the Atwood, Spoelsky comments about your podcast (I have read numerous articles by others on SOLID… and don’t listen to that many podcasts). Honestly Atwood and Spoelsky said what I had been thinking (a lot harsher than I would have, but nonetheless… I get hung up on the word “ALWAYS” because I know there is ALWAYS an exception).
The whole reaction/flaming that happens after these things turns me off and it makes me reconsider some of the friendships I am beginnning to establish within the Agile community…
Thank you for proving at least to me that some of you really are practical in your application of all this… maybe it will rub off on others… Thank you…
Your comments have made me open to hear your ideas now (and will have to go back into the archives…)
Jay Kimble
—The Dev Theologian
PS. I’m sure somehow I will get flamed for this….
Arne Claassen 4 days later:
I have to admit that getting started with SOLID, especially if you feel you have to practice all principles at once. While I was practicing every one of the principles independently for years, the one I think was the most powerful in enabling all the others was DIP. I think playing around with one of the numerous Inversion of Control Containers or picking up an open source project that uses one could be one of the most instructive exercises for getting into SOLID.
Philip Schwarz 5 days later:
Uncle Bob,
As you know, in Refactoring, Fowler defines the code smells ofShotgun Surgery (one class that suffers many kinds of changes) and Divergent Change (one change that alters many classes), and says that in order to make it possible, when we make a change, to be able to jump to a single point in the system and make the change, we want to avoid both smells, i.e. we want to arrange things so that ideally, there is a one-to-one-link between common changes and classes.
If we take your definition of the Single Responsibility Principle (SRP) in PPP
A class should have only one reason to change.
and we consider Fowler’s statement that
Divergent Change occurs when one class is commonly changed in different ways for different reasons.
it seems plausible that SRP and Divergent Change are closely related, i.e.:
violations of the SRP lead to the smell of Divergent Change
Divergent Change is the smell resulting from violations of the SRP
More evidence of this relation seems to be provided by Jeff Langr in Clean Code: although he refers readers to the full definition of SRP in PPP, he seems (to me) to concentrate on, and therefore emphasize, the utilisation of SRP as a means to achieve Fowler’s ‘one-to-one link’ (to ease maintenance):
Every sizeable system will contain a large amount of logic and complexity. The primary goal in managing such complexity is to organise it so that a developer knows where to look to find things and need only understand the directly affected complexity at any given time… We want our systems to be composed of many small classes, not a few large ones. Each small class encapsulates a single responsibility, has a single reason to change…
On the other hand, in your chapter on the SRP in PPP, I don’t see this emphasis on using the SRP to achieve Fowler’s one-to-one link to ease maintenance. The emphasis seems to be on using the SRP to avoid the risk of orthogonal responsibilites becoming unnecessarily coupled and resulting in fragile code:
If a class has more than one responsibility, then the responsibilities become coupled. Changes to one responsibility may impair or inhibit the ability of the class to meet the others. This kind of coupling leads to fragile designs that break in unexpected ways when changed.
But if I remember correctly, in some recent podcasts in which you have discussed the SRP, you have said that one of the SRP’s benefits is that the resulting classes are small and have intention-revealing names that make it easy to quickly track down the single class where a change needs to be made.
Uncle Bob: how does the SRP relate to Divergent Change? Is the SRP more about using Separation of Concerns to avoid fragility, or is it more about using it to make it as quick as possible to identify the single place where a change is required, or is it about both?
Philip Schwarz 5 days later:
doh!, in my previous comment I typed the brief smell definitions the wrong way round… here they are in the correct order:
Shotgun Surgery (one change that alters many classes)
Divergent Change (one class that suffers many kinds of changes)
unclebob 7 days later:
Uncle Bob: how does the SRP relate to Divergent Change? Is the SRP more about using Separation of Concerns to avoid fragility, or is it more about using it to make it as quick as possible to identify the single place where a change is required, or is it about both?
Philip, SRP says to keep together things that change for the same reason, and seperate things that change for different reasons. Divergent change occurs when you group together things that change for different reasons. Shotgun surgery happens when you keep apart those things that change for the same reaon. So, SRP is about both Divergent Change and Shotgun Surgery. Failure to follow SRP leads to both symptoms.
Kalpesh 11 days later:
Uncle Bob,
Have you thought of training people in India? I think what India lacks is the kind of refreshing approach & a jumpstart on how to develop things better, from a craftsman like you.
Your thoughts?
Larry 13 days later:
Thanks, Uncle Bob. This seems like excellent guidance.
As an aspiring junior developer who’s trying to wrap his puny brain around these concepts, I’m wondering if you could point me to an open source application that implements the SOLID principles.
Specifically, is there an open source .NET implementation, adhering to the SOLID principles, that could be an example for further study?
Thanks in advance, -Larry
Esko Luontola 13 days later:
Larry, in my current hobby project I’ve tried to follow the SOLID principles and Uncle Bob’s Clean Code book. The project page is athttp://dimdwarf.sourceforge.net and the source code is athttp://github.com/orfjackal/dimdwarf (in Java). The code in that project represents my interpretation of what is clean code. Others will probably have different interpretations.
I’ve noticed that following SRP tends to make the classes quite small (a good thing). For example TaskSchedulerImpl should be the largest class in that project, and it is only 147 SLOC long (217 LOC when counting empty lines and comments), but even that class has about three responsibilities, so I’m going to split it.
bestlijo@yahoo.com 9 months later:
Hi,
I began to understand the benefits of OOP when I came across OCP. Still I am a newbie. Could you please let me know whether there is any C# 3.0 book that explains how to implement SOLID using language features like Generics, Lambda, LINQ, etc?
cheap vps about 1 year later:
You can read about the Solid principles here. This is a paper I wrote nearly a decade ago. It uses a somewhat dated form of UML, and examples are in C++. Also the concepts are severely abbreviated. This is the Cliff Notes. Still, it should give you an initial notion of the names, definitions, and concepts.
There are quite a few papers here that explain the principles in much more detail. Just click on the “Design Principles” topic to see them all. Though I think you’ll find the other topics pretty interesting too.
Finally, the principles are definitively described in two books: Agile Software Development: Principles, Patterns, and Practices, and Agile Principles Patterns, and Practices in C#. You can see descriptions of these bookscheap VPSThanks Lijo