Hacker News new | past | comments | ask | show | jobs | submit login
Readme Driven Development (2010) (preston-werner.com)
226 points by goranmoomin on Nov 26, 2020 | hide | past | favorite | 42 comments



Author here. Fun to see this come up on HN again, every so often. Readme Driven Development still serves me well (that’s how we drove RedwoodJS early on) and we even expanded that into Tutorial Driven Development, where we wrote the RedwoodJS tutorial to show what we wanted to be possible from a DX perspective, and then figured out what code we needed to write to make it possible. It’s been an efficient way to focus on what’s important and not make usability sacrifices for the sake of easy coding. It’s really just the design-first approach, applied to a framework!


This is excellent! You put into words all those benefits I was trying to communicate a while ago (https://twitter.com/shcheklein/status/1325978612378423297) but didn't find the right term . Documentation is an overloaded term (means everything from readme to man pages) and I guess, that's why it makes it hard to explain DDD since a lot of engineers perceive it as something like `man` pages, or even doc strings.


Watch out, DDD is taken/ already has a different, widely-used meaning.


Domain-Driven Design.


UX is the only thing that matters, it just happens that the guts of your software have to do something correct and useful as one of the prerequisites to great UX. This is a great way to design software.


I think this is true for any specific moment, but as we are creatures of the 4th dimension, we must also care about how we change our code over time. When code complexity is managed, users can enjoy better versions of a piece of software more quickly and more often. If we let our code deteriorate into an inscrutable pile of tech debt, it will eventually affect the user experience, so the guts need to both do something correct (and useful) and also be amenable to change over time.


Absolutely agree. At my workplace, we often have to balance immediate UX requirements with longer term reliability, extensibility and security.


I missed this article in previous rounds, but during your interview with the Changelog regarding RedwoodJS I remembered the anecdote about "writing the tutorial first" and it really stuck with me.

I find this especially useful when I'm building complete solutions from lots of other technologies -- it's easy to fall into the trap of "well my API will behave like API X because that's what I'm using under the hood". Readme driven development really encourages thinking harder and producing something that's greater than the sum of its parts.


I like it. I try and design whatever I’m building from the user goals perspective (“user want to buy a ticket” “user wants to change a seat” “user wants a refund”), and I know from my perspective as a user I always hope the readme has been written more like a tutorial (a list of examples on how to do what I want... not a list of command line options!)

This feels like a good way to combine both things!


Readme Driven Development must be working well because Redwood is the most exciting thing about web and API development right now. I've been working through the man tutorial and Redwood's the best attempt I've seen to bring the poweful principles behind Rails to Node and JAMStack.


> Tutorial Driven Development

I had a nickname for this: whishful thinking design


Great article. Btw, you’re the guy who invented TOML, right?


I like how TOML was the first thing that came to your mind and not 'co-founder of GitHub'.


TOML is my true legacy. =)



Great post, something I'll share with my team. Thanks.


This reminds me of Doom’s development, where they did the press release before writing the game:

https://rome.ro/news/2018/12/10/reflections-on-dooms-develop...

I always think of that anecdote before starting a new project.


I heard about this technique in relation to Amazon product announcements.

Whoever came up with it, it's great.


This is how I write libraries but never formalized the tactic.

Basically create a readme with example of how to use the lib with explanation.

Then I design the library to match my design.

I see lots of libraries (especially in .net) that are missing that extra something as if they weren’t designed first.


I do the same with REST APIs and CLIs, and for the latter often build --help as pretty much the first thing (whether for real or just as a text document).

I recently was adding a couple features to an existing utility, where I made some new options (--opt3 --opt4) following the style of what was there. As I was trying to write the help I realized there were several combinations that were totally invalid, and describing the situations where each could be used was really hard. It really boiled down to only about 3 unique situations, so I replaced all those options with a single --mode switch, making it way simpler to code, document and use. Without docs first that wouldn't have been obvious until I either was partway through coding (or maybe writing validation code), or worse, got bug reports about someone trying an invalid combination and it breaking in some strange way.


I'm (temporarily stalled) in the middle of writing a CLI manpage for roughly this kind of purpose (finding a public interface that makes me happy before finally cutting the first release).

It has been clarifying in some big ways, but I also feel like I wouldn't have been able to do this without an initial implementation that I and one or two others have been putting through the paces.

It's taken some time to use it in enough real-world cases that I feel like we've actually discovered a significant fraction of the features it needs.

It takes reflecting on each feature for long enough to understand if it is global or situational, to decide if it's just a change to the program, a new default you can disable, or a new optional feature you must enable. Or is it really a fellow traveller with a number of related features that signal the need for a new mode?

Finding an interface that doesn't annoy me has taken collecting the entire current feature list, the next several planned features, and some "I suspect someone will ask for this some day" sorts of things--and then stepping far enough back from them to distill a smaller number of verbs they can be grouped under.


