When explaining to beginners, use simple examples.

I've always felt that most geeks give examples (to beginners) that are too complex. I believe this is an attempt to be complete. However, beginner examples should be so simple even if you feel like you are committing lies of omission.

A recently Slashdot article, Revisiting Why Johnny Can't Code: Have We "Made the Print Too Small"? mentioned that often the examples we give are too complex for the beginners we intend them for. They compare the starting example from Mark Zuckerberg's what-is-coding video to a simple BASIC example. They make a comparison to the book How to Teach Your Baby to Read, the authors explain, "It is safe to say that in particular very young children can read, provided that, in the beginning, you make the print very big."

In other words: Know your audience.

Many times I've seen people introduce a new system by boasting how it can solve sophisticated problems and start with the most bizarre, complex example. They instantly lose the audience. The first impression they've made is "this is too complex for me". Oops.

One of my favorite examples is the manual page for "find" in FreeBSD. The first example is:

find / \! -name "*.c" -print

What a shitty, mean, example to put in front of a beginner. This example requires that the person understand globs, the need to quote "*", the fact that many shells treat "!" special and it must be escaped. That's two different escaping methods in the same example! I imagine many people see \! then are disappointed to not be able to find \! mentioned anywhere else in the man page (to a new user \! is not !). Oh, and the example will get a user in trouble if they run it because it starts at "/" and, if they are on a machine with access to many NFS servers, will take days to run and may invoke the ire of their sysadmins. Good job, FreeBSD!

Here's a better first example of "find":

find /tmp -name foo.c -print
    Print out a list of all files named "foo.c"
    in /tmp or any subdirectory.

A good second example would introduce exactly one new concept, such as globs:

find . -name '*.c' -print
    Print out all files whose name ends with
    .c in this directory and any subdirectories.

I would then add the "not" concept:

find . \! -name '*.c' -print
    Print out all files whose name does not begin
    with .c in this directory and any subdirectories.
    Note that "!" is escaped because many shells
    treat it as a special character.

Notice that I change " to '. Don't start people using double quotes. That leads to security problems. Get them in the habit of using single quotes from the start.

The examples should cover the most common use-cases, not just show off how to use various features.

One of the most desired use-cases is to have find skip certain files or directories, especially if you use Git or Subversion. To do this one must use -prune, which doesn't work as most people would expect. So what is the first example to do such a thing?

find /usr/src -name CVS -prune -o -depth +6 -print
    Find files and directories that are at least
    seven levels deep in the working directory /usr/src.

Not only is that overly complex, but the description is useless to anyone looking for "skip directories".

The first example of -prune should be very simple and amazingly practical. Just skip one or more directories:

find . -name .git -prune -o -print
    List all files, but skip any subdirectories called .git

find . -type d \( -name .git -o -name .svn \) -prune -o -print
    List all directories, but skip any
    subdirectories called .git or .svn.

The other most common use case of find is to run a command on each file found. In this case the description is confusing to a new person:

find / -type f -exec echo {} \;
    Use the echo(1) command to print out a
    list of all the files.

Would it be so difficult to simply say:

    Run the echo(1) command on each file found.

Linux man pages are equally guilty. The man page for find on CentOS 7 starts with examples that delete files, and has a security hole in it:

find /tmp -name core -type f -print | xargs /bin/rm -f

Yes, the next example explains and fixes the security hole, but why start with an example that you wouldn't want users to blindly cut and paste?

The same man page lists this example for running a program on each file found:

find . -type f -exec file '{}' \;

Is "file" a command, a keyword, or are you supposed to replace it with the name of a file? Ugh. Why pick the one command that has so many different overloaded terms. What's wrong echo or stat or sha256sum?

find . -type f -exec sha256sum '{}' \;
    Run sha256sum(1) on each file found.

I've raised this issue with FreeBSD and Linux developers. One told me, "Man pages shouldn't be tutorials". That's a rationalization to cover up bad behavior. There is a big difference between a comprehensive tutorial, as would be appropriate for a book or video series, and having thoughtful examples.

Posted by Tom Limoncelli in Teaching System Administration

4 Comments

Great post. Keeping first examples simple and building on them gradually (and keeping them relevant) is the best way to not turn off people new to the material, whatever the material may be.

Also,I believe you have a typo in the explanations for the second and third find examples "whose name begins with .c" should be "whose name ends with .c".

You just TOTALLY stole my comment!

Great post :)

Thank you for pointing out the typo. I've fixed it!

This is one thing Snover and Co. got right with powershell.

Get-Help Write-Host -Examples

It's extremely convenient to have a section for just examples in help documentation.

 
  • Don't Miss Out - Register Today