4 ms·
The problem with many TDD critiques is that they offer no alternative. The original presentation: https://www.youtube.com/watch?v=DQBf6li1hww https://www.youtu
by apo 9y ago
The problem with many TDD critiques is that they offer no alternative. The original presentation:
https://www.youtube.com/watch?v=DQBf6li1hww https://www.youtube.com/watch?v=DQBf6li1hww
is a case in point. Presenter takes what he believes to be TDD's four main points, some of them strawmen, and mocks them. He does make some good points, but here's the problem: he offers no alternative.
If you're not writing tests as you go, that you run before every commit (or before you move onto the next thing), then what is your standard for putting code into a production repository?
- k__ 9y agoYou're right, I also don't know good alternatives. I wrote my first big API with many tests, hundreds of them. Then the requirements changed and all of them failed. People worked for weeks to get the tests passing again. So just writing many tests up front in a new project doesn't seem to help anyone. Also, I went from feature to bugfix sprints. First I implemented some features, then they got tested by non-devs, then I fixed all the bugs. Often this was faster than the whole tests up front stuff with refinement of tests afterwards. I also saw that >90% of my bugs came from the dynamic nature of my language of choice (JS). So I could imagine, that this feature->bugfix->feature->bugfix cycles could be greatly shortened (especially the bugfix parts) by using a typed language instead.
- humanrebar 9y agoIn most statically typed languages, the bugfixing (usually) takes longer because you need to do many more things each time you refactor. An enterprise Java application doesn't typically pass around the equivalent of a JS object. It passes around Users, Admins, and Guests. But then some features in Admins need to be added to Users without affecting Guests. But Guests inherit from Users, so you have to go back and restructure the type hierarchy. But it turns out that User is a Hibernate entity, so you have to make sure you don't change your DB schema on accident. Using a static language does help with some bugs (where it effectively serves as a compile-time test suite), but it can also increase coupling a lot. It's not easy to quantify that tradeoff in abstract. I'd be wary of people overselling aggressive compiler checks leading to productivity boosts.
- hacker_9 9y agoSomewhat disagree - you still have 'types' in JS, but the runtime just sees maps instead of concrete types. The concept is still there, but you won't get an error until runtime if you invalidate the models. At least with static languages the problems are made clear up front and prevent compilation. There are other limitations though, such as not being able to treat static types as a hashset at runtime, which can be good or bad thing depending on what camp you're in.
- humanrebar 9y agoThe 'types' in JS don't typically include implementation implications as much as they do in more strongly typed languages. If your algorithm is looping through a set of widgets, you just need a container and things that look like widgets. In Java, C++, etc., you often are pulling in a type with baked-in assumptions about logging, DB access, etc.
- bunderbunder 9y agoI'm beginning to suspect that, in the context of these debates, "most static languages" is a roundabout way of saying, "Java", or other static languages with a similarly anemic type system. Also it's a roundabout way of describing the particular way that Java code tends to be structured. In one that has better support for generics (i.e., reification, contravariance and covariance) and some form of mixin, you generally shouldn't have that much trouble adding behaviors to an entire class of types without having to modify any of them. This is the fabled open/closed principle that is oft lauded and rarely practiced. To take it a step further, if you're using interface polymorphism and decorators to build your types instead of relying on subclasses, you won't be able to paint yourself into the corner you describe in the first place. The problem is, of course, that a language like Java that doesn't let you add new behaviors for types without either modifying the original source file or resorting to some Gang of Four awfulness, will tend to punish people for writing cleanly-structured code like that.
- humanrebar 9y ago> ...is a roundabout way of saying, "Java", or other static languages with a similarly anemic type system... I agree. In my experience, it's how the median developer writes code, though. Even in more flexible languages they'll reach for type hierarchies and abstract base classes. I've seen people create these things in languages like Lua and Javascript that don't really need them. I think TDD-like approaches make the case for other approaches more clear, for what it's worth.
- tdbgamer 9y agoI am generally for TDD, but I don't think APIs really need heavy code coverage. That said, testing the input/output directly doesn't work well because now a single change the output data (adding a field to the JSON for example) will call tons of tests to fail. I usually use or create some JSON serialization/deserialization classes and use those to generate fake data and ensure that the API returns 200 responses. That way if I add a field to the JSON objects, my tests are unaffected and will generate the new fields in the tests. So I may do something like this (Python-ish): new_user = User.generate_user() response = api.post('/users', new_user.serialize()) assert response.status_code == 200 response = api.get('/users') users_json = json.loads(response) users = {} for user in users_json: users.add(User.unserialize(user)) assert new_user in users That way changes to the User JSON will not impact tests and I still have some basic sanity checks. Hope that helps.
- k__ 9y agoNice, thanks :) Do you have any good resources on testing? Books/articles etc.? I often have the feeling the only people who write about this stuff are the die hard TDD gurus.
- tdbgamer 9y agoNo problem! I did read Clean Code by Robert Martin. He's definitely in the "die hard TDD guru" category, but there are still useful examples to be extracted from the book. Besides that, I mainly learned a lot of testing tricks in the wild, reading through Github projects. My learning process now-a-days is mostly: 1. Discover a really cool trick or concept I didn't know existed in a Github project. 2. Research the hell out of it. 3. Try to use it in some personal example project.
- michaelmcmillan 9y agoThat has to be one of the worst presentations I've seen. Is it ironic?
- hwayne 9y agoIt's a bit of a tongue in cheek and a bit of a roast. Eric Smith does TDD consulting.
- contravariant 9y ago>If you're not writing tests as you go, that you run before every commit (or before you move onto the next thing), then what is your standard for putting code into a production repository? It seems to me that that would be the same standard that you would otherwise try to write a test for. Now writing a test isn't necessarily a bad idea, but I think it's important to realise that the test isn't the standard itself, but is itself an implementation.