π§π»ββοΈ Putting Test-Driven Development under Trial: Could the Critics Be Right? π³ Part 1
Let's embark on an investigative journey where the practice of TDD is put on trial. The prosecuting attorney presents the arguments against TDD, raising doubts about its effectiveness.
π π’ Newsletter Update Time π’
π Milestones Reached π
π Hey, developers! The biggest news of the week is that my first free Workshop, a 4-hour deep-dive into TDD basics and OOP misconceptions, took place last Saturday - and it was amazing. Stay connected because I will repeat some of those for sure at the beginning of 2024. Also, welcome 2 new subscribers that allow us to reach 46 members!!
π In case you missed it: two weeks ago, I talked about documentation in Agile, to try to remove some fog from some misconceptions about it! If you haven't already, make sure to take a read at it here and let me know what you think! πͺ
π₯ Premium updates π₯
π₯ Personal coaching services seats available: one-on-one guidance from me, Dan the dev, an experienced Agile developer who will help you develop the skills and knowledge you need to succeed in 12 1-hour sessions.
Take advantage of our 2-lessons Money Guarantee policy: enjoy the first two out of twelve sessions and if you are not happy with them, I will refund the entire amount. Discover more π here.
Thanks again for being a part of our journey! π
π£ Just a friendly reminder, folks! In our welcome email, you received a sweet discount that's valid for any of my products and services. Don't forget to take advantage of it - it doesnβt expire! π
π§π»ββοΈ Putting Test-Driven Development under Trial: Could the Critics Be Right? π³ Part 1
Introduction
Few practices in software development have sparked as much debate and controversy as test-driven development (TDD). Advocates think it's a panacea for writing clean, manageable code, while critics argue it's a time-consuming and unneeded burden. Today, we're putting TDD to the trial. Imagine a courtroom in which the prosecution throws charges and the defense rallies to demonstrate that those charges are wrong.
I collected all the critics I found online about TDD, and we will give all those critics the benefit of the doubt, trying to go very deep into understanding the cons that they typically suggest and to support their ideas - then, we will also try to demystify it. In the end, I will share with you what thoughts I had after all this work.
So grab your gavels and robes, for we're about to embark on the TDD trial of the century! ποΈπ©βπ»π¨βπ»
Test-Driven Development on Trial π
Setting up the stage for the trial, as a (very bad) prosecution attorney, I was able to collect the 8 most common criticisms that people throw against TDD:
Time-Consuming
Too much overhead
Focus on Testing, Not Design
Inflexibility
Over-testing
Difficult to Learn
False Sense of Security
Not Suitable for All Projects
We will deep dive into each of those, in a ping pong challenge between prosecution and defense of TDD - the first 4 points will be in this week's newsletter, and then the 2nd part will come next week.
Letβs see which criticism is concrete and which is not, and how concrete and real those problems are raised by skeptics.
TDD is time-consuming
Prosecution
Ladies and gentlemen of the jury, it's essential to acknowledge that Test-Driven Development consumes an exorbitant amount of time. The reason is that TDD necessitates developers to compose tests before crafting the actual code, and this supplementary step serves only to extend the already arduous development timeline. TDD's insistence on creating tests prior to developing the actual code is an irksome and time-consuming ritual.
To elucidate further, allow me to emphasize the problems with TDD's initial phase, where the developer is burdened with the task of devising test cases. This detracts significantly from the rapid inception of the code, leading to longer project timelines. In fact, the documentation-intensive nature of TDD often exacerbates the already onerous demands of software development, resulting in an unwarranted delay in reaching the final product.
What we want to point out and make very clear here, your honor, is that TDD increase time for development, making the life a lot harder - and while we cannot prove that there might be a gain of time on the long run, we can definitely see we are slower in the immediate - and that is not good for business.
Defense
Honorable people of the jury, we vehemently refute this accusation: claiming that Test-Driven Development is time-consuming is something inaccurate that starts from some bad habits about learning and applying a new practice.
What we want to say is that for any new practices we want to learn and apply, we cannot start applying them on the job - we should invest time in learning via exercises and training, starting from trivia software exercises and then moving to more complex ones. If you start doing TDD and try to apply it while still learning and not being confident enough, of course, you will be a lot slower than usual. But this is an unsafe way of approaching new methodologies or technologies on the job, and itβs also disrespectful of the money the company pays us.
The reference here is professional sport: if you want to be able to apply good techniques during the match, where points are at stake and there is pressure, you must work hard first to excel in those practices during training, where you have no pressure and all the time needed for learning. Developing a feature for software that is (supposed to) make money, itβs our performance moment, itβs like we are in the match - there is pressure due to money and time, and that is normal, so you cannot use a practice/methodology/technology you are not confident enough, and you should build that confidence before via training.
And remember: training is a developer's responsibility, not the companyβs: βcompany doesnβt give me time for trainingβ is just an excuse, the responsibility for the quality of our work and our learning is ourselves.
TDD causes too much overhead
Prosecution
The next problematic point we want to highlight about TDD is that the testing code creates an overhead that complicates projects. One of the more troublesome aspects of TDD, as our esteemed critics contend, is the unwarranted overhead it introduces to software projects. This weighty accusation concerns the task of maintaining the testing code alongside the production code, which, according to the prosecution's perspective, considerably exacerbates the complexities of project management.
Now, please indulge me as we delve into the nitty-gritty of this allegation. Our critics astutely point out that TDD's unwavering emphasis on creating tests in tandem with the production code results in an inherent conundrum. As developers, we find ourselves in the unenviable position of maintaining two parallel sets of code - the production code itself and the code responsible for testing it.
This approach adds layers of intricacy to the project. This situation isn't merely an issue of maintaining an additional set of files; it involves ensuring that the testing code is in harmony with the production code. In our experience, such meticulous synchronization introduces confusion and can escalate into an administrative nightmare.
The stark reality is that the act of maintaining these test codes often leads to a decline in overall project manageability. We contend that this complication is just one of many signs that TDD is a practice far too cumbersome for today's fast-paced software development landscape.
Defense
First of all, your honor, I want to point out that is not merely about TDD, itβs a general attack on having automated tests in our codebase - which is even worse, probably, but also easier to defend.
The moment you start wondering how to make software development better and to have a better life at work daily, you start realizing that there is typically a lot of time wasted in unplanned work: bugs, defects, issues in production, and any other kind of activities that you cannot plan because itβs unexpected. Agile, XP, and Lean all agree that we should strive to reduce the time we spend in unplanned work to the minimum possible (around 20% of the time for high-performance teams, according to the research in the βAccelerateβ book, against 27% invested by low-performance teams).
Writing and maintaining an automated test suite is a minimal investment that pays off by enhancing code quality, reducing defects, and increasing the maintainability of the code itself - meaning it reduces unplanned work in the future. TDD can reduce that even more, to be honest, because it ensures a couple of additional points:
we are sure all the code is covered by tests without any additional effort
you will write only the minimum code required for your current needs, meaning the YAGNI principle will be respected and you will have to maintain the less code possible
big complex problems/features will not keep you stuck because you donβt need to overthink the entire design beforehand - you can just understand how to start and have a generic understanding, and tests will drive you to the solution
So we can say with absolute certainty that having an automated tests suite is very very helpful, and an investment that is worth doing - and TDD raises even more of that value.
TDD focuses on testing, not design
Prosecution
I'd like to draw your attention to yet another critical viewpoint, one that questions whether Test-Driven Development (TDD) leads us down a path of good design, as its proponents claim. Our esteemed critics argue that TDD's singular emphasis on testing overshadows the importance of promoting well-crafted software, and they propose that it often steers developers toward writing code primarily to fulfill test cases, rather than to foster sound design principles.
This critique, ladies and gentlemen, underscores a fundamental issue with TDD. The practice may encourage a myopic focus on satisfying test conditions rather than nurturing the kind of software that stands the test of time. Instead of nurturing the growth of elegant, maintainable, and efficient code, TDD, according to our critics, may drive developers to prioritize passing tests at the expense of the software's overall quality.
These criticisms, as unpalatable as they may be to some, should give us pause. We are left to ponder whether TDD is truly a beacon of good design or, as our critics assert, a practice that might inadvertently pave the way for poorly designed software. The prosecution contends that this is a matter we cannot afford to take lightly and warrants a closer examination of TDD's value in contemporary software development.
Defense
There are two questions we want to start our response from, to demonstrate that this accusation is completely without basis and concreteness.
The first question is: are you sure that it is bad to focus primarily on passing the tests? As the Agile Manifesto states, the first measure of progress is βworking softwareβ - and passing those tests means our software is working, so it is for sure something to celebrate and be happy about.
But the second question will add light also on the first one: are you sure that TDD emphasizes passing tests instead of good design? I think that the name here is probably causing some misunderstanding.
Let me explain: TDD means Test-Driven Development. Development is the process where we add functionalities to a software, and while we do that we also decide the design of the software to achieve that purpose. TDD means that you develop software by letting the tests drive this process, and TDD has a specific target that is stated in the very first page of Kent Beckβs book: βclean code that worksβ.
βClean codeβ means code with a good design, intended as a design that makes it easy to read and maintain the code. βThat worksβ means code that does what we expect from it. Tests we use to drive the process allow us to achieve both: if they are green, our code is working - and thanks to those tests, we can easily refactor our code to improve its design being sure that the behavior is still the same.
The focus of TDD is not only on testing, is βclean code that worksβ and the test-driven process is the best way known today to achieve that result - it also allows us to split the problem: we write the tests and make it green, focusing on βcode that worksβ - then, we refactor focusing on βclean codeβ.
TDD doesnβt take care itself of it: itβs up to you to be sure you know what the software is supposed to do to write useful tests, and itβs also up to you to know the best design and refactor practices to apply - once you know those, TDD is the best tool to be sure you achieve them both.
TDD is not flexible
Prosecution
Now, your honor, please let us now cast our gaze upon the notion of inflexibility. As opponents of TDD, we want to present an argument that has struck at the very heart of its methodology, contending that the rigid nature of this approach, which insists on writing tests before any code, may stifle creativity and innovation.
The prosecution asserts that this critique is a striking indictment of TDD's potential drawbacks. We argue that the demand for tests to precede coding creates an environment where creativity and exploration take a back seat, as it's not conducive to imaginative problem-solving or the pursuit of alternative, innovative solutions.
In our ongoing scrutiny of TDD, the notion of inflexibility is indeed a substantial concern. It prompts us to consider whether, in its zeal to ensure testing, TDD might inadvertently suppress the very creativity and out-of-the-box thinking that often leads to groundbreaking software solutions. The prosecution submits that these allegations, while disputed by proponents, are nonetheless serious and warrant careful consideration as we weigh the merits of TDD in the realm of software development.
Defense
Letting aside the attack about TDD being focused on testing, that we already responded to in the previous point, we want to totally refuse the prosecution accusing TDD of being inflexible.
In this case, we can start our responding taking inspiration directly from Kent Beckβs TDD book itself: in the βMastering TDDβ chapter, the author respond to some hypothetical questions that may arise when trying TDD. Among all the incredible insights of this chapter, one of the questions is: βHow much feedback do you need?β.
The question is about feedback because tests in TDD are described as a way to have a short feedback loop about our decision, so this question can actually be rephrased to βHow many tests should I write?β. And the answer is: it depends!
With a very clear example, Beck shows us how the same problem caused him to write 6 tests, while another developer wrote 65. Quoting the book:
You will have to decide, from experience and reflection, about how many tests you want to write.
TDD's view of testing is pragmatic: tests are a means to an end, the end being βcode in which we have great confidenceβ. Taking this idea to the limit, it means that if our knowledge of the implementation gives us confidence even without a test, then we might even decide to not write a test at all.
In the end, this means that the more you know the problem you are solving with the code, the less number of tests you will feel the need to feel safe - and as a consequence, you will write fewer tests. On the reverse, when you are facing a problem for the first time, you will probably prefer to have a lot more tests to feel safe.
And that sounds like a very flexible approach to me!
Next week, we will discuss the last 4 points, and then I will share my take and conclusions, as always, and also the most important resources I know to understand more about the impact of this practice.
Until next time, happy coding! π€π©βπ»π¨βπ»