It’s a really simple question, but one that’s hard to answer. If you start by saying "I take a story from the board" then let me stop you right there. I'm not interested in the process, I'm interested in what happens between after the choice of what to do and before the done bit.
Maybe you’re answer involves the tools you use? You might begin with "I write in Emacs; let me tell you about my setup...". Nope. Not interested in that. Glad it works for you, but it doesn't really tell me about how you really construct software.
Maybe your answer involves the syntactic rules you use? You write software with spaces, not tabs and all your statements are semi-colon terminated and it’s either K&R or the highway? Yawn. That’s not what I'm after.
How do you actually build your software; what happens between the brain and the keyboard?
After pushing a bit more, I ask again and I sometimes get responses like this:
- All the significant code I write is peer-reviewed.
- I try to write unit-tests when I can.
- Most of my bug fixes contain a regression test.
What do they have in common? They are all weak statements that don’t really tell me (and most importantly YOU) anything about the way you develop software. They probably tell me that your heart is in the right place, but it doesn't show any commitment.
Every single one of these statements has an escape hatch. It's far too easy to ignore these values. You can almost imagine the excuses now. This is just a small commit, it doesn't need a review, let alone a unit test. This bug I just fixed, it’s so tiny, so inconsequential that it doesn't need a regression test for it.
I'm not going to try to argue that you should never use an escape hatch, but to word things so generally is simply inviting temptation.
Trying to strengthen those practices
So what happens if we strengthen our statements a bit more? Let’s take the first half-fledged principle and try to improve it a little.
- All code will be peer-reviewed
Peer reviewing all code. That's undoubtedly a good thing, and it certainly doesn't have an escape hatch. Or does it? The problem with this statement is it’s far too vague. What is the code being reviewed for and to what criteria? Perhaps it’s obvious to you, but what about the others on the team. Often you’ll ask around and get different answers from members of the team.
Is it a formatting check? I hope not, because you’ll have automated that and stopped arguing about it a long time ago. Right?
Is it checking for obvious mistakes? Maybe. That’s definitely a good start, but it’s still a bit woolly. What's obvious to you probably isn't so obvious to someone else on the team.
I'd suggest a strong set of criteria creates a tighter statement. For example:
It doesn't really matter to me (though it should matter to you) what the criteria is, the most important thing is that it’s strong enough for a disciplined code review.
So what good are fully fledged practices?
OK, so you've agreed on a couple of practices. What’s that actually going to do for you? Once you've got a disciplined way of developing software you can start to reflect on how things are working for you.
You've got a set of fully fledged practices. These practices are hopefully challenging you to think much more carefully about the way you construct software. Perhaps you've committed to getting all code peer-reviewed? Chances are you've got some doubters on your team? How can you demonstrate these practices are working?
Look at your practices; how do they translate into outcomes? Perhaps you want a code review before every push because you are trying to unpick a mess of legacy code? Maybe you’re trying to roll out test-driven development because your integration tests take hours to run? For any outcome, you can probably think of something you can compare that will help you know whether it's working or not. Perhaps you could measure whether your code coverage increases? Maybe you could take a look at the cyclomatic complexity of the code? How many times did the build break this week? You don't even need automated measures, you could simply ask opinions.
Put together, practices and retrospectives give you a base to reflect on the way you develop software and try to find ways to improve upon it. Donald Knuth did this. For the entire history of the Tex program, Knuth kept a bug journal recording the how's and why's of everything that went wrong. I've never seen a quote suggesting so, but I'd imagine it's hard not to become a better developer by reflecting on what works and what doesn't.
Putting it all together
Every team dislikes something about their software. Maybe it's harder to change than it was a year ago? Maybe the compilation time takes forever because of all the coupling? Maybe someone else wrote it and it just plain sucks? Flip the problems around and you've got goals to achieve. You want the ability to change code quickly and easily. You want a 10 minute build. You want simple and maintainable code. Now you have measurable outcomes!
This is where deliberate practices come into play. Now you've chosen some practices you can start to see how much difference they make on day-to-day development. I'd suggest that most practices probably need a good few months before they've truly bedded in. It's worth reflecting on practices more often though, perhaps you can see benefits sooner?
There is no such thing as a one-size-fits-all approach to software development. The idea of best practice is a complete myth; it's about what works for your project, your team and associated human factors and your work environment. By being deliberate about the practices you use then you can attempt to find what works best for you.
This is obviously a grossly simplified approach. The real world is messier and there are constraints all over the place, but I still think that being deliberate about the way we create software is an important step in the continuing journey to become a better software developer
So, how do you write software?