[HN Gopher] Rules for Writing Software Tutorials
___________________________________________________________________
Rules for Writing Software Tutorials
Author : mtlynch
Score : 78 points
Date : 2025-01-02 14:23 UTC (8 hours ago)
(HTM) web link (refactoringenglish.com)
(TXT) w3m dump (refactoringenglish.com)
| mtlynch wrote:
| Author here.
|
| I've been thinking for a long time about anti-patterns I see when
| following software tutorials, so I put together this list of
| things I think differentiate good tutorials from poor ones.
|
| I'm happy to hear any feedback on this list or hear about other
| things I should include.
| MortyWaves wrote:
| I actually don't like the example with Djano and JS: too much
| bad/fake SEO compounded by Googles enshitification mean that
| very specific search terms for specific technologies get
| drowned out by generic word salads like "organising and
| structuring djano projects".
|
| There's probably a million of those already.
| mtlynch wrote:
| Thanks for reading and for the feedback.
|
| Yeah, I see what you're saying. I had this article[0] in
| mind, which is a well-written article and ranks #1 for
| "organize front end code django" on Google. None of the other
| results are close in relevance or quality.
|
| But I guess that example could be confusing for readers who
| aren't familiar enough with Django to know why structuring
| the frontend is a hard problem that not many people write
| about.
|
| [0] https://www.saaspegasus.com/guides/modern-javascript-for-
| dja...
| jackpirate wrote:
| I have a minor nit to pick. I actually prefer when tutorials
| provide the prompts for all code snippets for two reasons:
|
| 1. Many tutorials reference many languages. (I frequently write
| tutorials for students that include bash, sql, and python.)
| Providing the prompts `$`, `sqlite>` and `>>>` makes it obvious
| which language a piece of code is being written in.
|
| 2. Certain types of code should not be thoughtlessly
| copy/pasted, and providing multiline `$` prompts enforce that
| the user copy/pastes line by line. A good example is a sequence
| of commands that involves `sudo dd` to format a harddrive. But
| for really intro-level stuff I want the student/reader to
| carefully think about all the commands, and forcing them to
| copy/paste line by line helps achieve that goal.
|
| That said, this is an overall good introduction to writing that
| I will definitely making required reading for some of my data
| science students. When the book is complete, I'll be happily
| buying a copy :)
| mtlynch wrote:
| Thanks for reading!
|
| > _Many tutorials reference many languages. (I frequently
| write tutorials for students that include bash, sql, and
| python.) Providing the prompts `$`, `sqlite >` and `>>>`
| makes it obvious which language a piece of code is being
| written in._
|
| I think it's fine to show the prompt character, but I think
| it's the author's job to make sure that copy/paste still
| works. I've seen a lot of examples that use CSS to show the
| prompt or line number without it becoming part of copied
| text, and I'm highly in favor of that.
|
| I think if I had to choose between breaking copy/paste and
| making the language obvious with the prompt character, I'd
| exclude the prompt, but I think that's a matter of taste.
|
| > _Certain types of code should not be thoughtlessly copy
| /pasted, and providing multiline `$` prompts enforce that the
| user copy/pastes line by line. A good example is a sequence
| of commands that involves `sudo dd` to format a harddrive.
| But for really intro-level stuff I want the student/reader to
| carefully think about all the commands, and forcing them to
| copy/paste line by line helps achieve that goal._
|
| Yeah, I agree about preventing the reader from copy/pasting
| something dangerous.
|
| In tutorials that require a reboot, I'll never include a
| reboot command bunched in with other commands because I don't
| want the user to do it by mistake. And I agree for something
| like `dd`, you'd want to present it in a way to make it hard
| for the reader to make mistakes or run it thoughtlessly.
| ctkhn wrote:
| Very good stuff. Going to consult this as I build personal and
| work projects. Working at a huge org right now and its amazing
| how many crucial details are missed in the tutorials that we have
| for internal things we depend on
| indentit wrote:
| I really like how clear and well laid out these rules are. It
| covers lots of things that I have always thought about when I
| write instructions in README files etc, so it's very nice to see
| everything neatly described/reasoned in one place. Thanks for
| sharing!
| alentred wrote:
| Extending on the copy-pasteable snippets, another big improvement
| (flaw to avoid) is to include all imports to the code snippets.
| stared wrote:
| There is a lot of good advice about details!
|
| Especially one that got my heart:
|
| > Some authors design their tutorials the way you'd give
| instructions for an origami structure. It's a mysterious sequence
| of twists and folds until you get to the end, and then: wow, it's
| a beautiful swan!
|
| > A grand finale might be fun for origami, but it's stressful for
| the reader."
|
| Yes, a lot of tutorials are puzzle games. You need to guess other
| tools to install, which are obvious to the author, but not
| everyone.
|
| I would add a few things:
|
| * Have two types of examples - minimal and the most typical (one
| is to show the essence without distraction, the second to serve
| as a practical starting point) * Always provide the full code
| sequence to run code; if there are any assumptions, these should
| be listed explicitly (e.g. "it needs Node 22"); you hinted a bit,
| but since many tutorials miss that, it deserves attention.
|
| Even better, if it is possible to combine it into one point and
| make it runnable. For example, for a package I had been
| developing, livelossplot, I made Jupyter Notebooks runnable in
| Colab:
|
| * https://colab.research.google.com/github/stared/livelossplot...
| * https://colab.research.google.com/github/stared/livelossplot...
| jagged-chisel wrote:
| I thought "Keep your code in a working state" would be discussing
| how to keep code working when some dependency changes. What was
| covered is valuable advice, but I'd like some exploration on
| keeping the published code cohesive under refactoring and
| refinement away from the text.
|
| For example, if I'm P. Shirley and I've written a book (with
| code) about following light rays between a virtual camera and
| virtual objects. I have refactored some code to be more clear. Of
| course, I have iterated on this code to verify it remains
| correct, but the related text isn't affected. I have to remember
| where to paste this new code. Unless the documentation had some
| kind of reference to the specific file, lines, and/or function to
| render into the text.
|
| What's the advice for best practices here?
| amenghra wrote:
| Some people embed code in a way that's similar to a test and
| then have a process to run/test all the embedded code.
| smitty1e wrote:
| Given that most examples are relatives small, one could
| leverage org-babel[1] and write the tutorial with executable
| code, and go straight to .PDF!
|
| [1] https://org-babel.readthedocs.io/en/latest/
| joshka wrote:
| Make the tutorial text include the code verbatim from a working
| repo that passes CI. No pasting necessary. Sure you still have
| to verify that the tutorial text aligns with the code changes,
| but you don't have to do anything manual to update the code in
| the tutorial.
|
| As an actual example of this, here's a plugin for Remark that
| allows us to import specific functions from a rust source file.
| https://github.com/ratatui/ratatui-website/blob/main/src/plu...
| If the source code fails to compile, we get a CI error (in the
| rust checks). If the source code changes in a way where the
| import is no longer correct, we get a CI error (in the npm
| checks).
| rinvi wrote:
| Thank you for this. I want to also reference diataxis [0], a
| systematic approach to technical documentation authoring, which I
| think has some good advice on the subject of tutorials.
|
| [0] https://diataxis.fr/tutorials/
| rglover wrote:
| This is a great list of stuff. I spent years writing tutorials
| and wish this list existed when I first started.
| edihasaj wrote:
| Great
| Linux-Fan wrote:
| I am rather ambivalent about these rules. I disagree with a lot
| of the individual points, but I am also sure that I have probably
| often written bad tutorials myself where some of the rules would
| have clearly helped... :)
|
| > 5. Make code snippets copy/pasteable
|
| I like to use the prompt to identify the language and also the
| user (root `#` vs. user shell `$`) to perform the action under. I
| advise against copying random commands off the internet
| especially those that run as root and may break your system (like
| `apt` and `--yes` together...). Of course, today, it is often
| assumed that you have sudo setup and then `sudo ...` is used to
| indicate the use of root privileges. It is an interesting
| convention although in my opinion this sometimes hides the actual
| intent.
|
| I prefer: # echo 3 > /proc/sys/vm/drop_caches
|
| over echo 3 | sudo tee /proc/sys/vm/drop_caches
|
| The example given in the article is exactly one where attention
| is required: It adds a PPA as root, thereby giving "full control"
| to the PPA author. Never straightout copy-paste such stuff.
|
| > 6. Use long versions of command-line flags
|
| I am so much more used to the short versions hence I prefer `grep
| -RF` over `grep --dereference-recursive --fixed-strings`. Also,
| my go-to documentation about these commands (POSIX) doesn't even
| know about the long options.
|
| I know that the advice to prefer the long options is repeated
| pretty often so it might just be me :)
|
| > 7. Separate user-defined values from reusable logic
|
| Ever followed some "enterprise-grade" software setup tutorial?
| Sometimes they start by assigning 20 variables to some generic
| values that you don't change most of the time and then go about
| to reference them on the next 20 pages or such making it close to
| impossible to know what is really going on. Also I find that for
| simple cases this greatly complicates the input process.
|
| I think the example doesn't really show the difference because it
| has some variables (just not in shell syntax) in the code already
| like `YOUR-API-TOKEN`. Of course it is better to write
| `$API_TOKEN` rather than `YOUR-API-TOKEN`. I often prefer to see
| the example value in the example i.e. not `YOUR-API-TOKEN` but
| some real string (if feasible). In many cases I won't change a
| value in the beginning to see how far I get with a "known valid
| input". Also, I often prefer to pattern-match some real value
| against what I have available, e.g. I have a key which I think
| could be the API key but if the format is totally different from
| the tutorial I may realize that this is an "app token" rather
| than "API key" and that I may need to get a different value if it
| fails to run with my input or such.
|
| > 9. Let computers evaluate conditional logic
|
| If dosed correctly, I think this is good advice. I'd strongly
| prefer the conditional boxes from the "bad" example over the
| "good" monster shell script command. In my opinion a tutorial
| shouldn't optimize for speed of execution but rather foster the
| understanding by the reader. There is no help if I find this post
| 10 years later and it helpfully outputs "ERROR: Unsupported
| platform" on my Debian 16 system. If the text instructions are
| given as in the "bad" example, I quickly realize that all of this
| is outdated and I should probably try with the most recent
| package name (example-package2) rather than meddle with some
| script.
| baudaux wrote:
| > As soon as possible, show a working demo or screenshot of what
| the reader will create by the end of your tutorial.
|
| For this reason I am building a new way of writing coding
| tutorials, with the possibility of writing and running code
| snippets into the web browser including graphical apps:
| https://exalib.com
| codetrotter wrote:
| > Tutorials often forget to mention some key detail, preventing
| readers from replicating the author's process.
|
| I also find this sometimes.
|
| A high quality tutorial on the other hand, is often one where the
| author bothered to set up a fresh VM and follow their own guide
| step by step to confirm that everything works as described. This
| way the author avoids unintentionally forgetting to mention
| additional dependencies that have to be installed and additional
| config files that need to be tweaked in order for the steps to
| work.
___________________________________________________________________
(page generated 2025-01-02 23:00 UTC)