Reject Agility, Embrace Specification

9 min read Original article ↗

22 Jun 2026

Here's a reproduction of the infamous "Waterfall Diagram", from the landmark paper Managing the Development of Large Software Systems (Royce, 1970):

SYSTEM REQUIREMENTS SOFTWARE REQUIREMENTS ANALYSIS PROGRAM DESIGN CODING TESTING OPERATIONS

Behold, the enemy of Agile! Although, in its defence...

  • This diagram was the second of 9 figures, each showing a more sophisticated and realistic approach to software development than the last.
  • It's almost 60 years old ("Program Design" and "Coding" is a distinction that makes a lot more sense in the era of batch compilation)
  • It's much better than my realistic diagram of the Agile Model:
CODING NONSENSICAL AGILE CEREMONY

(Keen-eyed readers will note that unlike the Agile Model, the Waterfall Model actually terminates...)

But I bring up the "Waterfall Diagram" because I am writing about specifications, and in doing so I inevitably open myself to accusations of Waterfallism. For just as the fall of Rome marked the beginning of the Dark Ages of Western Europe, so too has the publication of the Agile Manifesto marked the Dark Ages of Software Engineering; our present age of superstitious planning rituals, and broad literary collapse. And to argue in this Dark Age that extensive writing - or indeed thinking - should precede or accompany the development of computer programs is to invite hostility.

And so I will face this foursquare; and much as the Anglo-Saxons once looked upon the ruins of Roman Civilisation, I have looked upon the Ruins of Software Engineering (beautifully preserved in the aforelinked PDF scan), and I have striven to find a new way forward. In later years the Renaissance was sparked by the re-discovery of the classics; and it will be the same, I think, for us.

Specifications in a Modern Style

Why won't people write specs? People claim that it's because they're saving time by skipping the spec-writing phase. They act as if spec-writing was a luxury reserved for NASA space shuttle engineers, or people who work for giant, established insurance companies. Balderdash. First of all, failing to write a spec is the single biggest unnecessary risk you take in a software project. It's as stupid as setting off to cross the Mojave desert with just the clothes on your back, hoping to “wing it.” Programmers and software engineers who dive into code without writing a spec tend to think they're cool gunslingers, shooting from the hip. They're not. They are terribly unproductive. They write bad code and produce shoddy software, and they threaten their projects by taking giant risks which are completely uncalled for.

— Joel Spolsky, Painless Functional Specifications

So what do I mean by specifications, or specs? Broadly; non-code artefacts that describe software problems and solutions. It can describe a vision of software before it exists, or be an audit of a current system. But its purpose is to describe how software should behave, how it should be built, and where it should sit in the world.

(Some might prefer to call these "requirements", or "design docs". IEEE defines an alternate model on page 46 of this document which may suit you just as well (or better). If your terminology or taxonomies differ - use them! My goal is not to convince you to follow my model precisely; the goal is to convince you that yours is worth specifying.)

Kinds of Specs

Operational Functional Technical COMPUTER CODE

Software exists in multiple contexts, from corporate strategy to code, and rarely will one document satisfy everyone. A technical specialist likely cares little about the business goals software is meant to meet, and likewise board members might be bored to tears hearing about algorithms and architecture. And again, the way I've split contexts here is not prescriptive; words like "product" or "systems" may appear in your own definitions, or you may have four instead of three; season to taste. The important things are:

  1. Different contexts are of interest to different stakeholders.
  2. An outer context provides a foundation for the inner context.
  3. Recognising that a change in an outer context will trigger a change in inner contexts.

(There is arguably an even larger context missing here; the Strategic Business context. To this I will do something a consultant should never do, and admit I do not have enough experience here to intelligently talk about it.)

And finally it's worth noting that the borders between different contexts will always be blurry, and a good spec author welcomes feedback and input. If something in say the functional specs turns out to be infeasible technically, this is useful information! Communicate, and do not build on things blindly.

Operational Specs

All software exists in some operational reality, larger than itself.

  • User roles: internal and external (i.e. Suppliers, Customers)
  • Workflows (i.e. Order Processing, Manufacturing)
  • Constraints (i.e Physical, Logistic, Regulatory)

