Code, language, communication

Funny how the world works at times. Not long after writing about programming being design (note that things don’t necessarily land here right after I write them, at least for now) I found a tweet asking why we even bother ourselves with bridge or house building analogies and metaphors, instead of taking programming for what it is — programming? It made me think about this more, so I want to share why I consider it both valuable and inevitable.

Analogies are inevitable

Our brains are wired in such a way that they look for similarities and try really hard to categorize the world around us. Sometimes they get it wrong and since we can't escape this process, I think it's worthwhile to try and make it more informed. Especially when it’s a part of a feedback loop influencing our perception of programming, which is definitely the case for me.

I think the best examples of how categorization affects perception and unlocks the areas of creativity you need to recognize and solve the problems in front of you, are to be found in the history of some of the largest businesses of our time. You see, in order to be good at the stuff you do, you first need to understand what business you're in.

I already talked about McDonald’s and their burger business, but you may not be aware that McDonald’s is not actually a fast food company. They’re a real estate company. Realizing this marked the difference between building an international empire and filing for bankruptcy for the guy who created the franchise (who, by the way, wasn’t a McDonald). Sure, the burgers are important, but when you look at the big picture of the whole franchise, they're only important because they allow the buildings to make money. It’s upside down.

Another similar example is Amazon. Seemingly a store but the problems they faced in the first years of operation were solved by taking clues from FedEx or UPS, not Walmart. They were distribution problems, not retail problems. Same with Facebook. To the average person it’s a social network, aka a place to communicate with your friends, express your interests, and share cat memes. But everyone at Facebook understands that they are an advertisement company and the whole app is just an insanely addictive, interactive billboard. And then we have Apple, which looks like a software and hardware company, but is really an amalgamation of a fashion designer with a church (it’s ok, I can say that, I'm writing this on a Mac). On the other hand, looking at these companies taxes, maybe they all are... But I digress.

The point is, had these companies failed to correctly identify the core business they’re in — be it real estate, warehousing and delivery, or advertisements — they would've found their problems impossible to solve, because they would've been trying to solve them in a wrong framework.

Your perception of the nature of your work affects how you do that work. Which is why it’s so important to think of programming as design, and of software production as that immediate, cheap, negligible process of program execution.

Who do we write code for?

The detrimental side effect of seeing programming as "producing software" is that you see the code and the (running) application as two facets of a single end product. But that leaves one of these facets without a target audience, because while the end users are certainly interested in working software, they couldn’t care less for the code itself.

Thus the value of the code is diminished and it's seen as an almost unfortunate byproduct of the process. I've even heard both programmers and executives say things like: "clients don’t care about code quality, they care if it works". And I pushed back against that idea directly, until I realized the misconception lies somewhere else. It’s just that we do not write code for clients, customers, or users. We write it for each other. And yes, I’m not pretending to be original in this idea, just to provide my view on it.

Again, it’s the same as a technical drawing. It’s kind of useless for the home owners or investors. Heck, they might not even be able to fully understand it, even if the visual nature of it makes it arguably easier than with code. What they’re interested in is a house that doesn’t collapse on itself. The target audiences for the design are architects and contractors. In the same way, if we decouple code (as the design) from the final software (as the product) we’ll be able to find the target audience for the code: other programmers. This is perfectly summed up by Kevlin Henney's idea of programming as "codifying knowledge" as well as by this quote from Harold Abelson's "Structure and Interpretation of Computer Programs":

Programs must be written for people to read, and only incidentally for machines to execute.

So what are the qualities other programmers will look for in a piece of code, if we view it as a design document? From the top of my head I’d list explicitness, descriptiveness, and clarity. First and foremost, that design has to be understandable and unambiguous to them. And it must make it clear what the end product is supposed to be, just like it’s obvious from a technical drawing that the structure it describes is a barn, a house, or a car.

The difference is that while technical drawings are a visual medium, code is a textual one. And while it can be visualized with stuff like C4 or UML, the important part to remember is that these are not the final design. They’re accompanying documents. Helpers, if you will. They’re not used by the builder (the computer) to realize the end product (stuff of screen), which is why they’re not the source of truth — the code is. That’s also why Simon Brown insists on encoding enough information in your code to be able to automatically generate meaningful visualizations, rather than drawing them. Otherwise they will simply drift apart and become a source of confusion.

The purpose of software

Ok, but there’s one more quality of software which we haven’t talked about yet, but which is extremely important here. The clue is in the name — software. As opposed to hardware, software should be moldable and easy to change. After all, that’s the idea behind having a programmable computer: not having to rebuild the physical structure every time we want to do something else. The very idea of software came from the realization that what we need from computers changes more often than how they make it happen. Which leads us to the conclusion that the purpose of software is to change.

And this is the most important quality other programmers will, whether they realize it or not, look for in the code you write — ease of change. Because that’s what they’ll be asked to do: make that code do something else.

And that's always to root of it, regardless whether they're adding a new feature or fixing a defect. After all, there's no reason to even look at the design (be it code or technical drawings) unless you want to modify the structure. Which brings us all the way back to that quote about technical debt:

You’re wise to make that software reflect your understanding as best you can, so that when it comes time to refactor it’s clear what you were thinking when you wrote it.

Conversely, it’s unwise to write software in a sloppy way, which obscures that initial understanding instead of exposing it. It would be like an architect creating a technical drawing which looks like doodle. If another architect was tasked with adjusting the structure, they would say it’s easier to tear it down, as they have no idea where the wet walls are or how the electrical installation is made. Does that ring a bell?

Interestingly, even relatively well structured codebases usually have at least one place like that — the Master Function which does everything and everyone working on the project knows that as soon as there’s a need to modify it, they’ll just need to rewrite the whole thing. It's not because it doesn’t do what it’s supposed to be doing right now. The structure as it stands is perfectly legit. It’s just that nobody understands the design document.

How can we avoid this? How can we write code which is understandable and unambiguous to our peers? It all starts with understanding what that code is — a piece of design we create not only to meet the immediate needs of our customers, but also the future needs of the developers (be it ourselves or our successors). And that the code, being a design document, is first and foremost a one way communication device between us today and them in the future.