Long, long ago, in February of 2020, Joshua Kerievsky of Industrial Logic fame published a blog post entitled, “A Tale of Two TDDers.” In it, he described a production issue which he said was based on real-world experiences in a real code base. He described two team mates, David and Sally, who took very different approaches to solving the problem.
Although based on a real incident, the story in this blog post is not the actual tale; it’s a contrived version in which David and Sally separately solve the same problem two different ways. David used a test-driven approach and took several hours to refactor a bunch of related code. Sally pushed a quick fix into production and the team immediately added the missing test case(s). Of course, in real life the team solved the problem just once. But Josh wanted to set up a question for readers: “Which programmer would you prefer on your team?”
The post generated quite a bit of enthusiastic discussion. So much, and so enthusiastic, that just 6 days later Josh posted a follow-up post, “One Defect, Two Fixes” to try and clarify. He mentioned the first post had “generated a lot of interesting discussion, some of which bordered on deep misunderstanding.”
Continue reading The Curious Incident of the Magnetic Scotty Dogs in the Night-Time
Test-Driven Development (TDD) is a tool. To get value from a tool, it’s necessary to:
- choose the right tool for the job; and
- use the tool properly.
Circa 2019, there are numerous debates about whether TDD is useful. It seems to me many of the arguments against TDD boil down to one of the following:
- trying to use TDD in situations where it is not the right tool for the job; or
- using TDD improperly.
Choosing the wrong tool or using a tool improperly are certainly things that we fallible humans do from time to time. However, when people have experienced those things with respect to TDD, that isn’t what they say. Instead, they say TDD categorically does not help. It is inconceivable that they could have made a mistake. The tool they used must have been at fault. They are here to warn you against being harmed by that tool.
Continue reading Against TDD
Simulating an ALU in F#
I’m a rank beginner with F#, and I was looking for a fun way to get started. The usual tutorials seemed a little stale. Then it occurred to me that logic gates could be modeled as functions pretty easily. Why not practice F# by writing some functions that mimic the behavior of logic gates?
Continue reading Simulating an ALU in F#
As long as we write tests, what’s the big deal about writing them “first” rather than “last?” Let’s explore that question.
The video looks a lot better on YouTube than it does here. Try https://youtu.be/Bf89rd0o5-0.
When we’re conscientious about writing examples before production code, and we drive all our production code from executable examples, we can enjoy several benefits:
- Helps us remember details and not overlook things
- Helps us avoid over-engineering or going too far with our design
- Helps us keep the design simple
- Provides a safety net for experimenting with different implementations
- Provides a safety net for refactoring
- Gives us frequent positive feedback so we don’t feel beaten down at the end of the day
- Provides executable low-level documentation of everything the application does
- Makes it easier to locate the source of bugs; keeps us out of the debugger for the most part
- Creates a regression test suite as a side-effect of writing the examples that drive the design
- Equally useful for emergent design and up-front design, and for greenfield development as well as enhancements and bug fixes
It’s a commonplace to say there is no “silver bullet,” and everything we do in the software field has to take context into consideration. In fact, this is quite true. TDD is a useful technique to know. To know TDD well, you must understand why and when it is useful, and how to do it correctly. If you apply TDD for the wrong reasons, in the wrong places, or in the wrong way, then it will not yield any value.
Many of the complaints people raise about TDD and about unit testing in general boil down to a misunderstanding or a misapplication of practices. Some complaints, however, are completely valid. You have to make your own professional judgments about such matters. To be equipped to make such judgments, you need to understand how TDD can add value in your work; and when it will not.
Continue reading Looking at TDD through a lean-agile lens
Can contemporary lightweight software development and delivery methods “scale” in large enterprises without appropriate support for the venerable IBM mainframe platform? Thought leaders in the “agile” community seem to think so. For example, this proposed session on code isolation and automated testing for mainframe applications received almost no notice from the review team for the Agile 2015 conference. The two reviewers who noticed the submission seemed not to understand what it was about, or to see any relevance or usefulness in it.
It’s true that some large enterprises don’t have mainframe technology. Apple, Google, Amazon, and a handful of others built their businesses in an era when alternatives to the mainframe were plentiful. Those companies tend to be relatively uninterested in “agile” and “lean” methods, as they have come up with their own ways of doing things, and their financial position doesn’t lead them to believe they need to change. They’re probably right. If they were “dysfunctional” they probably wouldn’t be doing quite so well financially…a minor detail often overlooked by enthusiastic change agents.
However, the majority of larger enterprises have been around for decades. They have used computer technology all those years. The general pattern has been to layer new technologies on top of old rather than to migrate applications. Name a large bank or insurance firm that doesn’t have a significant investment in mainframe systems. Now explain how you would bring agility to those organizations just by setting up a few Scrum teams, applying good technical practices only to the outermost layer of their technology stack, and ignoring technical practices and tooling on the mainframe platform.
Continue reading Bringing TDD and automated testing to the mainframe platform
Can you tell by looking at the unit test cases whether the code’s author wrote the tests first? During a TDD class I taught last week, one of the participants suggested that you can’t tell. Completed code and unit tests would look the same regardless of which had been written first. At the time I didn’t give the comment much thought.
I consider test-driven development (TDD) to be a basic software development technique. I’ve used it in a wide range of circumstances for different types of applications in different domains based on different languages and tools. I coach people in using the technique, I run workshops at conferences on it, and I offer a two-day training class on it.
My only regret is that I didn’t learn about TDD earlier in my career. All those years doing things the hard way…time lost forever. Oh, well.
I use TDD and I like it, but I never try to “convince” anyone that they should use it, or even that it works well. I never suggest that TDD is a “goal” for an individual or for a team. TDD might help you achieve some other goal, but it isn’t a goal in itself. It’s just a technique.
And, let’s face it, nearly all the code in production today, worldwide, was developed without TDD. Nearly all the code under development right now is being developed without TDD. Clearly, programmers can get along without it.
Continue reading The right kind of lazy