A few weeks ago I gave a keynote at Strange Loop
called Making Hard Things Easy. It’s about why I think some things are hard
to learn and ideas for how we can make them easier.
Here’s the video, as well as the slides and a transcript of (roughly) what I
said in the talk.
the video
the transcript
Hello, Strange Loop! Strange Loop is one of the first places I
spoke almost 10 years ago and I’m so honored to be back here today for the
last one. Can we have one more round of applause for the organizers?
I often give talks about things that I’m excited about,
or that I think are really fun.
But today, I want to talk about something that I’m a little bit mad about,
which is that sometimes things that seem like they should be basic take me 10
years or 20 years to learn, way longer than it seems like they should.
One thing that took me a long time to learn was DNS, which is this question
of — what’s the IP address for a domain name like example.com?
This feels like it should be a straightforward thing.
But seven years into learning DNS, I’d be setting up a website. And I’d feel
like things should be working. I thought I understood DNS. But then I’d run
into problems, like my domain name wouldn’t work. And I’d wonder — why not?
What’s happening?
And sometimes this would feel kind of personal! This shouldn’t be so hard
for me! I should understand this already. It’s been seven years!
And this “it’s just me” attitude is often encouraged — when I write about
finding things hard to learn on the Internet, Internet strangers will sometimes
tell me: “yeah, this is easy! You should get it already! Maybe you’re just not
very smart!”
But luckily I have a pretty big ego so I don’t take the internet strangers too
seriously. And I have a lot of patience so I’m willing to keep coming back to a
topic I’m confused about. There were maybe four different things that were
going wrong with DNS in my life and eventually I figured them all out.
So, hooray! I understood DNS! I win! But then I see some of my friends struggling with
the exact same things.
They’re wondering, hey, my DNS isn’t working. Why not?
And it doesn’t end. We’re still having the same problems over and over and over
again. And it’s frustrating! It feels redundant! It makes
me mad. Especially when friends take it personally, and they feel like “hey I
should really understand this already”.
Because everyone is going through this. From the sounds of recognition I hear,
I think a lot of you have been through some of these same problems with DNS.
I started a little publishing company called Wizard Zines where —
(applause)
Wow. Where I write about some of these topics and try to demystify them.
Here are a few of the zines I’ve published. I want to talk today about a
few of these topics and what makes them so hard and how we can make them
easier.
For each of them, we’re
going to talk a little bit about:
a. what’s so hard about it?
b. what are some things we can do to make it a little bit easier for each other?
So, bash is a programming language, right?
But it’s one of the weirdest programming languages that I work
with.
First, let’s run this script, bad.sh
:
mv ./*.txt /tmmpp echo "success!"
This moves a file and prints “success!”. And with most of the programming languages that I use, if there’s a problem, the program will stop.
[laughter from audience]
But I think a lot of you know from maybe sad experience that bash does not
stop, right? It keeps going. And going… and sometimes very bad things
happen to your computer in the process.
When I run this program, here’s the output:
mv: cannot stat './*.txt': No such file or directory success!
It didn’t stop after the failed mv
.
Eventually I learned that you can write set
at the top of your program, and that will make bash stop if
-e
there’s a problem.
When we run this new program with set -e
at the top, here’s the output:
mv: cannot stat './*.txt': No such file or directory
Great. We’re happy. Everything is good. But every time I think I’ve learned
everything that go wrong with bash, I’ll find out — surprise! There are more
bad things that can happen! Let’s look at another program as an example.
Here we’ve put our code in a function. And if the function
fails, we want to echo “failed”.
So use set -e
at the beginning, and you might think everything should be okay.
But if we run it… this is the output we get
mv: cannot stat './*.txt': No such file or directory success
We get the “success” message again! It didn’t stop, it just kept going. This is
because the “or” (|| echo "failed"
) globally disables set -e
in the
function.
Which is certainly not what I wanted, and not what I would expect. But this is
not a bug in bash, it’s is the documented behavior.
And I think one reason this is tricky is a lot of us don’t use bash very often.
Maybe you write a bash script every six months and don’t look at it again.
When you use a system very infrequently and it’s full of a lot of weird trivia
and gotchas, it’s hard to use the system correctly.
One thing that I sometimes hear is — a newcomer will say “this is hard”,
and someone more experienced will say “Oh, yeah, it’s impossible to use bash.
Nobody knows how to use it.”
But I would say this is factually untrue. How many of you are using bash?
A lot of us ARE using it! And it doesn’t always work perfectly, but often
it gets the job done.
We have a lot of bash programs that are mostly working, and there’s a big
community of us who are using bash mostly successfully despite all the
problems.
The way I think this is — you have some people on the left in this
diagram who are confused about bash, who think it seems awful and
incomprehensible.
And some people on the right who know how to make the bash work for them,
mostly.
So how do we move people from the left to the right, from being overwhelmed by
a pile of impossible gotchas to being able to mostly use the system correctly?
Well, bash has a giant pile of trivia to remember. But who’s good at remembering
giant piles of trivia?
Not me! I can’t memorize all of the weird things about bash. But computers!
Computers are great at memorizing trivia!
And for bash, we have this incredible tool called
shellcheck.
[ Applause ]
Yes! Shellcheck is amazing! And shellcheck knows a lot of things that can go
wrong and can tell you “oh no, you don’t want to do that. You’re going to have
a bad time.”
I’m very grateful for shellcheck, it makes it much easier for me to write
tiny bash scripts from time to time.
Now let’s do a shellcheck demo!
$ shellcheck -o all bad-again.sh In bad-again.sh line 7: f || echo "failed!" ^-- SC2310 (info): This function is invoked in an || condition so set -e will be disabled. Invoke separately if failures should cause the script to exit.
Shellcheck gives us this
lovely error message. The message isn’t completely obvious on its own (and this
check is only run if you invoke shellcheck with -o all
). But
shellcheck tells you “hey, there’s this problem, maybe you should be worried
about that”.
And I think it’s wonderful that all these tips live in this linter.
I’m not trying to tell you to write linters, though I think that some of you
probably will write linters because this is that kind of crowd.
I’ve personally never written a linter, and I’m definitely not going to create
something as cool as shellcheck!
But instead, the way I write linters is I tell people about shellcheck from
time to time and then I feel a little like I invented shellcheck for those
people. Because some people didn’t know about the tool until I told them about
it!
I didn’t find out about shellcheck for a long time and I was kind of mad about
it when I found out. I felt like — excuse me? I could have been using
shellcheck this whole time? I didn’t need to remember all of this stuff in
my brain?
So I think an incredible thing we can do is to reflect on the tools that we’re
using to reduce our cognitive load and all the things that we can’t fit into
our minds, and make sure our friends or coworkers know about them.
I think this is an incredibly valuable community service. The example I shared
about how set -e
got disabled is something I learned from my
friend Jesse a few weeks ago.
They told me how this thing happened to them, and now I know and I don’t have
to go through it personally.
One way I see people kind of trying to share terrible things that their
computers have done to them is by sharing “best practices”.
But I really love to hear the stories behind the best practices!
If someone has
a strong opinion like “nobody should ever use bash”, I want to hear about the
story! What did bash do to you? I need to know.
The reason I prefer stories to best practices is if I know the story about how
the bash hurt you, I can take that information and decide for myself how I want
to proceed.
Maybe I feel like — the computer did that to you? That’s okay, I can deal with
that problem, I don’t mind.
Or I might instead feel like “oh no, I’m going to do the best practice you
recommended, because I do not want that thing to happen to me”.
These bash stories are a great example of that: my reaction to them is “okay,
I’m going to keep using bash, I’ll just use shellcheck and keep my bash scripts
pretty simple”. But other people see them and decide “wow, I never want to use
bash for anything, that’s awful, I hate it”.
Different people have different reactions to the same stories and that’s okay.
I was talking to Marco Rogers at some point, many years ago, and he mentioned
some new developers he was working with were struggling with HTTP.
And at first, I was a little confused about this — I didn’t understand what
was hard about HTTP.
The way I was thinking about it
at the time was that if you have an HTTP response, it has a few parts: a response
code, some headers, and a body.
I felt like — that’s a pretty simple structure, what’s the problem? But of
course there was a problem, I just couldn’t see what it was at first.
So, I talked to a friend who was newer to HTTP. And they asked “why does it
matter what headers you set?”
And I said: “well, the browser…”
The browser!
Firefox is 20 million lines of code! It’s been
evolving since the ’90s. There have been as I understand it, 1 million
changes to the browser security model as people have discovered new and
exciting exploits and the web has become a scarier and scarier place.
The browser is really a lot to understand.
One trick for understanding why a topic is hard is — if the implementation if the
thing involves 20 million lines of code, maybe that’s why people are confused!
Though that 20 million lines of code also involves CSS and JS and many other
things that aren’t HTTP, but still.
Once I thought of it in terms of how complex a modern web browser is, it
made so much more sense! Of course newcomers are confused about HTTP if you
have to understand what the browser is doing!
Then my problem changed from “why is this hard?” to “how do I explain this at all?”
So how do we make it easier? How do we wrap our minds around this 20 million lines
of code?
One way I think about this for HTTP is: here are some of the HTTP request
headers. That’s kind of a big list there are 43 headers there.
My brain does not contain all of those headers, I have no idea what most of
them are.
When I think about trying to explain big topics, I think about — what is
actually in my brain, which only contains a normal human number of things?
This is a comic I drew about HTTP request headers.
You don’t have to read the whole thing. This has 15
request headers.
I wrote that these are “the most important headers”, but what I mean by “most
important” here is that these are the ones that I know about and use. It’s a
subjective list.
I wrote about 12 words about each one, which I think is approximately the
amount of information about each header that lives in my mind.
For example I know that you can set Accept-Encoding
to gzip
and then you might get back a compressed response. That’s all I know,
and that’s usually all I need to know!
This very small set of information is working pretty well for me.
The general way I think about this trick is “turn a big list into a small list”.
Turn the set of EVERY SINGLE THING into just the things I’ve personally used. I
find it helps a lot.
Another example of this “turn a big list into a small list” trick is command line arguments.
I use a lot of command line tools, the number of arguments they have can be
overwhelming, and I’ve written about them a fair amount over
the years.
Here are all the flags for grep, from its man page. That’s too much! I’ve been
using grep for 20 years but I don’t know what all that stuff is.
But when I look at the grep man page, this is what I see.
I think it’s very helpful to newcomers when a more experienced person says
“look, I’ve been using this system for a while, I know about 7 things about it,
and here’s what they are”.
We’re just pruning those lists down to a more human scale. And it can even help
other more experienced people — often someone else will know a slightly
different set of 7 things from me.
But what about the stuff that doesn’t fit in my brain?
Because I have a few things about HTTP stored in my brain. But sometimes I need
other information which is hard to remember, like maybe the exact details of
how CORS works.
And so, that’s where we come to references. Where do we find the information
that we can’t remember?
I often have trouble finding the right references.
For example I’ve been trying to learn CSS off and on for 20 years. I’ve made a
lot of progress — it’s going well!
But only in the last 2 years or so I learned about this wonderful website called
CSS Tricks.
And I felt kind of mad when I learned about CSS Tricks! Why didn’t I know about
this before? It would have helped me!