By Nate Abele
"Design is the rendering of intent." — Jared M. Spool
When we talk about software design, we don't talk about the pixels that appear on the screen, but of the system behind the pixels, that brings them into being: how data flows through it, and how its components fit together.
...
Axioms are fundamental, self-evident truths. These truths will serve as the bedrock on which we can build a philosophy of, and approach to, software design.
Software design is about optimizing for two dramatically different audiences, with complementary capabilities but diametrically opposing interests: computers and brains — specifically, human brains. What follows are the capabilities of each of the two audiences: what each is good at (and, conversely, what the other is terrible at).
- Ambiguity
- Inference
- Intuition
- Complexity
- Lots of data
- Dynamism — many things changing at once, continuously
- Precision
- Repetition
...
[Main book part goes here-ish...]
...
Simple, well-defined units with clean boundaries are easy to reason about independently, but combine even a few of these units, and the number of possible interactions between them quickly grows by orders of magnitude (see also: the halting problem). @TODO: Find a reference that better explains the combinatorially-explosive growth of possible machine states relative to a linear increase in program size, and how it relates to the halting problem.
Unknown unknowns — Unexpected failure modes are, by definition, unexpected. We can only write tests for failure we can anticipate.
Integration complexity: one service invokes another using a callback that invokes a third, which, due to an unanticipated set of conditions, unexpectedly re-invokes the first, resulting in indirect mutual recursion.
From the prior two points (unexpected failures & integration complexity), we can correctly infer that it is unreasonable to expect that (a) all units will always be called with expected values, or (b) that all units will correctly handle (and be test-covered for) all values that will be passed to it in production.
Even in a strongly-typed, pure functional language, automated testing only provides a few programmer-predicted snapshots of behavior within a universe of possible outcomes. Long-term, the only real solution for guaranteed software reliability is something like total functional programming, or other sub-Turing-complexity techniques that facilitate verification analogous to mathematical proofs; see also: Epigram, Coq.
An aggregated collection of resources which may or may not be referenced in the book itself.
- React Stateless Functional Components: Nine Wins You Might Have Overlooked
- Machine-checked explicit state: An arrow in the heart of complex web applications
- The Mostly Adequate Guide to Functional Programming — Dr. Boolean (aka Brian Lonsdorf)
- Making Impossible States Impossible — Richard Feldman
- Beyond series — Anthony Ferrara
- Boundaries — Gary Bernhardt
- The Clean Architecture — Uncle Bob
- What's Functional Programming All About?
- Simple Made Easy — Rich Hickey
- The Value of Values — Rich Hickey
- The Mythical Man Month — Fred Brooks
- The Design of Design — Fred Brooks
- Media for Thinking the Unthinkable — Bret Victor
- The Future Doesn't Have to Be Incremental — Alan Kay
“Extracting patterns from today's programming practices ennobles them in a way they don't deserve.” — Alan Kay