I find operational requirements require the most eliciting; they are the least likely to exist formally and the most likely to have developed organically and live in people's heads.

Functional Specs

Once grounded in an operational context, one can begin to think how the software works from a user's perspective.

  • Scenarios / User stories
  • User interfaces (wireframes)
  • High-level data flows (integrations, reporting, etc.)
  • Non-Goals - what the system will not do, and why

If you only write one level of spec, make it Functional Specs. It most clearly defines what success is in terms of the software being written, and it is the one most likely to be read by both technical and non-technical stakeholders.

Technical Specs

The internal implementation of the software; an explicit reckoning of technical tradeoffs and decisions.

  • Tech stack choices
  • Dependency justification (I go into more detail here)
  • Core Modules
  • Key Algorithms and Data Structures
  • Data schemas (SQL, JSON, binary...)
  • High Level API (HTTP Routes, Wire Protocols...)

Specs at this level can be very useful as input for AI tooling, to help create working prototypes and first drafts. Discovering your assumtpions are broken is best done sooner than later!

Frequently Encountered Objections

No one will read them.

There is an onus on the reader, and there is an onus on the writer

The writer must make the specs engaging. Diagrams, links, quotes, bullet points, and even fundamentals like the correct use of paragraphs (now extinct on LinkedIn) and relevant headings. The author must be able to point to some division of the spec (whether file, web page, section etc) and say "Stakeholder; this section is relevant to you!".

As for the reader, I will make this (perhaps controversial) point - a base level of literacy is a prerequisite for good software. At time of writing, serious software starts at six figures and goes on from there. They are famously hard to estimate and budget for. Given this, if decision makers cannot trouble themselves to spend time on a well-written document, with diagrams and bullet-points, that defines what success looks like in a way that is relevant and understandable to them, I question how important the project really is to them anyway.

No volume of meetings will ever make up for an unwillingness to read and write

"Upfront Design Does Not Work."

I very much agree that specifications should not be etched in stone, and should be malleable. "No plan survives first contact with the enemy" and all that. But to march into battle with no plan at all is to invite failure. And so I argue you should do an upfront design, but do not over specify; you must retain the capacity to react to changes. Know that it will be changed by contact with reality; by things yet unforeseen. And favour breadth over depth: it is better to cover everything, than cover any one thing in detail.

"A sufficiently detailed spec is code"

An objection most commonly made by those programmers who see specs as a bureaucratic burden imposed on them from above. Of course in practice programmers themselves instinctively know this not to be true; or READMEs, man-pages, API documentation would have no reason to exist in anything open-source.

Anything sufficiently complex must be reasoned about at different levels. We could equally make the observation that all other natural sciences are just the children of physics; but much of our advanced civilisation is, of course, built on the reasoning of complex natural phenomena at levels far above the atom.

Specifications: An Effort Worth Making

The hardest single part of building a software system is deciding precisely what to build. No other part of the conceptual work is so difficult as establishing the detailed technical requirements, including all the interfaces to people, to machines, and to other software systems. No other part of the work so cripples the resulting system if done wrong. No other part is more difficult to rectify later.

— Fred Brooks, No Silver Bullet

What could go wrong? What's wrong? Which question would we rather ask? The former, because code, like steel, is less expensive to change while it's hot. A problem solved in production is many times more expensive than a problem solved in implementation, or a problem solved in design.

TigerStyle

Everything in software is done in a context. Specs make these contexts concrete.

The programmer, sure of the functional context in which he operates, is free to devote all his skill in the making of software that is reliable and fast. He is not burdened by doubt ("is this really what the business wants?"), his thoughts not distracted by the consideration of contexts other than his own.

And so, I leave you with this; if you enjoy wasting money and projects that never end, by all means specify nothing. Rely on an incoherent picture; fragments scattered across emails, meetings, and chats; and hope that expensive technical resources can piece this all together, and somehow delve into your mind to recreate the image you had.

But if you want to succeed, what success looks like must be defined. And this picture of success must be refined still further until it can form the basis of a technical execution. Requirements exist regardless of whether they are specified or not; you might as well write them down.