I write a /lot/ of cli apps for personal and work use and I’ve always wrote READMEs first in the same way and had wrote it off as me procrastinating. Now I can think I’m actually being more productive ;)


> By restricting your design documentation to a single file that is intended to be read as an introduction to your software, RDD keeps you safe from DDD-turned-waterfall syndrome by punishing you for lengthy or overprecise specification. At the same time, it rewards you for keeping libraries small and modularized.

Particularly liked this part.This nuance of not going too far in either direction is what makes the idea effective, I would think. Will keep it in mind for every future project.

And hey, writing the readme first will very likely make tdd easier, as the first few tests to write would be essentially transcripts of the readme into code.


nice, I just went on the first commit of the first repo on his github and he's stuck with it!¹

edit: I see similar examples on the og hn thread https://news.ycombinator.com/item?id=1627342

[1] https://github.com/redwoodjs/redwood/commit/e2ceb0dcdffe4c28...


I agree, this is a great tactic.

I'd been writing my project for over a year and hoping to get help, buy-in, and collaboration. Then I realized that I hadn't updated my Readme since starting out, and it was out of date, and, frankly sucked. It was not convincing, and it was the first thing that devs saw when assessing my project!

Kudos to the author.


I have always liked this idea. Then, my github page is full of interesting readmes with no implementation whatsoever.


If "discovering" your idea is a significant motivator for realizing it, I guess thoroughly scratching the creative itch first might be risky.

This is probably it's own Goldilocks or yin/yang sort of thing? Sometimes I quixotically wander into implementing a project, hook myself with sunk-cost fallacy a fraction of the way to the finish line, and would have ultimately considered it a blessing to scratch the itch without touching implementation.


I assume that's common in some way or another. Most projects don't get to the finish line.


Late pseudo-edit: if someone wants to implement this I'd be delighted

https://github.com/asemic-horizon/pierpaolo



How do you handle readmes getting out of date? I started a new project with a colleague and we wrote a nearly 1000 line Markdown readme with code examples of best practices, patterns etc before we brought on 4 other engineers to the team (who were new to the company). But it quickly became old and out of date as we worked through the project.

So more specifically, I know that one strategy is to just make time to keep it up to date, but I do think there is more to it than that. One aspect was out of date code examples - referring to old line numbers or old patterns that we reconsidered. I think some of that could be automated, and it made me wish for or wonder something better.


How did the readme get out of date...

Did the API change from the spec of the readme?

Shouldn't the readme change first, so its always the code that's out of date? :)


Hah! I see, I missed the point


Is there some develeper churn on the project? If yes, they would be perfect test drivers for the readme. If they get lost, there is a problem with your readme, or with your code. Likely both.

You also have a developer readme, right? ;-)


Would be great to have a dynamic Readme generated from tests (eg. RSpec etc...)


For sufficiently small libraries, I've done a number of READMEs with usage examples that include test assertions. The examples then serve as the test suite. For example:

https://www.npmjs.com/package/spdx-expression-parse

I've released free scripts for Node.js that do the job of parsing the Markdown, extracting fenced code blocks, and filtering by infostring. That leaves just lines of code, which you can pipe straight to the Node interpreter:

https://www.npmjs.com/package/defence-cli


Literate.jl comes close.

You maintain a file README.jl, with a mixture of Markdown text, example code in Julia, and hidden code in Julia. Inspired by Knuth's literate programming idea, there are several things you can do with that file:

* Weave it to get README.md, with the text, the example code, and the output from running the example code.

* #include it in your tests, to run the example code, then run the hidden code to verify the results.

* Super-weave it to generate a web notebook, where people can modify the example code and see what happens.

This isn't perfect. When the examples generate graphical output, you have to write some boilerplate code to capture it as a GIF and link it in README.md. That gets annoying in a numerical language like Julia. But it's pretty good.


I wrote a specification-test framework that does this:

https://github.com/hitchdev/hitchstory

Project with README that is partially generated from the code samples in the tests:

https://github.com/crdoconnor/strictyaml

with the README template:

https://github.com/crdoconnor/strictyaml/blob/master/docs/in...

that grabs code snippets and their expected outputs from the story:

https://github.com/crdoconnor/strictyaml/blob/master/hitch/s...


You can kind of do that with Go with "example" tests and Godoc. In Go, tests can just be code snippets demonstrating the usage of an API. But ultimately, isn't it what TDD is about? Thinking about the public API before implementation in order to focus on what matters?


This should apply to corporate software too. Agile is great, we should be agile, but also document things after deciding to do them, and before you do them!


Depends on what "agile" means for you, term is so perverted now you can't make any assumptions about what people think it means. Agile says working software over comprehensive documentation, so documenting things before you write the software seems to go against that.


This is generalized to the principle: begin with the end in mind (from that habit book).

Great for every other activity as well.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: