The Three-Things Theorem of function intention
- Publish Date
- Authors
- Sam Jones

Origami, the ancient art of paper folding, has gone through a modern mathematical renaissance. The folding process was originally passed down between generations orally. Recently, though, artists have developed a way to document the steps to fold a shape with a diagram called a crease pattern.

New theorems have emerged to determine whether a crease pattern can be folded. For example, a crease pattern must be two-colorable. Each region in the crease pattern can be colored with one of two colors in such a way that no two regions of the same color share a dividing crease.
The art of origami has been reduced to simple, elegant, binary theorems that represents its integrity.
A theorem proving code intention
We can think of our source files as crease patterns used to diagram the intention of the systems we build. We can then define theorems to help us ensure that our diagrams, our source files, have integrity. Each function should have a clear intention, and to prove that, I’d like to introduce The Three-Things Theorem of Function Intention.
A function should do one of these three things
Coordinate
Coordinate the actions of other small, well-named units by using a defined control flow mechanism.
function coordinator () {
return callFirstFunction
.then(res => callSecondFunction(res))
.then(res => callThirdFunction(res))
}
A coordinating function is responsible for creating a pipeline of actions, for calling other well named functions. It manages interactions and that’s it. Just like a good people manager, a coordinating function becomes less effective when it’s splitting time actually doing the work that should be a delegated task.
Calculate
Calculate a very specific value, state, or object in our system.
function simpleCalculator (val1, val2, val3) {
return Math.pow(Math.abs(val1 + val2) * val3, 2)
}
function domainObjectCalculator (input) {
return { output: _.get(input, 'foo.bar.baz') }
}
Calculating a value doesn’t just need to be limited to a mathematical equation. A calculating function can also be used for transitions in domain concepts, like when we “calculate” new objects in our system.
Control
Encapsulate and expose ways to control the flow of our application.
function until (condition, run) {
return function method (subject) {
if (!condition(subject)) {
return method(run(subject))
} else {
return subject
}
}
}
function nComplete(n) {
return ...
}
function calculateNewN(oldN) {
return ...
}
until(nComplete, calculateNewN)(5)
We can build functions that perform the control flow through our applications. They can hold conditional logic, looping, and anything algorithmic. This allows our domain functions to focus on performing a specific task. until
is an example of an fairly complex path through our application, but structuring it as a higher-order-function allows you to prove that it works with tests that aren’t mixed up by other complex domain logic. All the pieces can be tested in isolation, making them easier to develop, change, and understand.
Learn more
-
About this idea in a talk about code design that Sam gave called JavaScript Is Too Convenient
-
About origami from an amazing talk given by Robby Kraft on software built for origami artists
Sam Jones
- Status
- Double Agent
- Code Name
- Agent 0019
- Location
- Philadelphia, PA