December 30, 2017

...Learn TDD with Codemanship

TDD & "Professionalism"

Much talk (and gnashing of teeth) about the link between Test-Driven Development and "professionalism". It probably won't surprise you to learn that I've given this a bit of thought.

To be clear, I'm not in the business of selling TDD to developers and teams. If you don't want to do TDD, don't do it. (If you do want to do TDD, then maybe I can help.)

But let's talk about "professionalism"...

I believe it's "unprofessional" to ship untested code. Let me qualify that: it's not a good thing to ship code that has been added or changed that hasn't been tested since you added or changed it. At the very least, it's a courtesy to your customers. And, at times, their businesses or even their lives may depend on it.

So, maybe my definition of "professionalism" would include the need to test (and re-test) the software every time I want to ship it. That's a start.

Another courtesy we can do for our customers is to not make them wait a long time for important changes to the software. I've seen many, many businesses brought their knees by long delivery cycle times caused by Big Bang release processes. So, perhaps it's "unprofessional" to have long release cycles.

When I draw my imaginary Venn diagram of "Doesn't ship untested code" and "Doesn't make the customer wait for changes", I see that the intersection of those two sets implies "Doesn't take long to test the software". If sufficiently good testing takes weeks, then we're going to have to make the customer wait. If we skimp on the testing, we're going to have to ship untrustworthy code.

There's no magic bullet for rapidly testing (and re-testing) code. The only technique we've found after 70-odd years of writing software is to write programs that automate test execution. And for those tests - of which there could be tens of thousands - to run genuinely fast enough to ensure customers aren't left waiting for too long, they need to be written to run fast. That typically means our tests should mostly have no external dependencies that would slow them down. Sometimes referred to as "unit tests".

So, to avoid shipping broken code, we test it every time. To avoid making the customer wait too long, we test it automatically. And to avoid our automated tests being slow, we write mostly "unit tests" (tests without external dependencies).

None of this mandates TDD. There are other ways. But my line in the sand is that these outcomes are mandated. I will not ship untested code. I will not make my customer wait too long. Therefore I will write many fast-running automated "unit tests".

And this is not a complete picture, of course. Time taken to test (and re-test) the code is one factor in how long my customer might have to wait. And it's a big factor. But there are other factors.

For example, how difficult it becomes to make the changes the customer wants. As the code grows, complexity and entropy can overwhelm us. It's basic physics. As it expands, code can become complicated, difficult to understand, highly interconnected and easy to break.

So I add a third set to my imaginary Venn diagram, "Minimises entropy in the code". In the intersection of all three sets, we have a sweet spot that I might still call "professionalism"; never shipping untested code, not making our customers wait too long, and sustaining that pace of delivery for as long as our customer needs changes by keeping the code "clean".

I achieve those goals by writing fast-running automated "unit tests", and continually refactoring my code to minimise entropy.

Lastly - but by no means leastly - I believe it's "unprofessional" to ship code the customer didn't ask for. Software is expensive to produce. Even very simple features can rack up a total cost of thousands of dollars to deliver in a working end product. I don't make my customers pay for stuff they didn't ask for.

So, a "professional" developer clearly, unambiguously establishes what the customer requires from the code before they write it.

Now my Venn diagram is complete.



ASIDE: In reality, these are fuzzy sets. Some teams ship better-tested code than others. Some teams release more frequently than others, and so have shorter lead times. Some teams write cleaner code than others. Some teams waste less time on unwanted features than others.

So there are degrees of "professionalism" in these respects. And this is before I add the other sets relating to things like ethics and environmental responsibility. It's not a simple binary choice of "professional" or "unprofessional". It's complicated. Personally, I don't think discussions about "professionalism" are very helpful.


Like I said at the start, TDD isn't mandatory. But I do have to wonder, when teams aren't doing TDD, what are they doing to keep themselves in that sweet spot?




Posted 3 weeks, 3 days ago on December 30, 2017