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.
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.
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.
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.
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!
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.
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.
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.
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:
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:
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.
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.