top | item 42417478

Preferring throwaway code over design docs

327 points| softwaredoug | 1 year ago |softwaredoug.com | reply

172 comments

order
[+] jasonpeacock|1 year ago|reply
This is called prototyping, which is a valuable part of the design process; some people call it "pathfinding".

These are all inputs into the design. But a design is still needed, of the appropriate size, otherwise you're just making things up as you go. You need to define the problem your are solving and what that solution is. Sometimes that's a 1-page doc without a formal review, sometimes it's many more pages with weeks of reviews and iterations with feedback.

Don't forget: "weeks of coding can save hours of planning" ;)

[+] lmm|1 year ago|reply
> a design is still needed, of the appropriate size, otherwise you're just making things up as you go.

A design needs to be understood, certainly, but that doesn't necessarily mean a document, or indeed any permanent artifact. And if you do need a permanent record, a PR can be as good a medium as any.

> Don't forget: "weeks of coding can save hours of planning" ;)

I've found the opposite is true far more often. People plan and plan until the plan is not merely pointless but actively destructive to productivity.

[+] eadmund|1 year ago|reply
I think that it’s one of those dichotomies. One needs both a design and a prototype.

As you say, weeks of coding can save hours of planning. But weeks of planning can be wasted, too. It’s easy to write things on paper which don’t make sense or are impossible, e.g. ‘We will colour the unicorn fleet semi-sad.’ Ideally, the design and the prototype would evolve in concert, each iteration of one driving the next iteration of the other, spiralling like the double-helix of DNA.

The great virtue of a bias towards building prototypes is that at the end of a round of prototyping one actually has software which can do something — at the end of a round of design one doesn’t really have anything.

[+] sevensor|1 year ago|reply
Agreed, why not both? In fact, I’d say, first write up a theory, then demonstrate that it does or does not work using a prototype, then write the actual design doc. At all times, and continuing into the implementation phase, prioritize the disposability of your code. The easier it is to delete, the better.
[+] DrNosferatu|1 year ago|reply
Right on the money:

Prototyping and pathfinding are totally fine and mostly necessary.

*But*, Software Engineering without design docs or any kind of specification (even if succinct) is just tree-house building, *not* Engineering.

And the bigger the size and importance of the project, the sooner the problems and technical debt will start to show.

[+] shric|1 year ago|reply
> Don't forget: "weeks of coding can save hours of planning" ;)

Also, "weeks of planning can save hours of coding" :)

[+] ElatedOwl|1 year ago|reply
Writing is really beneficial for exploring the problem space.

Many times I’ve confidently thought I understood a problem, started writing about it, and come away with new critical questions. These things are typically more visible from the abstract, or might not become apparent in the first few release milestones of work.

I’m reminded of a mentor in my career, who had designed an active/active setup retroactively for a payment gateway. He pulls up a Lucidchart and says “this diagram represents 6 months of my life”.

They’re not always necessary or helpful. But when they are you can save weeks of coding with a few days of planning.

[+] appleiigs|1 year ago|reply
I had a boss who had a math degree. He'd map out the flow from start to finish on a whiteboard like you see mathematicians on TV/movies. Always had the smoothest projects because he could foresee problems way in advance. If there was a problem or uncertainty identified, we'd just model that part. Then go back to whiteboard and continue.

An analogy is planning a road trip with a map. The way design docs most are built now, it shows the path and you start driving. Whereas my bosses whiteboard maps "over-planned" where you'd stop for fuel, attraction hours, docs required to cross border, budget $ for everything, emergency kit, Plan A, Plan B.

Super tedious, but way better than using throwaway code. Not over-planning feels lazy to me now

Sure, everyone has a plan until you get punched in the mouth; however, that saying applies to war, politics, negotiations, but not coding.

[+] softwaredoug|1 year ago|reply
I agree writing is beneficial. But I also find this works with coding. And they go hand in hand for exploring in my experience.

And in the end a good PR has a lot of writing too and has this effect. IMO this sort of well documented draft PR serves as a better design proposal because pure writing causes you to forget important constraints you only remember when you’re in the code.

[+] patrickmay|1 year ago|reply
"Writing is nature's way of letting you know how sloppy your thinking is." -- Dick Guindon
[+] ChrisMarshallNY|1 year ago|reply
The biggest issue that I’ve had with design docs, is that nobody reads them; even if required by their employer.

The biggest issue that I’ve had with prototyping, is that people consider it “ship” code, and force me to use it as final code.

I find that I’m best served with a hybrid approach, where I spend a lot of time planning and documenting, but basically, for myself, then writing ship-Quality prototype code, so that using it in the end product is OK.

[+] kccqzy|1 year ago|reply
The reason people don't like to read the average design doc is because the average software engineer doesn't have enough writing skills to express the concept clearly and concisely without editing. The design doc becomes a mumble jumble of raw notes that nobody really understands except the author. And then people dread reading this kind of raw notes.

However, if someone tells that design doc writer that this is something like a term paper at school that is being graded, they can actually improve their writing by quite a bit by doing some editing. So the symptom is really the same as prototyping: people write draft-quality design docs and magically hope it to be a good quality piece of writing suitable for a wider audience. What they need is a few rounds of editing, just like when they write prototype code they need a few rounds of refactoring.

[+] m1n1|1 year ago|reply
We had to build and launch something by a deadline in order to avoid renewing a contract that would have cost $x mil. But we discovered we weren't going to finish in time with the resources and the approach that was planned.

So I got approval to hack out a temporary impartial suboptimal version and we were able to take off in time.

This has allowed us to fly for a bit while others finish building out the permanent proper version of that part of the wing.

In fact, during our flight we discovered missed requirements in the original design. This has delayed that proper version's release to prod. But I've been able to add that quickly to my hack and keep us flying.

My hack doubles as a production support tool. And as an alternate route if the permanent version needs to be paused because of a bug. Yes it's a partial imperfect hack but it has benefits.

Someone has complained about the language I used since it is less common. But remember, we weren't going to be able to take flight with the existing resources and approach.

We would have needed more and/or faster developers in the favored language to meet the deadline.

If any present employee (including me) had bandwidth and was able to be as productive in the favored language as I was building my hack in the uncommon language, that employee would have been tasked to build the permanent solution on time. That option was not available.

Anyways, if you have an existing production support tool, it's also a place where prototype features can live for a while.

[+] hcarvalhoalves|1 year ago|reply
Another opinion piece, but no data, not even a concrete example.

I get it, every software engineer has strong opinions, but that’s a weak one. If you think writing a lot of code to see what sticks is the job description, you’ll be replaced by GPT in no time - it can do it faster and cheaper. The challenge is always in getting alignment on what should be built, you won’t code your way out of that.

[+] bccdee|1 year ago|reply
Hard agree. I don't know if "design doc" is the right word—I call them technical analyses—but writing up a doc that connects business & product needs to implementation details is highly useful to get everyone on the same page in terms of requirements & deliverables.

If I'm clear on the requirements & everyone else is clear on what I'm delivering, this is unnecessary. Sure, jump straight to prototyping. But this is rarely true for any serious project. There are always unknown unknowns that you need to tease out from the stakeholders, and a technical analysis is a great way to do that.

[+] softwaredoug|1 year ago|reply
That’s exactly my point, I think you get better alignment with “show don’t tell”.

Rectangles and dotted lines only get you so far. Being removed from actual code makes you forget the real constraints - the stuff that actually slows you down doesnt appear in google docs. “Here’s what I’m thinking (points at Draft PR)” gets you farther in my experiencre.

And yes it’s 100% an opinion. It’s a personal blog not a peer reviewed article :) I’m happy to be wrong.

[+] yen223|1 year ago|reply
Throwaway code is better than a design doc precisely because it is a concrete example.

Without something tangible like code to tether conversations, discussions over abstract designs invariably devolve into "my imaginary piece of string is longer than your imaginary piece of string" arguments that lead nowhere.

[+] redcobra762|1 year ago|reply
It's more likely that someone who holds this belief will be able to move substantially faster with an LLM, than it is that an LLM would take over this task in its entirety.
[+] simonw|1 year ago|reply
Sometimes the "data" behind this kind of article can be decades of personal experience.
[+] cplat|1 year ago|reply
I think there's merit to both design docs and prototypes.

At the same time, your argument that "you'll be replaced by GPT in no time" is also an opinion that you've not supported with any data; the same thing that you're accusing the OP of.

I mean If I stopped reading opinions, 99% of the HN comments would disappear.

[+] robertclaus|1 year ago|reply
In my experience there is a MASSIVE difference in the type of feedback someone gives on code vs a design. A design doc encourages "why" questions to get everyone thinking about the problem space. For example, a design doc comment might be "why are we suggesting a Rust Webserver when nobody in the company is proficient in Rust yet?".

In my experience those more subtle questions are much harder to raise once a prototype is working - "why does the team's experience matter? look how great it works! If you don't block it we could get this to production in a week by just polishing the prototype!"

