Software
Tools in
JavaScript
Good programming is not learned from generalities, but by seeing how significant programs can be made clean, easy to read, easy to maintain and modify, human-engineered, efficient, and reliable, by the application of common sense and good programming practices. Careful study and imitation of good programs leads to better writing.
— Brian Kernighan and P.J. Plauger, Software Tools in Pascal
The best way to learn design in any field is to study examples, and some of the best examples of software design come from the tools programmers use in their own work. In these lessons we build small versions of things like file backup systems, testing frameworks, regular expression matchers, and browser layout engines both to demystify them and to give some insights into how experienced programmers think. We draw inspiration from Brown2011,Brown2012,Brown2016, Mary Rose Cook's Gitlet, and the trilogy of books that introduced the Unix philosophy to an entire generation of programmers Kernighan1979,Kernighan1988,Kernighan1983.
All of the written material in this project can be freely reused
under the terms of the Creative Commons - Attribution license,
while all of the software is made available under the terms of
the Hippocratic License;
see
All proceeds from this project will go to support the Red Door Family Shelter.
Who is our audience?
Every lesson should be written with specific learners in mind. These three personas are ours:
-
Aïsha started writing VB macros for Excel in an accounting course and never looked back. She has spent the last three years doing front-end JavaScript work and now wants to learn how to build back-end applications. This material will fill in some gaps in her programming knowledge and teach her some common design patterns.
-
Rupinder is studying computer science degree at college. He has learned more about the theory of algorithms than about building software, and while he uses Git and unit testing tools on a daily basis, he doesn't feel he understands how they work. This material will give him a better understanding of those tools and of how to design some of his own.
-
Yim builds mobile apps for a living but also teaches two courses at Rupinder's college: one on full-stack web development using JavaScript and Node (which they are quite proud of), and another titled "Software Design". They are frustrated that so many books about the latter talk about the subject in the abstract and use examples that their students can't relate to. This material will fill those gaps and give them starting points for a wide variety of course assignments.
Like these three personas, readers should:
-
Know how to write JavaScript programs using loops, arrays, functions, objects, and classes.
-
Know how to create static web pages using HTML and CSS.
-
Be able to install Node on their computer and run programs with it from the Unix or Windows command line.
-
Use Git to save and share files. (It's OK not to know the more obscure commands.)
-
Be able to explain what a tree is and how to visit the nodes in one recursively. (These are the most complicated data structure and algorithm we don't explain.)
What tools do we cover?
Programmers have invented a lot of tools to make their lives easier. This volume focuses on a few that individual developers use while writing software; we hope that the second volume will explore those used in the applications that programmers build.
Title | Content |
---|---|
Using callbacks to manipulate files and directories | |
Using promises to manage delayed computation | |
Testing software piece by piece | |
Archiving files with directory structure | |
Loading, saving, and manipulating tables efficiently | |
Using patterns to find things in data | |
Turning text into code | |
Generating HTML pages from templates | |
Updating files that depend on other files | |
Figuring out what goes where in a web page | |
Managing source files that have been broken into pieces | |
Loading source files as modules | |
Checking that code conforms to style guidelines | |
Modifying code to track coverage and execution times | |
Generating documentation from comments embedded in code | |
Turning many files into one | |
Getting and installing packages | |
Assembling and running low-level code | |
Running programs under the control of a breakpointing debugger | |
Where we have been and where you could go next |
What ideas do we cover?
The glossary in
-
How to turn a program into a data structure that can be processed like any other.
-
How we can process a program like any other piece of text.
-
How programs are executed and how we can control and inspect their execution.
-
What design patterns are and which ones are used most often.
-
How we can analyze programs' performance in order to make sensible design tradeoffs.
-
How to find and run pieces of code when we don't know in advance that they exist.
How are these lessons laid out?
We display JavaScript source code like this:
for (const thing in collection) {
console.log(thing)
}
and Unix shell commands like this:
for filename in *.dat
do
cut -d , -f 10 $filename
done
Data and output are shown in italics:
Package,Releases
0,1
0-0,0
0-0-1,1
00print-lol,2
00smalinux,0
01changer,0
We occasionally wrap lines in source code in unnatural ways to make listings fit the printed page.
Where we need to break lines of output for the same reason,
we end all but the last line with a single backslash \
.
We also sometimes use ...
to show where lines have been omitted to shorten listings.
The full listings are all available in this project's Git repository
and on our website.
Finally,
we write functions as functionName
rather than functionName()
;
the latter is more common,
but people don't use objectName{}
for objects or arrayName[]
for arrays,
and the empty parentheses makes it impossible to tell
whether we're talking about "the function itself" or "a call to the function with no parameters",
which is confusing when we're passing functions as arguments.
How did we get here?
In the early 2000s, the University of Toronto asked Greg Wilson to teach an undergraduate course on software architecture. After delivering the course three times he told the university they should cancel it because of a lack of useful material: between them, the dozen textbooks he had purchased with the phrase "software architecture" in their titles devoted a total of less than 30 pages to describing the designs of actual systems.
Frustrated by that, he and Andy Oram persuaded some well-known programmers to contribute a chapter each to a collection called Beautiful Code Oram2007, which went on to win the Jolt Award in 2007. Entries in the book described everything from figuring out whether three points are on a line to core components of Linux and the software for the Mars Rover, but the breadth that made them fun to read also meant they weren't particularly useful for teaching.
To fix that, Greg Wilson, Amy Brown, Tavish Armstrong, and Mike DiBernardo edited a four-book series between 2011 and 2016 called The Architecture of Open Source Applications. In the first two volumes, the creators of 50 open source projects described their systems' designs; the third book explored the performance of those systems, while in the fourth and final volume, contributors built scale models of common tools as a way of demonstrating how those tools worked. These books were closer to what an instructor would need for an undergraduate class on software design, but still not quite right: the intended audience would probably not be familiar with many of the problem domains, and since each author used the programming language of their choice, much of the code would be hard to understand.
Software Tools in JavaScript is meant to address these shortcomings: all of the code is written in one language, and the examples are all tools that programmers use daily. Most of the programs are less than 60 lines long and the longest is just over 300; we believe each chapter can be covered in class in 1-2 hours, while the exercises range in difficulty from a few minutes to a couple of days.
How can people contribute?
If you would like to improve what we have or add new material,
please see the Code of Conduct in
Who helped us and inspired us?
This book is dedicated to Brian Kernighan, who taught us all how to write about software.
We are very grateful for feedback from Darren McElligott and Evan Schultz, and to the creators of EJS, Emacs, ESLint, Glosario, GNU Make, LaTeX, Node, NPM, Standard JS, WAVE, and all the other open source tools we used in creating these lessons. If we all give a little, we all get a lot.