It’s a wonderful rule, but one doesn’t always have the luxury of following it.
Consider a horribly complex legacy application without any regression test suite, where all the original developers have long gone, and documentation is outdated. The application is retired, put into “maintenance mode” they say. But, inevitably, a new bug is reported, and the customer is important enough to dust off the source code and provide them with a fix. What is Junior Developer to do?
Modifying the behavior of the existing application is dangerous because Junior doesn’t understand all the ramifications of what he is changing. So Junior hacks a solution on top of an already complex ball of spaghetti, making sure to alter the minimal amount of existing logic as possible. If this requires duplicating some code that already lies somewhere in the abyss, I argue that it is a necessary evil.
“It’s true that “Do One Thing” becomes larger and larger as you move up the chain, more nebulous, more difficult to define. The higher up you get (OS level?), the more the One Thing becomes a vision statement rather than a concrete definition you can point to. But I’d still say it’s true; I think we can somewhat reliably point to the “Do One Thing” of OS X, Windows Vista, Ubuntu.”
Or Plan9. They took “Do One Thing” to a whole new level. I once read that adding features to the Plan9 code-base actually made it shrink.
I wonder how that relates to the ‘defects in programming languages’ discussion?
I’d be interested to hear your comments on Kim’s suggestions to use dependency injection to solve the issue adequately. Since it was a Java problem, Uncle Bob’s idea to use Ruby to solve it seems… out of place.
Well, we started with OAOO, then DRY, then Single Point of Truth. Actually, Curly predates the DRY acronym.
Oh, wait… we started a long time before OAOO. We spoke in the negative about “multiple maintenance points” and before that…
We’ll find a dozen ways to say it, but the Java people will decide that they need one more so that they can maintain their terminology ghetto, and we’ll have at least a million and one.
Yeah, I’m mostly joking. The point is that we do keep restating the same thing for decades, and saying in more ways and more clever ways doesn’t seem to cause people to actually do it. The interesting question is how can we help people do it? Some of us are insane (in the Einstein-ian mode) and keep trying the same thing by stating it over and over. Other than following the principle ourselves and teaching it to others, what can we do?
I’ve been perusing your blog for about an hour and have found some useful stuff and some not-so-useful stuff. Your “Curly’s Law” post is extremely useful. Your “Branding” and “Office Tour” posting are not.
My friendly advice is to leave “branding” and “tours” to the marketing hacks and give us some more coding pointers.
Good article. Nothing I didn’t know before, but as I was reading through it I immediately thought about a current program I’m writing that I got sloppy on and just copy-pasted a loop (with minor modifications) rather than turning it into a proper function. Lo and behold, I go back and look at the code after two weeks and another guy has come through and fixed a bug in one of the loops but not the other (guess he just missed it). So I converted it into a proper function.
The only problem with the proposed solution is that partial classes didn’t show up until .Net 2.0, so if you’re working in an older version of the runtime (because, say, you’re working with a web app built in ASP.Net 1.1 and, say, upgrading it is a nightmare) you either stick all the methods in one class or you get gnarly with your class structure to compartmentalize it.
As far as editing the data and reporting layers of Employee separate from Employee’s business logic, it depends. Is the data layer considered to be the database and the stored procedures you use to have your code talk to it or is it code to talk to the database? If it’s code to talk to the database, why separate it from the Employee class? That sort of monotonic relationship doesn’t earn you anything: the Employee class is worthless without its data layer and the data interface layer is worthless without the Employee class, so have Employee encapsulate the data interface layer.
Even with the GoF’s patternalia on speed-dial, it’s easy to mangle the implementation of something like MVC - lord knows I’ve done it enough in my time.
There is nothing wrong with the employee class. Don’t listen to this example or else you could end with a system with object bloat.
DRY works here if calculatepay only exists in the employee class and not in the front end, in the RDMS layer, or is repeated in another class.
Employee could be a base class with calculatepay being an overridable method. Other class inherit and may calculate pay differently by implementing there own version of calculatepay, or they use base employee method.
You can have an object that has multiple methods that update that objects state. Its a guideline not an absolute rule. If you folow this rule to the letter, you will have lots of little classes in your application and your code will be hard to follow.
I don’t agree with the Single Responsibility Principle but that’s just my opinion. I agree that all business logic for employee’s should be located in one location of code and not spread throughout the codebase.
If you go back into histroy and re-read the literature regarding Coupling and Cohesion (or even normalisation and denormalisation) you are half way there. Look cross cutting concerns as well as covered AOP.
All of this has been known and covered for decades.