Negative Architecture
Guiding software by flipping figure and ground
You’ve probably seen this picture before. It’s one of several images that people use to show how perception works. You either see a vase or two faces looking at each other. In the terminology of Gestalt Psychology, one becomes the figure and the other becomes the ground. We can switch between the vase and the faces but we can’t see both at once. The distinction we automatically make is that one is the figure, the object of our perception, and the other is the background, or ground.
It might not seem that paying attention to the ground is worthwhile. Most of us either see the vase or the faces and we’re lucky if someone points out that there is another way of seeing things. The book Drawing on the Right Side of the Brain by Betty Edwards leverages this knowledge of ground to help people become better at drawing. One of her exercises involves deliberately not paying attention to the figure. Instead, she tells students to draw the contour and forget that they are drawing a person or a chair. When you draw the contour you are rendering what you see as pure shape without part of your brain telling you it is a person or an object. When your brain categorizes it starts to embellish. We all know what a person looks like so we work from that memory rather than the shape that we actually see.
In software, something very similar happens. Any system we design is made of pieces - components, frameworks, libraries or services. It doesn’t matter whether we make them or use them. Each of them does something for us, and the thing that it does is the figure.
What’s the ground?
The ground is the list of things that it doesn’t do - the things we are absolutely sure that it doesn’t do.
A great example of this from functional programming is the IO Monad in Haskell. Any piece of code in your application is either in the IO Monad - in which case it can do IO - or, it is outside in the pure part of your application. There you have a guarantee that it will not do IO. That guarantee is useful. You can look at that area of your code and know that you have one less thing to think/worry about.
These guarantees form a negative architecture - a set of things that you know can’t happen in various pieces of your system. The potential list is infinite but that doesn’t stop this perspective from being useful. If you’re using a particular persistence technology in one part of your system, it is valuable to be able to say that it is only used in that place and no place else in the system. The same can be true of other technologies. Knowing what something is not able to do reduces the number of pitfalls. It puts architecture on solid ground.