-->
George Fairbanks - IEEE Software - The Pragmatic Designer: Intellectual Control
IEEE Software - The Pragmatic Designer: Intellectual Control
Jan 14, 2019 | George Fairbanks
This column was published in IEEE Software, The Pragmatic Designer column, 14 January 2019, Vol 36 number 1. It reached the home page of Hacker News but got few comments.
In the early days of software engineering, Edsger Dijkstra warned us not to let the size and complexity of our programs cause us to lose “intellectual control” due to the limited nature of our minds. To my knowledge, he never defined precisely what intellectual control was. Our software today is staggeringly larger than the programs of the 1960s, so does that mean we have it under our intellectual control, or did we find ways to make progress without Dijkstra’s high standards?
I see signs that we have some software that is under intellectual control and other software that is not. In this column, I’m going to discuss how we can recognize these two categories, what happens when engineers on a project have different attitudes about intellectual control, some advice on when we probably should insist on it, and some ideas about how we achieve it.
Pre-publication draft. Please click this official link so your view counts in the IEEE's records of article views – plus the IEEE site has profesionally typeset PDFs.
It’s difficult to have a conversation about something as abstract as control over programs. To ease into it, we can use a metaphor from Rich Hickey’s presentation called Simple Made Easy. He asked us to imagine driving a car on a road with guardrails. In this metaphor, the guardrails are tests and driving the car is us writing programs. He then wondered if it’s OK to successfully arrive at our destination after hitting the guardrails during the journey. His audience laughed because having a car under control means we are able to drive without hitting the rails.
The laughter had a nervous quality to it because we often write code that ends up breaking the tests, so perhaps we don’t really have as much control as we thought. Are we monkeys at typewriters writing random programs hoping one will eventually pass the tests? No, we have some expectation that this code will do what we want. Failing tests are a signal that we didn’t understand the program as well as we needed to.
If we’re honest with ourselves, the way we write software today has a little bit of that monkey quality. We don’t get everything straight in our minds before typing, but neither are we just throwing programs at the tests without thinking. In my experience, we use a proposed change to a program as a little hypothesis, “I think perhaps this is the way things work,” and then run the tests to get feedback on that hypothesis. Over time, we build up a theory in our heads of how the program works. That theory gives us intellectual control.
Let me contrast intellectual control with another kind of control you may recognize. Imagine that you start looking at an existing codebase with tests, one where the original authors have departed, so you cannot ask them questions. You develop hypotheses about how the code works and gather evidence by seeing whether or not your code changes break the tests.
But this time, you never get that “Aha!” moment that results in a general understanding of the program. Your hypotheses never add up to a theory. You are still making forward progress because you can try several things until you find one that keeps the tests passing, but you keep hitting those guardrails and they are the primary things keeping you from failure.
My intent is to reveal these two approaches to building software, which I’ll call intellectual control and statistical control, so that we can have a discussion about their natures and when we should use one or the other. To some extent, I’ve exaggerated the distinction between them so that we can see things more clearly. We rarely find ourselves fully invested in one approach or the other. More commonly, there are parts of the code that mostly make sense to you and other parts where you’re mostly relying on the tests to keep you on track.
You can have enough control over the car that you don’t hit the guardrails or you can lack control and hit the rails a few times along the journey. Both get you to your destination. In software development, sometimes we are able to obtain intellectual control because we have built up a theory of the program and, therefore, are generally able to write code without breaking the tests. Other times, we cannot find that general theory, and so we’re relying on the tests to give us statistical confidence that it seems to be working.
But why call it statistical control? Another of Dijkstra’s famous sayings is that tests can show the presence of bugs but not their absence. Tests are a sampling of the output space, so passing tests provide a statistical confidence that the program behaves as expected. Passing tests...