-
Notifications
You must be signed in to change notification settings - Fork 0
/
communicating-with-humans.html
89 lines (89 loc) · 8.32 KB
/
communicating-with-humans.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
<head><title>Communicating With Humans</title><link href="tufte-css/tufte.css" rel="stylesheet" /><script src="http:https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML" type="text/javascript"></script></head><body><h1>Communicating With Humans</h1><p class="subtitle"><a href="about-me.html">John Jacobsen</a></p><div><p><em>If nobody but me likes it, let it die. — <a href="http:https://www.informit.com/articles/article.aspx?p=1193856">Knuth</a></em></p><p><figure><a href="img/marg-printed.jpg"><img src="img/marg-printed.jpg" /></a></figure></p><p><span>This is the fifth post in a <a href="/clojure/2014/07/03/an-advanced-clojure-workflow/">series</a> about my Clojure workflow.</span></p><p>When you encounter a new codebase, what best allows you to
quickly understand it so that you can make effective changes to
it?</p><p>I switched jobs about six months ago. There was intense
information transfer both while leaving my old projects behind,
and while getting up to speed with new ones. I printed out a lot
of code and read it front-to-back, quickly at first, and then
carefully. I found this a surprisingly effective way to review
and learn, compared to my usual way of navigating code on disk
and in an editor solely on an as-needed basis. </p><p>If this (admittedly old-school) way of understanding a program
works well, how much better might it work if there was enough
prose interspersed in amongst the code to explain anything
non-obvious, and if the order of the text was presented in such
a way as to aid understanding? </p><p>What is the target audience of computer programs, anyways? It is
clearly the machines, which have to carry out our insanely
specific instructions... but, equally clearly, it is also the
humans who have to read, understand, maintain, fix, and extend
those programs. It astonishes me now how little attention is
paid to this basic fact. </p><p><span>In addition to communicating, we also have to <em>think carefully</em> about our work. While not every
programming problem is so difficult as to merit <a href="https://www.youtube.com/watch?v=f84n5oFoZBc"> a year’s worth
of contemplation</a>, any software system of significant size requires continual
care, attention, and occasional hard thinking in order to keep
complexity under control. The best way I know to think clearly
about a problem is to write about it – the harder the
problem, the more careful and comprehensive the required
writing. </span></p><p>Writing aids thinking, because it is slower than
thought... because you can replay thoughts over and over, iterate
upon and refine them. Because writing is explaining, and because
explaining something is the best way I know to learn and
understand it. </p><p><span><a href="http:https://en.wikipedia.org/wiki/Literate_programming">Literate Programming</a> (LP) was invented by Donald Knuth in the 1980s as a way to
address some of these concerns. LP has hardcore enthusiasts
scattered about, but apparently not much traction in the
mainstream. As I have gotten more experience working with
complex codebases, and more engaged with the craft or
programming, I have become increasingly interested in LP as a
way to write good programs. Knuth takes it further, considering
the possibility that programs are, or could be, <em>works
of literature</em>. </span></p><p>Knuth’s innovation was both in realizing these possibilities and
in implementing the first system for LP, called WEB. WEB takes a
document containing a mix of prose and code and both typesets it
in a readable (beautiful, even) form for humans, and also orders
and assembles the program for a compiler to consume. </p><p><span>Descendents and variants of WEB can be found in use
today. My favorite for Clojure is currently <a href="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/gdeer81/marginalia">Marginalia</a>,
originally by Michael Fogus and currently maintained by Gary
Deer. </span></p><p><span><a href="http:https://web.archive.org/web/20090102151452/http:https://www.perl.com/pub/a/tchrist/litprog.html">Purists of LP will disagree</a> that systems like Marginalia, which do not support reordering
and reassembly of source code, are “true” Literate
Programming tools; and, in fact, there is a caveat on the
Marginalia docs to that effect... but what Marginalia provides
is good enough for me: </span></p><p><ol><li>Placement of comments and docstrings adjacent to the
code in question; </li><li>Beautiful formatting of same; </li><li>Support for Markdown/HTML and attachment of JavaScript
and/or CSS files; therefore, for images, mathematics (via
MathJax) and graphing (see next blog post). </li></ol></p><p>The result of these capabilities is a lightweight tool which
lets me take an existing Clojure project and, with very little
extra effort, generate a Web-based or printed/PDF artifact
which I can sit down with, learn from, and enjoy contemplating.</p><p><h1>Marginalia in Action:</h1><p><figure><a href="img/marg-screenshot.png"><img src="img/marg-screenshot.png" /></a></figure></p><p><figure><a href="img/emacs-screenshot.png"><img src="img/emacs-screenshot.png" /></a></figure></p></p><p><h1>The Notebook Pattern</h1><p>I often start writing by making simple statements or questions: </p><p><ol><li>I want to be able to do \(X\).... </li><li>I don’t understand \(Y\).... </li><li>If we had feature \(P\), then \(Q\) would be easy.... </li><li>How long would it take to compute \(Z\)? </li></ol></p><p><span>Sentences like these are like snippets of code in the
REPL: things to evaluate and experiment with. Often these
statements are attached to bits of code — experimental
expressions, and their evaluated results. They are the
building blocks of further ideas, programs, and chains of
thought. In <a href="/clojure/2014/08/03/marginalia-hacks/">my next post</a>, I’ll talk about using Marginalia to make small notebooks
where I collect written thoughts, code, expression, even
graphs and plots while working on a problem. This workflow
involves some Marginalia hacks you may not see elsewhere. </span></p><p>Meanwhile, here are some quotes about LP:</p><p>“Instead of writing code containing documentation, the
literate programmer writes documentation containing
code.... The effect of this simple shift of emphasis can be so
profound as to change one’s whole approach to programming.”
—Ross Williams, FunnelWeb Tutorial Manual, p.4. </p><p>“Knuth’s insight is to focus on the program as a message
from its author to its readers.” —Jon Bently,
“Programming Pearls,” Communications of the ACM, 1986.</p><p><span>“... Literate programming is certainly the most
important thing that came out of the TeX project. Not only
has it enabled me to write and maintain programs faster and
more reliably than ever before, and been one of my greatest
sources of joy since the 1980s—it has actually been
indispensable at times. Some of my major programs, such as
the MMIX meta-simulator, could not have been written with any
other methodology that I’ve ever heard of. The complexity was
simply too daunting for my limited brain to handle; without
literate programming, the whole enterprise would have flopped
miserably.” —Donald Knuth, <a href="http:https://www.informit.com/articles/article.aspx?p=1193856&rll=1">interview</a>, 2008.</span></p></p></div><div><p><a href="about-me.html">about</a>|<a href="content.html">all posts</a></p><p>© 2016 <a href="about-me.html">John Jacobsen</a>. Created with <a href="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/eigenhombre/unmark">unmark</a>. CSS by <a href="https://edwardtufte.github.io/tufte-css/">Tufte-CSS</a>.</p></div><script type="text/javascript">var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-40279882-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script');
ga.type = 'text/javascript';
ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http:https://www')
+ '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
})();</script></body>