DEV Community

loading...

Discussion on: An Introduction to Test-Driven Development

Collapse
stevepryde profile image
Steve Pryde

I've seen a lot of people talk about how good TDD is and they provide lots of contrived examples but personally I have found that not having clear requirements and not having clear inputs and outputs are the norm. I can't remember the last time I worked on anything of even low complexity where I knew how the end result would look ahead of time, enough to write tests. In my experience, almost all programming is exploratory.

That said, I do find TDD more applicable at the function level, rather than the application level. It ties in with the benefits of pure functions since these are easier to test in isolation and it is more common for a pure function to have a set interface defined ahead of time.

But for anything larger than a few thousand lines of code (which I would consider small), the whole process of building the application involves exploration around which interface works best. This includes the boundary between user and application as well as boundaries between various subsystems. It would be counter productive to write the tests first and then be constrained to stick with what could well be a sub-optimal design. My applications typically take the form of building a proof of concept, then iterating over the design until it feels right (efficient, less code, low on resources, easy to maintain) and then optimising where it makes sense. During that process the interface will almost always change. I feel like TDD requires a crystal ball, and the one constant in the software industry is changing requirements.

Sorry I realise this comes across as arguing against TDD but really I just want to hear how people would apply TDD at the application level. How often do you write software where the design and interface is fully known at the start and doesn't change?

As I said if I'm writing a function or a small subsystem that seems critical and has a clear interface, then yes I'll write a unit test. Most of the time everything I write is open to be refactored, and the reliability is crafted into the app design in other ways (good data structures, types etc). I write more unit tests for things that are designed to be reused a lot. But I still write them after the fact. Because that is after the interface has been worked out via trial and error.