Software development ruled by well-formed 'best practices' can cloud your view of the bigger picture. Sometimes, you need to view the project standing in the client's shoes.
Unfortunately, the balance of nature decrees that a super-abundance of dreams is paid for by a growing potential for nightmares.
— Peter Ustinov
I’ve been writing this column for five years now, and in that time I’ve looked at many things that get put forth as "best practices" in our profession. These range from writing good comments in your source code to using a version control system to test-driven development to code reviews -- to name just a few. But there’s a paradox inherent in all of these things. By focusing on individual best practices, it’s entirely possible to miss the big picture. This month, I want to take one giant step backwards and advocate for a very simple best practice: Think about what you’re doing.
Why Are You Here?
It’s not all that likely that you’re getting paid to write code. Oh, there may be developers out there in that enviable position, but at least in my case, my customers don’t pay me to write code: They pay me to solve business problems. To the people signing the checks, it’s fairly irrelevant whether I solve those problems by writing the smartest, slickest C# code you’ve ever seen or by sprinkling magic pixie dust on their servers. As long as the goals of the contract are met on time and within budget, the customers stay happy.
Now granted, the customers are generally hiring me because they believe that I’m going to write code to solve their problems (if I did have a supply of magic pixie dust, I’d most likely raise my hourly rate considerably). But the important thing to understand is that to the customer, the code is a means, not an end in itself. That is, they want code to solve some business problem. Assuming that it does so, and in a way that meets their other needs (for example, that it not cost astronomically more than budgeted), then the internal features of the code, and the process that I used to create it, are largely irrelevant to them.
Who’s The Boss?
"But wait!" I can already hear the shouts from some quarters of my audience. "By doing x I am responding directly to the customer’s business need y." There are a lot of things you can substitute in place of the variables in that sentence: Unit tests make the code more maintainable, code reviews make it more reliable, writing in C# makes it more portable, and so on. You can no doubt come up with dozens more variations on this theme as well as I can.
There are two problems with this argument. The first is that it ignores the cost of the proposed practice. More fully developed, it would read "By doing x at a cost of $z I am responding directly to the customer’s business need y." There is, after all, no such thing as a free lunch. By explicitly placing the costs in the equation, you make it possible to judge both sides of the argument, and to measure the cost-benefit ratio of the proposed practice.
That makes clear the more major problem with the argument that you should always do x, whatever it is. Who died and left you in charge? Unless it’s your money, you are not the one to be making the tradeoffs between speed of delivery, size of budget, and such intangibles as maintainability and reliability. As the technical expert, you can and should make the tradeoffs clear to the customer. But ultimately, it’s the person who holds the purse strings who gets to say, "You know, we’re only going to use this system for the next three months. I need it in two weeks, and I’m willing to take a few risks to get there. So I understand you’re cutting corners to deliver."
You might choose to go looking for a higher class of customer in such a situation, but you can’t reasonably and ethically go into a massive development effort with all the "best practices" bells and whistles when you’ve explicitly been told to do things in a quick-and-dirty way.
No Best Practices
Software testing consultant James Bach has written eloquently about our industry’s propensity to seize upon individual tools and techniques as being universally applicable in his blog entry,"No Best Practices" at http://blackbox.cs.fit.edu/blog/james/archives/000187.html. His core argument, which I find compelling, is simple:
"There are no best practices. By this I mean there is no practice that is better than all other possible practices, regardless of the context. In other words, no matter what the practice and how valuable it may be in one context, I can destroy it by altering things about the situation surrounding the practice."
Do go and read the whole entry; James develops this thought at length in an entertaining and thoughtful manner. The important thing to note is that best practices are contextual. You may have some practice that has served you very well in many situations in the past, but that doesn’t give you the right to declare it universally applicable. As a smart developer who wants to do the best thing for the customer, you need to figure out whether it’s still a best practice for this particular job.
There’s a powerful lesson here. Far too many developers seek to impress clients by walking in with a pre-packaged set of tools and methodologies that they can lay on the table to validate themselves with. "We are a great bunch of developers," they say, "because we do x and y and z on all of our projects, and we will do them on your project too. Trust us, we know what’s best for you." If the practices are a match for the customer’s needs, that’s fine. But if they’re not a match, then what? At best, you lose the sale. At worst, you’ve got a severe mismatch between what ought to be done and what does get done, and you end up with a project that wastes money or doesn’t deliver what the customer is expecting. The tail starts trying to wag the dog. Large consulting shops can get away with intimidating small customers who have the misfortune to hire them in this fashion. Smaller consulting shops can just get themselves fired.
What’s the alternative? Listen first instead of talking. You wouldn’t, I hope, presume that you understand the entire business domain that you’re writing code for without talking to the customer. So extend that attitude to talking about the tradeoffs. You may be inordinately fond of test-driven development. Fine -- present it to them as "here’s a technique I’ve found useful in the past, because it helps keep the code clean when requirements change on long-running projects." Perhaps they’ll come back and tell you that sounds great. But if they express reservations because this is a short-term contract, you need to be prepared to explore the topic.
And Think Again
Finally, you need to realize that by its nature software development tends not to be static. It’s very tough for us to predict up front how long something will take or how much it will cost. Similarly, many of our customers have a hard time expressing their goals in terms of quality, cost, maintainability, and other metrics. You need to be prepared to periodically reexamine the tradeoffs you’ve made on a project, and if necessary reengineer things to better serve your customers. Perhaps that quick and dirty project is going into long-term production now, and it’s time to take a serious look at adding a testing infrastructure. Conversely, an older project may be nearing the end of its lifetime, and it could be time to just patch a few final bugs while abandoning a previous high level of process. Don’t be afraid to question your own previous assumptions.
The good developer has a variety of tools and techniques at their disposal. The great developer has the wisdom to know when to use them.
Want to read more of Mike’s work? Visit his Larkware site for daily updates at www.larkware.com.
Mike Gunderloy, MCSE, MCSD, MCDBA, is a former MCP columnist and the author of numerous development books.