Making sense of design patterns, best practices, etc - When to break the rules13 Feb 2009
I read a couple of posts the other day from Jeff Attwod (The Ferengi Programmer) and Rob Connery (Patterns, Purists, and Sinkholes) that were a little more thought provoking than average. They're both talking about how to make sense of all of the 'best practice' advice thats out there, how to know when you're allowed to break the rules, and the various troubles that you can get into on both sides of that coin. Certainly you can quickly get lost when using the design pattern hammer for every problem and often you just have to 'get things done, NOW!'. But obviously those best practices and principles (like Bob Martin's SOLID principles), have a ton of value and really can't be ignored by any professional developer. So how do you know when to break the rules?
I really liked the analogy given by a commenter (James) on Rob's article, drawing on his experience as an electrician - specifically as an electrician's apprentice (I can relate - that's my background). The point that I took home was - rules can only get you so far, butit's the rules and guidlines that the 'newbies' learn in their first few years, combined with the experiences lived through in those years that give people the knowledge and widsom to deal with things that the rules don't cover or when it's 'safe' to compromise rule X in order to achieve the goal at hand.
So, think twice when faced with the common choice between doing it right or doing it quick. Are you really qualified to decide when to cut corners?
I'm not ashamed to admit that I love to watch Mike Holmes' 'Holmes on Homes' show on the Home and Garden network. His motto is: "If you're going to do it - do it right the first time". His show is all about how much effort and waste and heartache happens when contractors cut corners (too much). His genuine passion for doing things right really resonates with me.
I stumbled across another quote the other day that seems to fit in this context. John Wooden is a famous college basketball coach of the 60's and 70's, and in his time was well known for a few sage sayings. "Be quick, but don't hurry" really captures the great balance we struggle with in software development - the need to deliver value (working software) quickly, but with sufficient quality that we won't regret later. "Doing it right doesn't" doesn't have to mean "Doing it slow", all the time. It certainly shouldn't be an excuse for spinning your wheels or not making good progress on your projects.
As a manager of software developers, I would WAY rather deal with the problem of "it's taking too long" rather than "the quality sucks and our customers are coming after us with pitchforks and flaming torches!". I'm sure everyone would agree that rushing, cutting corners, and dealing with the resulting pain will take longer to get to the end of the job than taking that bit of extra time to do it 'the right way'. But how do you deal with the crushing realities of hard deadlines and customer commitments (made by you or others)? What if you just don't have the time to do it the way you want to?
The challenge of course is trying to figure out where the line is - how far down the path of 'doing it right' do we need to go in this case? Do I really need to do those unit tests? How much of the code is worth getting reviewed? How much should be done by pairs of devs? All of it? really? Do we need an interface in this case? Is a dependency injection framework overkill for this? Will it take the new folks too long to understand the system if I do it that way? How much regression testing should we do? Do we need usabilty testing?
I don't have answers for those questions because obviously 'it depends'. I can say that I very much default to the answer that you should really really try to 'do it right the first time', and only make decisions to cut those corners in the light of the experience and wisdom of the real journeymen on your team. No rule can be a replacement for the life lessons learned by those with the battle-scars, but those rules are a darned good starting place for all of the conversations.
In conclusion, I'd like to leave you with another set of rules. 🙂 🙂 These ones are by Eric S Raymond, and can be found here: http://catb.org/~esr/writings/taoup/html/ch01s06.html
They are the distilled wisdom of many of the developers who wrote the Unix operating system - some of the real 'elders' and journeymen of our industry. (appeals to authority can be useful sometimes! :) )
- Rule of Modularity: Write simple parts connected by clean interfaces.
- Rule of Clarity: Clarity is better than cleverness.
- Rule of Composition: Design programs to be connected to other programs.
- Rule of Separation: Separate policy from mechanism; separate interfaces from engines.
- Rule of Simplicity: Design for simplicity; add complexity only where you must.
- Rule of Parsimony: Write a big program only when it is clear by demonstration that nothing else will do.
- Rule of Transparency: Design for visibility to make inspection and debugging easier.
- Rule of Robustness: Robustness is the child of transparency and simplicity.
- Rule of Representation: Fold knowledge into data so program logic can be stupid and robust.
- Rule of Least Surprise: In interface design, always do the least surprising thing.
- Rule of Silence: When a program has nothing surprising to say, it should say nothing.
- Rule of Repair: When you must fail, fail noisily and as soon as possible.
- Rule of Economy: Programmer time is expensive; conserve it in preference to machine time.
- Rule of Generation: Avoid hand-hacking; write programs to write programs when you can.
- Rule of Optimization: Prototype before polishing. Get it working before you optimize it.
- Rule of Diversity: Distrust all claims for “one true way”.
- Rule of Extensibility: Design for the future, because it will be here sooner than you think.