Sufficient Design
Sufficient Design means Damned Good Design.
Posted by Uncle Bob on Wednesday, April 28, 2010
@JoshuaKerievsky wrote a blog entitled “Sufficient Design”.
Josh makes this point:
‘Yet some programmers argue that the software design quality of every last piece of code ought to be as high as possible. “Produce clean code or you are not a software craftsman!”’
He goes on to say:
“Yet ultimately the craftsmanship advice fails to consider simple economics: If you take the time to craft code of little or moderate value to users, you’re wasting time and money.”
Now this sounds like heresy, and I can imagine that software craftsmanship supporters (like me) are ready to storm the halls of Industrial Logic and string the blighter up by his toenails!
But hold on there craftsmen, don’t get the pitchforks out yet. Look at the scenario that Josh describes. It’s quite revealing.
Josh’s example of “not being a craftsman” is his niggling worry over a function that returns a string but in one derivative case ought to return a void.
Horrors! Horrors! He left a bit of evolved cruft in the design! Revoke his craftsman license and sick the dogs on him!
Ah, but wait. He also says that he spent a half-day trying to refactor this into a better shape but eventually had to give up.
The fool! The nincompoop! The anti-craftsman! A pox on him and all his ilk!
OK, enough hyperbole. It seems to me that Josh was behaving exactly as a craftsman should. He was worrying about exactly the kinds of things a craftsman ought to worry about. He was making the kinds of pragmatic decisions a craftsman ought to make. He was not leaving a huge mess in the system and rushing on to the next feature to implement. Instead he was taking care of his code. The fact that he put so much energy, time, and thought into such a small issue as an inconsistent return type speaks volumes for Josh’s integrity as a software craftsman.
So, as far as Josh Kerievsky is concerned “Sufficient Design” is “Pretty Damned Good Design”.
Look, all our software will have little tiny warts. There’s no such thing as a perfect system. Craftsmen like Josh work hard to keep those warts as small as possible, and to sequester them into parts of the system where they can do the least harm.
So the only aspect of Josh’s post that I disagree with is his contention that the “craftsman” message is one of unrelenting perfection. Craftsmen are first and foremost pragmatists. They seek very high quality code; but they are not so consumed with perfection that they make foolish economic tradeoffs.
Comments
Corey Furman 14 minutes later:
Isn’t the best software craftsman the one who is more concerned with delivering on what the customer wants than the one who is enamored with beautiful architecture? Note, I don’t think – deny, in fact – that the two are mutually exclusive.
Rebecca Wirfs-Brock 27 minutes later:
It is when little warts add up that we end up with a pile of junk. So taking the time to consider our options is important. Even if we don’t end up changing our code. I think there is a big difference between delivering value, and delivering value that we programmers can live with and enhance with ease.
Unlike other craftsmen and women, we have to live with our creations on an ongoing basis.
James Brechtel about 2 hours later:
Corey, the customer wants and needs something that can be maintained as well as function as they desire.
Stephen Seymour about 2 hours later:
I am fortunate to have worked as a craftsman in two fields: carpentry (10 years) and software (10 years). I can say that the main point made by Joshua, and as always Uncle Bob, rings true.
I worked as both a rough carpenter and as a finish carpenter, and the degree of “perfection” I had to choose differed greatly depending on the task at hand. One particular parallel between the two fields works well here, and I’ve though about this parallel many times in the past.
I remember first learning how to quickly hang sheetrock, and due to my nature of wanting to do things “perfectly” I first tried to cut the sheetrock to fit the space it was going into with barely any room to spare. I actually did okay at this, but all it takes is one time for the piece to be too big to fit, followed by your hanging partner rolling his eyes and saying, “Hey, don’t try to make it perfect. Measure it and cut it back a quarter inch or so and everything will come out better that way.” My partner was right, of course, and this is one of the secrets to hanging sheetrock. Not only does the job get done a hell of a lot sooner, but it does indeed come out better in the end because then the team isn’t thrashing back and forth with the same piece(s) of sheetrock.
The same applies, analogously, with software. A true craftsman knows where to back off from “perfection” (quotes included because there really is no such thing in software, or anywhere else for that matter). She’ll know where to let things slip a little bit in the interest of the goal: getting a product/feature to ship with no defects. She’ll also know when to slip some flexibility into the imperfection so that code can be changed later, without any impact to users, in order to wring some more value out of it.
Perfection in software implicitly means one is accepting of imperfection—the key is in the wisdom used to know where to accept the perfectly placed imperfection. Based upon experience, I think this same approach is likely true in all aspects of life. If you’re reaching for perfection, you better well be accepting of imperfection. :)
Keith about 3 hours later:
Craftsmen deal with imperfections all the time! little jagged edges of the parts that come together to create the whole.
A real craftsman knows exactly how these jaggys will effect the overall design. Some will add up and cause grief. Some will never be seen are and be perfectly hidden with no consequence. A master craftsman will know exactly how imperfections will impact a design.
Hank Roark about 3 hours later:
In the place I work our founder once said “I will never put my name on a product that does not have in it the best that is in me.”
It seems as a craftsman this is a worthy goal…for you, your customers, and the people that have to work on your product after you.
Tetsuo about 6 hours later:
What about tests?
Do they get into account when evaluating these ‘economic tradeoffs’?
I mean, may a craftsman not write tests he finds too costly to implement, and return little value?
Or “if you don’t TDD all your production code you are like a doctor who doesn’t wash his hands”?
Olle Kullberg about 10 hours later:
“if you don’t TDD all your production code you are like a doctor who doesn’t wash his hands”?
In some situations, to not deliver code when business screams for it is like a doctor who forgets his glasses inside a patient after stitching him up.
If you have an A-level error in production, there is simply no time to test C-level functionality. Write the A-level and B-level tests, ship it and go to your boss to ask for more time to level out the details.
A-level errors are not supposed to go into production, but they do since skill is as rare today as it has ever been before. An ohh yes, you can have 100% test coverage and still get A-level errors in production, this I guarantee. No quantitative metric will save you.
Personally I think unit testing is overrated, and clean code is underrated.
Corey Furman about 11 hours later:
>>James Brechtel said: Corey, the customer wants and needs something that can be maintained as well as function as they desire.
No, not really. The customer only “wants” maintainable code to the extent that they believe that it will cost them less later. I have never had a consumer of my applications ask me for my thoughts on how well the system was constructed. Clean, well constructed, change-resistant code is for our benefit. We shoot for these goals because we care about our craft, our art. We do code reviews, look at the metrics, pay attention to the smells because it is by these practices we read the heuristics of the code.
No one suggested, and I doubt that anyone within the sound of this article would believe, that testing is dispensible. The point that I was making is that customers pay for features with completions with high fidelity. This is a tenet of Lean. How we get there and stay there is up to us.
Steve Py about 14 hours later:
Depending on the situation, customers won’t give a rat’s ass about maintainability or extensibility. Sure they’ve got plans for the future but the fact is they want to get something out early to actually see how much interest there is in a product. In their eyes, even if it costs more later to extend, it’s better to “choose” to spend more on the important stuff once they’re bringing in income, than it is to spend “probably less” before the product ever makes it out the door.
Most software is “soft”. It is not engineering. It’s not like building a bridge where it pays to think and design ahead because making more bridges or tearing down and replacing bridges is expensive, and you can’t just add extra lanes when you need them. It’s not even really like writing a book or producing a movie where once it’s done, it’s “done” and never to be touched again or fans will scream. (Starwars remastered, anyone?) [Hans shot firstdagnabit] Software can, and should be continuously improved.
Typically when a project starts, a certain (and often low) percentage of the requirements are firm enough to support a foundation of investment. We have a rough idea how they’ll evolve, and they’re features the customers will definitely use. The rest may be fleshed out as the project evolves, but when the remainder has got lots of “hmms”, and “ahs” coming from the customer/BA rough it in. There’s no point investing much time crafting it, and especially crafting stuff to use it as a foundation / example for other features… Mind you any truly important features should have been built in by now. (Heaven forbid you’re stuck with BDUF)
As for TDD/Unit Tests: Test coverage of uncrafted features will likely be sparse, but the golden rule is that as those features evolve, whether through change requests or bug reports, unit tests are the first thing added for the improvement. The feature has earned some value, so craft away. The difference is that it has proved its worth and is doing its part to bring in real money. Before it was released it was “hmm” and “ah”. Chances are it’s going to be crafted in a different direction than what you might have had in mind prior to release.
My $0.02 (Free in Australia!)
Fizz about 14 hours later:
A Craftsman will see the mark in the wood and ensure that it is hidden, most great craftsman are good at hideing problems and mistakes in a way that ensure the end consumer never sees them i.e. Pragmatic
When craftsman reviews the work of another craftsman they will see “errors” that the consumer will not notice and therefore not frett about.
If you have to write bad code (if you work in the real world you will have too) hide it, encapsulate it in a class or method, just make sure it works and the user will not see side effects.
The end user will not see the code so will not care.
John Sonmez about 16 hours later:
I agree with you 100%.
Consider this other possibility. Sometimes there is code we will write and it won’t be maintained. Sometimes economic factors related to time directly affect our success.
I created a Venn diagram that shows best practices and which ones help up build software, and which ones help us maintain software in my post about the subject from the economic angle here:http://simpleprogrammer.com/2010/04/17/when-doing-the-right-thing-is-wrong/
Of course the better you get at writing “Clean Code” the smaller the cost is for writing clean code. The trade-offs eventually become less, because the cost is close to free.
Richard L. Burton III about 16 hours later:
Programming is an absolute art form, with some transparent guidelines.
In regards to this topic, there are two types of engineers.
1. Those that blindly focus on code quality with disregard to business value.
2. Those that are trying to find a balance between being a true Craftsman with a strong focus of business value.
The latter one is always deemed evil by the former. I believe this is because of insecurities or fear of being labeled a noobie or mocked. In the ‘real world’, the latter is preferred because they are willing to accept a certain amount of crap with a focus on keeping the important parts well designed.
Abstraction is key to being able to isolate the crap code behind a Craftsman’s interface :)
Code problems are easier to fix than architectural and design problems.
Richard L. Burton III Co-Founder of SmartCode
Olle Kullberg about 18 hours later:
What about bad requirements?
When I think of the systems I have seen, many creepy, obscure lines of code has originated from creepy, obscure requirements. The “business is always right” attitude has a fundamental flaw, since there are some not-so-skilled people in business too.
Me: “Could we just not do this, or at least make it into some kind of general rule?” Business: “Just do it!” (Nike style)
There you are with your one-off requirement, and no matter how you twist and turn it will never be clean code.
What I am trying to say is that we are all doomed :-)
Vijay Ratnagiri about 19 hours later:
I was going to start with something along the lines of what Mr. Burton was saying. But now, let me expand a little on that.
Programming is indeed an art from. I always likened it to linguistic writing. Anyone can write a crude article or a not so well organized essay. But there are always elegant ways of writing up the same information and it takes and artist to do that.
The debate seems to be about whether or not the time spent in making the code elegant is necessary.
I’ll concede that the coding as writing analogy is applicable only when we regard the code being written is meant to be read, understood and maintained by someone else. If this is not the case then the value of clean code is negligible and astute business person would and should recognize this.
Now, what I think seems to be the misconception here is the assumption that a good craftsman would write inelegant code and then spend time refactoring it to make it elegant.
However, I contend that the art of writing elegant code, once learnt, will become second nature so much so that most of the time, the first draft of this sort of a craftsman will be pretty elegant to begin with and in many cases the elegance will be sufficient.
Mart 1 day later:
“So the only aspect of Josh’s post that I disagree with is his contention that the “craftsman” message is one of unrelenting perfection.”
I wish I understood this six years ago (and could accept it today). Going from “sufficient” to “zero flaws” requires an enormous amount of mental and psychic energy, more than it repays.
Jonathan Rasmusson 4 days later:
Good post Uncle Bob.
Absolutely craftsmen are pragmatists first and foremost. Sure they shoot for perfection – but they know when to stop and they know they’ll never get there.
Thx for sharing.
Esko Luontola 4 days later:
Also when you don’t right away know that how some code could be improved or implemented, it may be best to write a TODO comment and leave the code unchanged, and come back to it later. I have many times gotten an inspiration within a day or two, after which changing the code is easy.
pradeep 16 days later:
The problem with being pragmatic is that you do not realize when you have become too lax with your quality standards. People start by ignoring C-level errors and in a couple of years, they start to think that no testing is necessary since it can be maintained later.
I always ask my teammates to fix any issue that they are able to find. There will always be enough issues that we will have no clue anyways.