In my last post Beyond Static Typing, I dropped a bomb shell at the end and invented the ideology Design by Runs at Compile Time. But I didn't really dive into my proceived issues with TDD.
There is a laundry list af benefits. But that list doesn't even mention that it helps in making testable code. Did you know that if you want to write tests which validates logic without dependency you build a design different than if you just integrate directly?
Now this does not sound like a bad thing. Especially when coupled all those documenting tests which allow you to understand the desired behavior and throw out the code, rewriting it based on the tests alone. Not that anyone expects that to happen or be useful.
To remove dependency can require layers of abstraction, also a good thing. Abstraction can lead to boilerplate and worse obfuscation. TDD is about design, but it doesn't force or check for good design.
Consider the ideal, you'd define a scenario, given some situation and you are in a state when a request comes in then you would specify the desired outcome. The compiler would figure out how to get those elements to line up and build your program. This is the logic paradigm or machine learning. As programmers we don't get to write code at this level because we write the code to let others work at this level.
This means we have to balance the abstractions we use to expand code reuse (for bug fix and prevention) while maintaining enough info about what the computer is doing in order to find and fix bugs.
This is where TDD puts test readability above code readability incorrectly. Unit tests will help confidence that a refractor won't break behavior but it won't tell you where a bug is when you need to track one down, reading the code, possibly with the help of debuggers, will.
I'm not going claim anyone will be able to write universally readable code across all domains for every situation. But obfuscation of process to achieve testability is detrimental to code verification. I'm reading your code to find those edge cases and inconsistencies you missed, make it easy on me and your future self.
If you want to have well designed code, it falls on you to determine your audience, your domain, and so many more factors about the specific feature you're implementing amongst the existing code base.
Top comments (4)
This looks more like an argument against unit testing than TDD itself. In any case, given the power of modern mocking tools and/or following the Chicago school of TDD, the potentially negative impact that you are talking about can be very small or even non-existent.
I am glad to hear Chicago is winning. I would agree that my arguments have little to do with TDD and apply equally to writing unit tests. This is because I focus mostly on making readable code not comments or tests.
You're balancing pros and cons all day, the TDD approach (or any approach) shouldn't be followed without consideration to what you are giving up.
There are also studies about benefits. There is a nice graph, where they pile inconclusive data on the positive side, I'm not sure effort included the long term maintenance which I am actually asking about.
I think TDD really does have its benefits, but I also think other ways of getting developers to think about their changes would provide similar benefits.
I started reading What is TDD, "You base [the interface] on what you really need at the moment and not on what you think may be needed." But I argue that in both cases you are going to have a preconceived notion of what is needed and the test will reflect that, but it can be nice to actually use that conceived interface first.