The process of building software wasn’t always called engineering. In the early 1970s, men started pushing women out of the software profession—the more masculine a field, the higher the pay—and part of the strategy for that masculinization was associating it with other traditionally masculine fields, like civil engineering and mathematics.
But building software isn’t really like building a bridge or a train. It’s more like writing a book. When you build a bridge, you’re damn sure the thing isn’t going to fall down the first rush hour it gets. Trains don’t randomly explode. Huge amounts of effort go into measuring tolerances, analyzing possible failure modes, testing the limits of the parts, making assurances, and generally making sure the bloody thing works.
Sometimes software is built in that way, but mostly, people writing code just don’t care whether it’s bulletproof. The field doesn’t even agree that correctness—that is, given input of a certain type, the output of a program will be well-defined—is a property worth trying to achieve! We know about many different ways that computers can aid us in writing correct programs: type checkers, static analyzers, proof assistants, automatic test generators, and so on. But people still write reams and reams of code without those tools and without a second thought to their usefulness.
And they’re right to do so! Because most software doesn’t need to be engineered the way a municipal water supply does. It just needs to sort of work most of the time.
Most software doesn’t need to be engineered, it just needs to sort of work.
Software is a tool. A complex, oddly-shaped tool, but a tool. It exists as an extension of our hands, a thing we use to reach into the world, sense it and affect it. Meaning there’s a human present. Wherever the software goes, a human’s just behind. So if the tool isn’t working how they want it to, or if it’s broken in some way, they work around it.
Not all software has the safety net of a human’s hand. Maybe 80% of software is like this: web sites, video games, cash registers, ticket machines are all things that can fail and be worked around. The other 20% of software really is (and should be) engineered in a rigorous sense: power plant control systems, banking, space flight, telecom. Things that can’t fail, or things that work too quickly and finally for a human to fix as it works.
So if building software isn’t engineering, what is it?
I believe that the core skills relevant to the construction of software are communication and creativity. We communicate with coworkers, customers, users, and other programmers to identify needs and learn what work needs to be done. It is then our task to generalize and simplify, which is a fundamentally creative process.
Being good at building software means communicating effectively and being creative. But neither of those skills are emphasized at all in most CS courses. Discrete math, data structures & algorithms, operating systems, databases: most programmers will use specific knowledge gained in at least one of those areas, but nowhere represented are the skills vital to every programmer (with the notable exception of Dev Bootcamp’s engineering empathy). For example: communicating a technical decision, giving effective feedback, running a meeting effectively, or skim-reading code. I do those things every single day, much more often than I apply math in my work, but somehow people think you need to be good at math to build software.
It’s too late to stop calling it engineering, but we can recognize these other, much more central aspects of the process of building software and talk about them, teach them in our schools, and hold them up as much as we do graph search algorithms and binary trees.