With apologies to the reader. I’ve been thinking about this so long I’m no longer sure I have anything to say.

My manager at a former employer once said that all programs follow the same fundamental pattern.1

Input -> Program -> Output

I think this is an oversimplification, so instead I’ll say this:

There are exactly two design patterns in programming. The rest is commentary.

Pattern 1, a.k.a. Input -> Program -> Output (IPO)

This kind of program takes in an input and produces an output. Examples include pandoc, ffmpeg, gcc, obviously. Less obviously also Git (takes in the file system and returns it in an altered state).

Pattern 2, a.k.a. the Loop

This kind of program is much more common. Instead of taking a single input, it takes a sequence of inputs and returns a sequence of outputs intertwined with it. It may terminate at some point, or not [^2]. Notice that this is just a sequence of Input -> Program -> Output steps, iterated on a state.

Examples are web servers, UIs, games, and operating systems. I think “Where is the loop?” is a question I’ve been trying to answer subconsciously whenever I was trying to understand a complex code base.

Why care?

I claim that if the loop, input, program, and output steps of a program are not clearly separated in design, bad things are likely to happen.

This is a more specific version of the single-responsibility principle, and of not mixing layers of abstraction.

Related patterns

There are well-known design patterns that are related to IPO and loops. An ETL is perhaps the most classic version of IPO. An event loop is a neat way of structuring the loop, giving the input in each iteration the useful standardized representation of an event. An MVC architecture is a way to build IPO loops, where the model is both the input and the output of each iteration.

What about other design patterns, which you might read about in a book? If I’m proposing a theory of everything, I should talk about them too. I think for the most part they are either some version of IPOs or loops, design principles for structuring one of the stages, or powerful hacks that create order out of the chaos that is legacy code.

Another way to think about this is that this is just one very broad frame for thinking about computation. Other frames might be necessary to think about the flow of messages, about caching, or about how to structure a program around a hard algorithmic core.

  1. Reproduced from Compilers, principles, techniques, and tools. Alfred V. Aho. 2012, Addison-Wesley Pub. Co.