Hacker Read top | best | new | newcomments | leaders | about | bookmarklet login

>Unfortunately most software is just not well defined up front.

This is exactly how I feel about TDD, but it always feels like you're not supposed to say it. Even in environments where features are described, planned, designed, refined, written as ACs, and then developed, there are still almost always pivots made or holes filled in mid-implementation. I feel like TDD is not for the vast majority of software in practice - it seems more like something useful for highly specialist contexts with extremely well defined objective requirements that are made by, for, and under engineers, not business partners or consumers.



view as:

I forget which famous Unix personality the quote / story comes from, but it amounts to "The perfect program is the one you write after you finish the first version, throw it in the garbage, and then handle in the rewrite all the things you didn't know that you didn't know."

That rings true to my experience, and TDD doesn't add much to that process.


Well except for the second step where you aim precisely.

Exactly. I write my programs/systems a few times. Each time I discard the previous version and start from scratch. I end up writing code that's easy to test and easy to swap parts if needed. I also know what TDD brings to the table. On top of that I have over 15 years of professional experience... so I usually know how to write software that complies with what we usually call "good code", so TDD offers me zero help.

For more junior engineers, I think TDD can help, but once you "master" TDD, you can throw it out of the window: "clean code" will come out naturally without having to write tests first.


I was taken by TDD for about six months, years ago. I always felt that I was never good at it because edge cases I hadn’t thought of came up or the interface wasn’t actually the best/cleanest/most maintainable way to write that code.

But it got me thinking about testing while writing the class instead of shoehorning a class into a test just before the PR went up. That’s what I think my takeaway was. To this day I think about not just how clean/maintainable the code is, but also how testable the code is while I am writing it. It really helps keep monkeypatching and mocking down.


I'm almost positive Joe Armstrong has some version of this quote. I couldn't find it, though.


Ah, but it's the _third_ version, because of Second System Effect. So, really, plan to throw two away. https://en.wikipedia.org/wiki/Second-system_effect

If you know you're throwing two away, you won't even really start in earnest until the third one.

This is one of the better points I have ever seen made, bravo. So true.

Whoever said that specific quote, it is a paraphrase of a point that Alan Kay has been making since the late 1970s. His speeches, in which he argued in favor of SmallTalk and dynamic program, make the point over and over again. I believe he said almost exactly the words you are quoting.

That was my paraphrase. From fuzzy memory, don't think it was Alan Kay, but I'm sure the approach is common with that crowd.

The only other clue I have is that it was apparently someone who was super productive and wrote a ton of the early common Unix tools.


Screenwriters encourage a "vomit draft" -- A draft that is not supposed to be good but just needs to exist to get all the necessary parts on the page. Then a writer can choose to either fix or rewrite, but having a complete presentation of the story is an important first step.

I've advocated the same for early projects or new features. Dump something bad and flawed and inefficient, but which still accomplishes what you want to accomplish. Do it as fast as possible. This is your vomit draft.

I strongly believe that the amount a team could learn from this would be invaluable and would speed up the development process, even if every single line of code had to be scrapped and rebuilt from scratch.


I'm using "vomit draft" from now on.

This is how I write documents - start with the table of contents and fill in the blanks until the document is done.

Isn't there some law as well that states that successful software projects start with a working prototype, and software designed from the ground up is destined to fail?


The idea of the vomit draft works for narrative text because it's aimed at human consumers and humans are very adaptable when it comes to accepting input. We can absorb a whole bunch of incoherent, inconsistent content and still find the parts in it which make sense, do useful and interesting things.

An executing program is a lot less forgiving, for obvious and unavoidable reasons.

What TDD brings to the table when you are building a throwaway version is that it helps to identify and deal with the things which are pure implementation errors (failure to handle missing inputs, format problems, regression failures and incompatibilities between different functional requirements). In some cases it can speed up the delivery of a working prototype, or at least reduce the chance that the first action that the first non-developer user of your system does causes the whole application to crash.

Genuine usability failures, performance issues and failure to actually do what the user wanted will not get caught by TDD, but putting automated tests in early means that the use of the prototype as a way of revealing unavoidable bugs is not downgraded by the existence of perfectly avoidable ones. It may also make it easier to iterate on the functionality in the prototype by catching regressions during the changes cycle, although I'll admit that the existence of lots of tests here may well be a double-edged sword. It very much depends on how much the prototype changes during the iterative phase, before the whole thing gets thrown away and rebuilt.

And, when you come to building your non-throw away version, the suite of tests you wrote for your prototype give you a check list of things you want to be testing in the next iteration, even if you can't use the code directly. And it seems likely enough that at least some of your old test code can be repurposed more easily than writing it all from scratch.


Normalise early-stage re-writes.

(Only slightly joking)


I’ve heard something similar once, but I don’t remember where:

“Write it three times. The first time to understand the problem, the second time to understand the solution and the third time to ship it.”


I wish more places followed this.

Doesn't matter how good you are the v1 of a program in an unknown area is always complete crap but lets you write an amazing v2 if you paid attention making v1.


I think this is what the best programmers do, they are always rewriting things…

Reminds me of the chapter "Plan to Throw One Away" from The Mythical Man Month.

> In most projects, the first system built is barely usable. It may be too slow, too big, awkward to use, or all three. There is no alternative but to start again, smarting but smarter, and build a redesigned version in which these problems are solved. The discard and redesign may be done in one lump, or it may be done piece-by-piece. But all large-system experience shows that it will be done. Where a new system concept or new technology is used, one has to build a system to throw away, for even the best planning is not so omniscient as to get it right the first time.


I've heard Sape Mullender from bell labs (and plan 9) say it during classes he tought.

it doesn't matter how well your app is designed, your UX designer is not going to tell you you need a function that does X. you just build something that looks like the thing they want, and then write some tests to make sure someone doesn't break that thing, and if you have to write a dozen functions to create it and they're testable then you test them but you don't say oh no i can't write a 13th function now because that wasn't part of the preordained plan

Yes its not well defined, neither before nor after implementing. I've made peace with accepting it never will be.

An implementation without definition, and a whole host of assumptions gets delivered as v1.

Product expectations get lowered, bugs and defects raised, implementation is monkey patched as v2.

devs quit, managers get promoted, new managers hire new devs, they ask for the definition and they're asked to follow some flavor of the year process (TDD, Agile, whatever).... rinse and repeat v3.

Sad. True. Helpless. Hopeless.


Legal | privacy