Single Responsibility Principle is about Implementation
I've often seen arguments made against person.save() being a violation of the Single Responsibility Principle and it's bothered me for a while. The argument goes something like "the Person is responsible for its own behaviour AND its persistence, therefore it has two responsibilities."
I've finally put my finger on why I don't agree with this and I'm wondering what the rest of you have to say about this.
To me, SRP is about implementation, not interface.
In other words, if a Person object has a reference to some persister and delegates the save() message to it, then the Person is not implementing persistence, and therefore does not implement that responsibility. Person would only change if its behaviour changed. Changes to the persistence layer might affect the Person, but not its clients. Loose coupling is preserved.
This may be obvious to many, but for me this has been a bit of a revelation. When recognizing principles violations, we need to keep in mind why these principles came into being. They exist to guide us towards flexible designs in which changes are localized as much as possible.
!commentForm
As a Rails developer, I wonder whether Rails' ActiveRecord[?] violates SRP. When I write a Rails model, I'm not delegating persistance to another object, I'm inheriting it.
I didn't find it obvious! I think it's a bit of a revelation to me, too, and I appreciate it being pointed out!
Anybody else surprised? Or was this common knowledge?
Anybody else surprised? Or was this common knowledge?
That's an interesting twist on what I'm talking about here. If you agree with the assertion that delegation does not violate SRP, then you may think that implementation inheritance does not violate it either. I have to think about that.
I will say that AR and ERB both provide MANY opportunities for and even encourage violations of OO thinking. They don't FORCE you to write poor OO designs, but they make it very easy by doing things like encouraging exposition of properties. And the tests generated for controllers encourage the one test per method anti-pattern that BDD has begun to led us back away from. Simply changing the names from things like "test_index" to "test_index_should_redirect_to_list" would begin to encourage smaller, more focused tests.
That said, I've seen a couple of people write about problems they've seen in Rails and seen DHH respond saying thinks like (paraphrasing) "hey - these things are there for your convenience, nobody is holding a gun to your head and telling you how to use them". He's absolutely right, however there's enough crappy code in the world that it would be nice to see tools that encourage better designs.
I will say that AR and ERB both provide MANY opportunities for and even encourage violations of OO thinking. They don't FORCE you to write poor OO designs, but they make it very easy by doing things like encouraging exposition of properties. And the tests generated for controllers encourage the one test per method anti-pattern that BDD has begun to led us back away from. Simply changing the names from things like "test_index" to "test_index_should_redirect_to_list" would begin to encourage smaller, more focused tests.
That said, I've seen a couple of people write about problems they've seen in Rails and seen DHH respond saying thinks like (paraphrasing) "hey - these things are there for your convenience, nobody is holding a gun to your head and telling you how to use them". He's absolutely right, however there's enough crappy code in the world that it would be nice to see tools that encourage better designs.
I think it's about both, really. You can violate it at either level and different things happen. Of the two ways, though, I agree that implementation violations are worse.
Michael - what are the effects you see of violating it on interface?
Increased coupling, wide and incohesive interface, and the same problem that the Interface Segregation Principle is aimed at. -- Michael Feathers
Increased coupling, wide and incohesive interface, and the same problem that the Interface Segregation Principle is aimed at. -- Michael Feathers
Add Child Page to SrpIsAboutImplementation