I basically want to get an idea of the percentage of people who think it's reasonable to use the Single Responsibility Principle in real-world code and how many actually do. In Podcast #38 Joel talks about how useless this OOP principle is the real world; and further that this demonstrates how people like Uncle Bob have likely not written non-trivial systems.
I've personally written or played a big role in a few software projects but have only now come across this pattern in my young career. I love the sound of this principle and would really like to start using it. I found Joel's argument in the podcast quite weak (as did others if you continue on to read the blog comments here). But, is there any truth in it?
What does the community think?
I have had some experience applying SOLID principles and my experience has been mainly good. I also heard the podcast and it sounds like neither Jeff nor Joel has tried any of the things they're talking about long enough to really asses the benefits. The main argument against is as usually "you write more code". If I look at what I do I write 10 maybe 20% more code (usually interface definitions) but because everything is highly decoupled it's far more maintainable. I hardly ever have situations where changes in one part of my application break other parts. So the 20% extra code i have to maintain pays for itself.
Jeff also missed the point on code quality. He doesnt see code quality as a great benefit for the customer. And he's right, the customer doesn't care. The customer does care about having new features implemented quickly and that's where code quality comes in. I've found that the investment of keeping the quality of code as high as possible has always paid itself back within a few months. High quality = low maintenance.
I do agree with them that like anything you have to be pragmatic about these things. If you need to deliver something then go ahead and do it fast and dirty. But clean up afterwards.
I'm working on a project that does lots of different, horribly complex things, in a framework that is supposed to be easily extensible by others.
At first, classes were large and did multiple things. In order to change those behaviors, you had to extend those classes. The methods were all virtual and didn't change the object's state, so it was pretty easy to do this.
But as the system grew, it became more clear that the framework was going to end up with a series of monolithic objects, each with looooong inheritance chains. This also resulted in unexpected dependencies--an abstract method taking a collection of class X to produce object Y defined in a base class dictated that EVERYBODY had to do it this way, even when it made no sense for half of the inheritance tree. This also resulted in massive classes that required tens of unit tests to get the code coverage over 80%, and the complexity was such that you weren't sure if you covered everything correctly. It was obvious this design would cause the framework to be very rigid and inflexible.
So we redesigned everything along SRP lines. You'd have your interface, a base class and, possibly, one or more implementation classes. Each one was composed of different objects which performed key functions of the overall process. If you wanted to change one part, you didn't override a method, you would produce another object that extended the requisite interface/base class and performed its job differently. SRP was even taken down into the arguments and return values of the class methods. For those parts of the system that needed to be flexible, rather than pass collections of X class that are used to produce Y objects, a class was created to encapsulate the process of production of Y objects. Components in the system would then pass these producers around, combine them with others (the responsibility of the producers), and eventually use them to produce Y. This allowed for different types of producers to be created, all of which could be treated exactly the same, even though they did vastly different things. The move also drastically reduced each class' code base and made them MUCH easier to test.
I would say that, as a new developer, it is VERY HARD to break everything down to this level. You almost have to write a big ball of mud, understand how it works, then redesign it as several different components, each taking responsibility for a part of the whole.
I haven't read or listened to Joel's comments so can't comment on those specifically.
I think you have to look at the single responsibility principle in terms of a goal, rather than a strict requirement. As with many things in software development, there are ideals that should be strived for but, unless your code has no monetary benefit or cost, you have to be pragmatic in serving your customer's needs.
In practice, it's very hard to get true SRP in OO situations. Consider a class that exists in a complicated system. It probably has only one business-oriented responsibility (such as printing a report), but it will have many other responsibilities internally that violate pure SRP ideals, such as logging and exception handling. If you change your logging mechanism significantly, you'll probably need to change the calls your printing class makes.
This is why AOP was conceived. Using it you don't have to change anything but the logging classes to change logging.
It's good to strive for business-oriented SRP for obvious reasons, but for sufficiently complicated systems you'll never get true SRP in OOP. AOP, sure, but not OOP.
I have no idea if that's what Joel's reasoning is, but that's how I would approach the idea.
The biggest problem with some of the large number of programming theories out there is that they focus on suggesting that good attributes in code, are in fact good attributes for code. They're right because they are intrinsically right, and thus not particularly useful.
Yes, code should be well written, and yes, things shouldn't be horribly repeated, and yes, changes shouldn't cause weird breaks in unexpected places. But, at the end of the day, really simple, really consistent code that expresses the solution in a simple, easily understandable way is worth far more than a big complex system that meets some rigorous principles. As an industry we tend to take good ideas way too far, creating masses of unnecessary complexity in the quest for the "right" solution, not the best one.
Paul.
I think the biggest benefits to being a disciplined OO developer and adhering to the SRP whenever possible are ease of testability and maintenance so I would say SRP is a good goal for any system that is going to be tested/maintained (basically, anything except a throwaway system).
I think SOLID principles sometimes don't comply with natural/business logic that one usually applies when designing classes. Robert C. Martin brought up an example of Rectange and Square classes (Square shouldn't be a descendant of Rectangle).
http://www.hanselminutes.com/default.aspx?showID=163
I'm not sure that it was regarding SRP but the idea is the same. SOLID principles may lead to counterintuitive decisions and it's hard to get though this barrier.
To me 'guidelines' is more appropriate name than 'principles'.
In general I agree with the SOLID principles, but you also have to take them into context. If you are writing a Proof Of Concept, then the SOLID principles are less applicable.
On the other hand if you are developing a product with a life that will span years, then you better look carefully at the SOLID principles and apply them. Otherwise it's going to cost the company tons of money in productivity.
In regards to Joel and his comments, he has a valid point. Sometimes the product needs to ship or the company fails. That's just the way it is.
As a developer it's your job to ship the product, but just because there is a tight deadline doesn't mean you go with a poor architecture. Choices like do you use datasets or business entities is a simple decision and both have similar implementation efforts, but in the long term the new feature development and maintenance between the two is drastic.
I think that it should be possible to write a simple one-line main responsibility for all classes. The word "and" in this one-liner is usually not a good sign. The single responsibility then often boils down to selecting the proper abstraction.
GUI near classes tend to reflect GUI and have the single responsibility of "being gui for XXXX". Coward's solution..
来源:https://stackoverflow.com/questions/488684/using-the-single-responsibility-principle-in-the-real-world