[+] bawolff|1 year ago|reply
This is not neccesarily a bad thing though. Lots of "why" questions are really counterproductive bikeshedding. Especially when it comes from just reviewing a design as opposed to working code.
[+] jp57|1 year ago|reply
We imagine software efforts that go through a clean, neat flow:

We write a design doc. Then make small incremental changes in a PR to rollout the functionality. Our git histories look clean and orderly. Like a steady march of progress.

Who imagines this? Professors who teach software engineering classes?

This reminds me of people who think that you write prose (essays, stories, novels, etc) by writing an outline and then "filling it out" with prose, as if in the process you will never discover anything that requires you to rewrite or restructure the document. Nobody writes that way. First drafts are always terrible and basically all good writing has been heavily revised.

Writing code is much more like writing than it is like building a house or a bridge.

[+] throwaway2037|1 year ago|reply
For myself, I always find great value in debugging new code that I have written. Something about stepping line by line through new logic, and viewing variables/memory really helps me to improve my code. "Oh, I don't need that local var." "Oh, I should add a temp var to make the code easier to debug here." "Oh, this code is weird when the collection that we iterate is empty." No matter how old I get, and no matter how much code I write, I always discover new things when I debug my newly written code. I guess this could be compared to an author writing a first draft, then going back to read it... or reading it aloud to themself or another person.
[+] simonw|1 year ago|reply
I really like this process: using an ongoing comment thread to document design decisions along the way, as opposed to trying to formalize them in a single document.

I use GitHub issues for this myself but that's functionally equivalent to using a PR - a PR is effectively a GitHub issue with an attached branch of code.

I wrote more about my process here: https://simonwillison.net/2022/Jan/12/how-i-build-a-feature/...

[+] kmoser|1 year ago|reply
But then how do you communicate the latest consensus on all issues, e.g. for a newcomer who doesn't want to slog through months of communication, or a team member who has been part of the thread all along but can't easily find where the team agreed on a particular thing? In other words, how do you summarize the thread into final documentation?
[+] aleksiy123|1 year ago|reply
I don't think they are mutually exclusive?

Design doc is broader. It's goal is communication.

Sometimes you need to communicate other than in code. Diagrams, images, words etc...

[+] corytheboyd|1 year ago|reply
Agree.

It’s very hard for anyone who isn’t the author, or otherwise intimately familiar with the code, to understand changes at a glance. The reader needs high level explanations and documentation to quickly build the correct mental model to understand the change in context.

If you can look at 1000 lines of diff and accurately tell what it’s doing, and much more importantly, the upstream and downstream implications… you’re either lying, or somehow work in a perfect hermetic vacuum of verifiability that I am very jealous of.

[+] miscaccount|1 year ago|reply
A design doc would help narrow down the number of prototypes to 2 to 3 in all the available options. This is especially useful if you are exploring adding something completely new.

Though i feel that showing is better than telling, when new people onboard they have a easier time understanding via a design doc than code.

[+] wavemode|1 year ago|reply
The design document is for documenting what problems you're trying to solve, and (critically) what problems you're not trying to solve. And the relative advantages and disadvantages of competing approaches.

The mistake people make with design documents is going into too much detail on -how- you're going to solve the problem. That's where prototypes ("throwaway code") come in. The design document should just be a high-level overview.

[+] gareve|1 year ago|reply
I think it all depends on the size of the team.

Very small team and too many design docs, not good.

Huge team, multiple timezones, multiple squads, and few design docs, not good either.

And then you balance with all the values in between depending on your team size & culture.

Even within the same company, your approach will/should change as it grows. There's a critical point where move fast and break things approach will eventually end up with too many outages, production bugs, unpolished/confusing product, and last but not least, FTC eye watering fines.

[+] bluGill|1 year ago|reply
Design documentation should be done on a whiteboard. You have limited space but that forces you to write down what is important and who it doing what. in a few weens it is so different from reality that you don't feel bad about erasing it for whatever is next.
[+] simonw|1 year ago|reply
... as long as you then take a photo of that whiteboard, attach a timestamp and put it somewhere people can find it in the future.

Otherwise it's not documentation at all, it's lost to the wind.

[+] dboreham|1 year ago|reply
I've been doing this for more than 30 years. Never seen one design doc. At least not one that was actually used to guide the subsequent implementation.
[+] koolba|1 year ago|reply
They both have their place. Ideally the design doc flows out from the proof of concept to document the non-trivial assumptions and decisions. But nothing beats an actual PoC to demonstrate that something will actually work.

I like the phrase “weaponize” to refer to the evolution of a PoC into a workable application.

