12 ms·
I find TDD is great when you have an interface to some code defined and are changing the behaviour of what happens when interacting with that interface. You can
by orobinson 5y ago
I find TDD is great when you have an interface to some code defined and are changing the behaviour of what happens when interacting with that interface. You can then add some tests to the existing test suite for the interface, watch them fail, then get to work implementing and be content that you’re done when all the tests are passing.
However, if you’re still developing the interface definition itself, TDD just wastes time when it transpires the interface you envisaged and wrote tests for doesn’t quite match up with the implementation as you write it.
- Jenk 5y agoThat's missed the beat a bit.. you are supposed to let the tests drive that design out, not big-design upfront and then fill out tests.
- tarkin2 5y agoChanging and newly-discovered requirements, rather than tests, drive your code.
- Jenk 5y agoDisagree. You are developing to a set of requirements at anyone time. What emerges from (A)TDD is the implementation of those requirements and the design therein.
- tarkin2 5y agoWhen those requirements change, and they can very, very quickly, you need to rewrite your tests--fine if you don't mind spending that time.
- AnimalMuppet 5y agoHopefully you only need to change some of your tests. When your requirements change, and you change your code, you have two questions. First, did my code change do what is needed for the requirements change? You modify tests (or write new ones) to answer that. Second, did I break anything in the process? The remaining tests answer that.
- monocasa 5y agoI've found the flow true for some environments with extremely well defined structures for doing any work (classic backend API servers being one example), but it's definitely not true for all envs. A lot of envs have you spiking so much on just how to even approach the feature that writing tests up front is wasteful overhead.
- cgrealy 5y agoIf you are spiking, then you should be throwing away that code. Don't productionise prototypes.
- monocasa 5y agoDon't just throw untested prototypes in production, but you don't gain anything in a lot of envs by throwing away a prototype completely. You're likely to introduce additional issues by rewriting it for no reason.
- AnimalMuppet 5y agoWell, if a spike is going to become production, when it does, then write the tests (along with all the other cleanup that needs to happen if your going to turn prototype code into production).
- monocasa 5y agoYes, but that model is distinctly not TDD. You came to a design, then backfilled tests.
- AnimalMuppet 5y agoOnly if you keep the design of the spike when you convert it to production. But that should be part of the "production-izing" process, right? You convert it to a solid design instead of a quick-and-dirty hack?
- BurningFrog 5y agoI don't understand the alternative, unless it is to not have tests?
- pydry 5y agoThe dirty secret of our industry is that a lot of the time, we don't. It's frequently scorned but Im not so sure it's always the worst idea in the world. I've built shoddy hacked together systems that made customers happy and wasted months building heavily tested well structured code doing something nobody wants. Well engineered tests take a lot of time to build - sometimes 2x the code itself. If you've built the wrong thing youve paid 3x the cost to figure it out before going back to the drawing board. I'm a big believer in retrofitting tests once code has proven itself useful.
- Jenk 5y agoCode changes when requirements change. I don't think anyone should be surprised by that.
- AnimalMuppet 5y agoBut, given the changing and newly-discovered requirements, letting tests drive the design of the implementing code can still be surprisingly effective. Why? Because if I find it hard to write the test, it's telling me that I'm likely to find it hard to write non-test code that uses the class/module/subsystem/whatever. It forces you to use the interface to your code. If it's hard to use, that's telling you to consider changing the design.
- sidlls 5y agoThis assumes the test isn’t making it hard to use unnecessarily.
- squeaky-clean 5y agoRequirements drive your tests, which drive your code.
- sidlls 5y agoOne doesn’t design around tests, unless the test code is the design spec. In which case something has gone horribly wrong in the requirements and analysis for the project.
- cgrealy 5y ago> One doesn’t design around tests No design gets to the coding stage until someone has answered "how will this be tested?" So, yeah, you should absolutely be designing around tests.
- sidlls 5y ago"how will this be tested?" can be answered without writing a single line of test code or defining what the test suite will look like. The design spec documents determine what the implementation should look like, and the tests should verify the implementation works as desired, not drive its structure. I don't want the implementation to be chopped up and scattered everywhere in the name of "testability" because someone decided that a tool should dictate the architecture of the code. That leads to unreadable, hard-to-maintain, inefficient code that, with a tight coupling to the test suite that makes both them of fragile in the presence of changes in the other. For very little gain.
- cgrealy 5y ago> That leads to unreadable, hard-to-maintain, inefficient code that, with a tight coupling to the test suite that makes both them of fragile in the presence of changes in the other. For very little gain. I completely disagree with everything above. Literally, take the sentence and make almost every word the opposite.
- drran 5y ago
- sockpuppet69 5y ago
- eric-hu 5y agoMy experience agrees with the GP, orobinson. I used to work at a company that wanted us to TDD everything. Everyone working there knew this from the time of interview, so it’s not like any of us were unwilling to give it a shot. When it came to adding a feature to a Rails app, the interface is pretty well defined, it’s going to serve up HTML and js, it’s got to fit on the existing structure of the page or conform to a design. Adjacent parts of our company were working on a Heroku clone PaaS, and I got some time on a team building an auto scaler service to spin up and down other services. We didn’t know how our service would kill and start other services. Tests were changing as much as production code while we worked on that. A lot of our work was spiking to see how our service fit into the ecosystem of other services.
- Jenk 5y ago> I used to work at a company that wanted us to TDD everything. Dogma is the bain of everyone :) I will never advocate "100% TDD." It is a tool like any other that has its place and, more importantly, doesn't fit everywhere. Though I will freely admit I do encourage people to use it more than what I have seen to be the typical amount. > When it came to adding a feature to a Rails app, the interface is pretty well defined, it’s going to serve up HTML and js, it’s got to fit on the existing structure of the page or conform to a design. It's very unlikely I'd use TDD on that. Boilerplate/plumbing is something I rarely use/advocate TDD for - it's the "clever" stuff you want to cover. The stuff that is following rules outside of the code itself. > Tests were changing as much as production code while we worked on that. Absolutely nothing wrong with that, imo.
- thibauts 5y agoExactly this. Encoding business requirements or expected output of a complex algorithm by writing tests before code can make some sense. Writing tests for something that has no defined shape yet doesn’t.
- agonz253 5y agoJohn Ousterhout has a different take on this in "A Philosophy of Software Design": The problem with test-driven development is that it focuses attention on getting specific features working, rather than finding the best design. This is tactical [as opposed to strategic] programming pure and simple, with all of its disadvantages. Test-driven development is too incremental: at any point in time, it’s tempting to just hack in the next feature to make the next test pass. There’s no obvious time to design, so it’s easy to end up with a mess. One place where it makes sense to write the tests first is when fixing bugs. Before fixing a bug, write a unit test that fails because of the bug. Then fix the bug and make sure that the unit test now passes. This is the best way to make sure you really have fixed the bug. If you fix the bug before writing the test, it’s possible that the new unit test doesn’t actually trigger the bug, in which case it won’t tell you whether you really fixed the problem.
- BurningFrog 5y ago> * There’s no obvious time to design* Design time is the refactoring after your tests pass. That's when you can move your code around with confidence, since you can lean on your tests.
- pydry 5y agoThis works provided you didnt encode your design mistakes in the tests themselves. Then youve just doubled the cost of fixing that mistake. It's hard to overstate how common this is.
- Jtsummers 5y ago> This works provided you didnt encode your design mistakes in the tests themselves. Then youve just doubled the cost of fixing that mistake. If your design mistakes are in your code and your tests, they'll also likely be in your mental model and your documentation (if it exists). At which point you what? Throw it all away and start over? In extreme cases, but in others you do partial rewrites and refactors. Address the issues. But not having tests because they may encode your design mistakes is as foolish as not having documentation or comments because they may also encode your design mistakes. In a few years, you'll have a blob of code that, in the best case, is perfectly readable and comprehensible. But, in reality, is likely to fail at communicating the overall design intent and requirements. And so what if it doubles the cost of fixing the mistake? You made a mistake and it had to be fixed anyways. In the end, I've never found tests to cost more than they saved. A lack of tests has always led to higher development costs (primarily as measured in time to delivery). Regressions are ludicrously common without tests, which eats away at your time (and therefore adds to your costs) very quickly.
- efsavage 5y ago> However, if you’re still developing the interface definition itself, TDD just wastes time when it transpires the interface you envisaged and wrote tests for doesn’t quite match up with the implementation as you write it. This sounds like TDD is WAI in this case. If the tests break because of the implementation of the interface, either the tests were wrong (likely because the interface was poorly or incompletely described) or the requirements changed (and broken tests means you had decent coverage). Catching this with a simple test run during initial development is far cheaper than debugging against someone else's expectations in the future.