It’s taken me a while to appreciate Edsger W. Dijkstra. I had a professor in college who used to comically refer to him as “fearless leader” whenever he mentioned some piece of bombastic wisdom from him. But, beyond the bombast, Dijkstra’s contributions to computer science and software engineering were seminal. Even though I didn’t pay as much attention to his ideas as I should’ve, they influenced me indirectly and one of them led me to ignore some avenues of thought that I wish I’d pursued earlier.
One of the things that Dijkstra spoke about often was anthropomorphism—seeing code and systems as human-like; things with awareness and intention. The short story is: Dijkstra was against it. He saw it as a sign of cluttered thinking; something that could lead us down bad paths. He wasn’t wrong. But, I think that, to use an old metaphor, this is “throwing the baby out with the bath water.” Imagining that our systems are alive can be a very useful frame, as long as it isn’t the only frame we have.
Here's an example.
One thing that I’ve done a few times with teams is ask people to role-play various parts of the system. The team might talk every day about a pricing service but what is it like to imagine that you are the pricing service? As you’re reading this now, think of some part of the system you work on and say “I am the X component/service. I feel good/ bad today because..”
Try it. You might be surprised by what you discover.
As I think about various systems I’ve worked on, and run through that exercise, I think about what they were like the last time I worked on them. I think about their recent change history, the way they interact with other systems and how that might feel or be seen if that system were a living, thinking being.
You might be wondering what the point of this is. I think the best way to approach it is to start with the idea that design is deep. In The Mythical Man-Month, Fred Brooks said:
I will contend that conceptual integrity is the most important consideration in system design. It is better to have a system omit certain anomalous features and improvement, but to reflect one set of design ideas, than to have one that contains many good but independent and uncoordinated ideas.
If we throw away the word “concept” for a second and focus on “integrity” we can see how this relates to design as a whole.
A building can have structural integrity, so can a body, a car or a tree. If you’re in an accident and break your arm, you are in pain. You definitely don’t feel very good, and that is what it is like when you react as a whole. If we can see these patterns in structure and behavior across many types of systems, why not use them to inform our notion of design? If we do, we can leverage empathy. How do you imagine your code feels based upon what you did yesterday? :)
It feels weird for me to write about this, because at one level it seems like it would be too mystical or woo-woo, but I’ve long had the sense that conceptual frames are tools, and there’s no one right frame for all purposes. Given that, the best thing we can do is have a whole palette of frames that we can choose from when we need to, and become very good at switching back and forth among them.
One of the most fascinating frames that I use is one from the philosopher and sociologist Bruno Latour. Brian Marick introduced me to his ideas a long time ago and I didn't realize then how much they would impact me.
Latour developed something that he called Actor-Network Theory in the 1980s. The crux of it is that we can gain a deeper understanding of social systems if we add objects in the environment to our analysis. As an example: a social system isn’t just six people in a team, it’s the team and the meeting software they use and the subject matter they discuss, along with all of their other tools. You can graph these relationships and see how we affect each other transitively through objects like calendars and pull requests. As if that weren’t strange enough, Latour goes further in his framing. He treats objects in the environment as if they were agents. In a very operational sense, I don’t think that’s far from the truth. The actions of living things are reactions to their environment. Code reacts/acts too, just much more slowly.
We can use that framing and see what it gives us. In my experience, it has been: empathy and insight.
In a sense, this is nothing new. Sailors sometimes talk about their ships as if they were alive. When I talk to artists, they often anthromorphize their art. They ask: what does this thing need?
We can definitely do this with subsystems in any system we are developing, but we can go further.
Imagine all of the code your organization develops as a single entity. Give it a name.
And no! Don't use the name Titanic! Pick a human name.
How does that entity feel today?
The nicer you are to it, the nicer it will be to you.