[+] BurningFrog|1 year ago|reply
A few more years, and same here.

Design discussions can be very useful though.

[+] allenu|1 year ago|reply
I'm a big fan of prototyping to explore a problem space. I think some initial design sketches are useful, but you often reach a point where you can only learn by implementing. I've encountered so many design constraints in the past that I couldn't have planned for, but perhaps others are better at comprehensively thinking through a problem space than I can.

I agree with the blog post that doing a hacky solution is very helpful to understand the problem space better, although I think it's something that's challenging in an organization. In a lot of orgs, it might be viewed as a waste of time to work on something hacky. It could also come across as wasting people's time by engaging in too many discussions over PRs. People want shipping solutions today, not explorations that might need to be rewritten later. Asking for feedback might also come across as someone being unsure of a solution and needing "help" on it.

The dynamics of working in a team generally nudge devs to make more conservative moves and writing more up-front design docs, which will be slower and safer. I'm not arguing that's a bad thing, though. You need the documentation to communicate intent across an org and many other people will need to pick up the work, too. A PR may not provide enough space to comprehensively explain the overall design.

As an indie dev now, I find sketching some designs, followed by prototyping, then "massaging" the prototype into a working, shippable solution the ideal workflow. However, it only works because I'm solo and don't need to worry about getting an okay on potentially risky solutions or having to communicate and get buy-in on implementations. In a company that has lots of other devs and lots of paying customers, I wouldn't be able to do things that way, and for good reason.

[+] damethos|1 year ago|reply
> In a company that has lots of other devs and lots of paying customers, I wouldn't be able to do things that way, and for good reason.

Why not? You do the "sketching/mockup" of most of the flow (without going into too much design detail) in order for the team to understand better what you are going to build. Then, everybody can provide feedback based on their perspective, do a couple of iterations, then prototype (which if done well will be the initial version of the shippable solution) and then iterate again.

[+] rich_sasha|1 year ago|reply
I think the key is to have a solid understanding that this is throwaway code.

I know of, erm, one quite company, fairly well known in its big industry, where indeed no one gathers any requirements and a junior guy is told to type it all in - with the view that it's probably 90% correct and the rest can be ironed out at some stage, or at worst rewritten.

But what tends to happen is thus:

1. The first draft tends to address all the wrong problems, doesn't abstract the right things, is over and under engineered in all the wrong places. Fine, it's a draft I guess

2. But here's the kicker: unless it's really unusable, there is now pressure on users to accept the draft, because changing it, perhaps substantially, requires work, and as it it sort of kind of works, if you squint. And this thing is there and you can pretend it's a job done.

I think ploughing in to writing code works if you ha r a decent idea of what you need to achieve and what the pinch points are. Without that it can be quite an expensive and frustrating approach.

[+] iamalexm|1 year ago|reply
Design docs are great for high-level orientation. If you are laying out all your code structure around it, you are doing it wrong. It's great to use the for what patterns will be used (using a facade pattern for example). It gives eng's a guide to how to implement at a high level and it should identify points of non-functional requirements; speed requirements, monitoring, security, etc. Throwaway code doesn't even touch on that. It should also put in scope some of the architecturally significant decisions that need to be made. While throwaway/prototype code can address some of that, it doesn't always identify it and talk about _why_ it is important.

In short, doing both is the best thing you can do and you should scope your design docs correctly.

[+] charlie0|1 year ago|reply
This makes me shudder because I've never seen this done in practice. What always happens is the code builds up like Jenga until no one wants to touch it.
[+] hasbot|1 year ago|reply
And it's so obviously bad that new hires want to re-implement from scratch even though they don't have complete knowledge of what the software does.
[+] krisoft|1 year ago|reply
I like the idea and we use it at work often. One pitfall one has to be aware is that it is easy for the people who are asked to provide feedback on the prototype to get bogged down in the details.

What you want is people to squint and tell you if they like the general approach, but what often happens is they tell you that you need more unit tests and you could use a ternary operator here and here. (The particular details will of course differ in each case.) The reason for that, in my opinion, is that your thing looks like a PR and therefore people default to the kind of review they do for PRs. But since this is a different beast it needs a different mindset during review.

And of course the only possible solution for that is proactice and active communication to get everyone on the same page.

[+] stasiu|1 year ago|reply
Does anyone have a design doc format that they prefer for backend development? We’ve been working with ADRs, is that similar or the same as a design doc?

PS. I like the approach. Sounds like something I read before where devs would throw away their code everyday until they were satisfied with the result.