Chapter 03 — One Thing Well

Write Programs to Work Together

Tenet two: write programs to work together. This one is about interface design. A program that can’t hand off to another program is an island. The Unix answer to that problem was simple: agree on a contract, then build to it.

Here’s the contract in action:

bash~/tutorials/
cat access.log | grep "404" | awk '{print $7}' | sort | uniq -c | sort -rn | head -10

Six programs. cat reads the file. grep filters to 404 lines. awk pulls the seventh field, the URL. sort orders them so duplicates are adjacent. uniq -c counts them. The second sort -rn re-sorts by count, descending. head -10 cuts off after ten results. None of these programs were designed to work together. None of them knows what the others do. They work because they share a contract: lines of text.

That’s composability. Not magic. A shared interface.

CSS custom properties as a shared contract

CSS custom properties are the same idea applied to a stylesheet. Define your values once at the top, in :root. Every rule in every file reads from that source.

The :root block is the contract. Components don’t talk to each other; they both read from the same place.

css~/tutorials/
:root {
  --color-ink:       #1a1f18;
  --color-parchment: #f8f6f0;
  --color-moss:      #5c7a3e;
  --color-fern:      #e0e8d4;

  --font-display: 'Fraunces', serif;
  --font-body:    'DM Sans', sans-serif;

  --space-sm:  0.5rem;
  --space-md:  1rem;
  --space-lg:  2rem;
  --space-xl:  4rem;
}

Change --color-moss in one place and it propagates everywhere: buttons, links, borders, focus rings. The component using it for a border doesn’t need to know about the component using it for a background. They don’t communicate with each other at all. They both read from the same source.

That’s the contract. Your nav component and your card component have never met. They work together because they share an interface.

This is what people mean when they talk about a design system. Not a Figma file. A shared contract that makes independent pieces compose.

JavaScript modules

ES modules are composable because each one declares its interface explicitly. export what you offer. import what you need. A module that exports clean, focused functions is easy to consume. A module that exports one giant object with forty methods is a monolith wearing a .js extension.

Each file is a small program. Each import is a pipe.

js~/tutorials/
// utils/format.js: formatting
export function formatCurrency(amount, locale = 'en-US', currency = 'USD') {
  return new Intl.NumberFormat(locale, { style: 'currency', currency }).format(amount);
}

export function formatDate(date, locale = 'en-US') {
  return new Intl.DateTimeFormat(locale, { dateStyle: 'medium' }).format(date);
}

// utils/dom.js: DOM interaction
export function show(selector) {
  document.querySelector(selector).hidden = false;
}

export function hide(selector) {
  document.querySelector(selector).hidden = true;
}

// main.js: orchestration
import { formatCurrency } from './utils/format.js';
import { show, hide } from './utils/dom.js';

format.js has no knowledge of the DOM. dom.js has no knowledge of formatting. They don’t need to. They work together through clean imports in main.js, which is the only file that needs to know both exist.

This is the Unix pipeline in a module system.

Gulp pipelines

You’ve already written this. Open your Gulpfile from the front-end fundamentals series and look at the styles task:

js~/tutorials/
gulp.task('styles', () =>
  gulp.src('src/scss/main.scss')
    .pipe(sass())
    .pipe(autoprefixer())
    .pipe(cleanCSS())
    .pipe(rename({ suffix: '.min' }))
    .pipe(gulp.dest('dist/css'))
);

sass() doesn’t autoprefix. autoprefixer() doesn’t minify. cleanCSS() doesn’t rename. Each plugin does one thing and passes the result to the next one. .pipe() is the text stream.

When you wrote this, you were implementing McIlroy’s second tenet directly. Not as an abstraction. Not as a thought exercise. You wrote programs to work together, in a Node.js process, because that’s what Gulp is built to do.

Reference