Henry Lucco | Posts

Everyone Should Program

April 14, 2026

I currently work for a heavily bureaucratic software company. One of the most common requests I get when trying to make progress towards shipping is "send me the doc" or "is there a doc?" or the most offensive: "we need to see a doc for this before we can move forward". Everyone wants to read the doc, everyone is involved with the doc and adding comments to it, and there is a vibrant and thriving market of documents be shared throughout the organization.

This one of the biggest blockers to the company making progress in any meaningful way.

Now, I should clarify that I am not blindly anti-doc. For the majority of non-technical employees, a document is the appropriate format for communication. The product managers I have worked with communicate largely through specification documents and various tickets, epics, and other project abstractions. The human resources specialists I have collaborated with maintain sets of documents with policies and other relevant information. This is appropriate as these people, for the most part, do not possess the necessary training or skills to create any other type of artifact. As a contrast, designers are producing and consuming mocks or flows of some sort, the same way that engineers and other technical employees (engineering managers, engineering directors, VP of engineering, CTO, etc.) should be producing and consuming code.

Documents on their own do not create problems, and have a wide range of use cases for which they are appropriate. The problem arises when an organization's culture shifts to encourage technical discussion through documents rather than code.

Programming languages were invented to allow human beings who predominantly communicate in natural language to express intent in a clear and specific enough manor to avoid ambiguity. Without programming languages, it is impossible to specify technical details in a way that isn't subject to misinterpretation. As a result, in order to contribute positively, a computer scientist must become fluent in these languages, so that they can express themselves to both the computer and other human contributors in a way that is both understandable and does not leave details to the imagination.

This is not to say that abstract conversations about computer science are not productive. These conversations are generally required for education and the building of a shared understanding, but they are never the definitive source of truth. That honor is reserved for the software artifact created as a result of the discussion, rather than the discussion itself.

Unsuccessful engineering orgs lose sight of this principal in favor of the "design document".

What is the design document?

This can vary from org to org, but for most a design document is typically supposed to describe the following:

  1. The top down architecture of the system being built and it's components (the classic boxes with arrows).
  2. The interfaces for which the system will interact with it's dependencies and customers.
  3. The structure of the code that will be written and how it will be organized.
  4. How the system will be tested.
  5. How the code will be deployed.
  6. Logging, alerting, and metrics that will support the system.
  7. Justifications and research to support the above.

The theory behind this concept is sound: "software is complicated and expensive to build, requiring the manpower of multiple people and serious time and commitment, if we don't have a plan for it then how can we ensure it will be built properly?". Or more practically, if multiple people are supposed to collaborate on a project, how will they know what to do without a document describing what needs to be done?

These two challenges (needing a plan and building a shared understanding for collaboration) are why most people building software accept and support the writing and sharing of a design document, and are stubbornly afraid to push forward without it. For these people, the design document represents a safe and paved road through the dark and forboding jungle of possible constraints, tradeoffs, and design decisions as well as a bulwark to cower behind in the event that something goes wrong.

Security issue? The security review of the design doc will catch it.

Scaling concern? The system design panel reviewing the design doc will catch it.

System inconsistent with the product specification? Just make sure the design doc matches the product spec, and you are all set.

These are the promises of the design document, and the foundation of sand on which modern software is built.

The allure of the design whispers in the ears of developers, middle management, VP's, and executives alike and convinces them that all of these problems can be solved through review and writing.

After the n'th review of the document, everyone feels satisfied. The debates have been had, concerns have been heard, revisions have been made, and a few months after the ideas conception, engineers can finally begin programming, it should be easy now seeing as all the hard problems have already been solved, after all we have an ironclad design document to refer to.

As anyone who has participated in this process before will tell you, this is not what happens in practice. Unforeseen blockers arise, progress is delayed, new tradeoffs must be made, and in the event of success, someone is still paged in the middle of the night to allocate more nodes to handle demand.

Why does this happen? We went through the design document thoroughly, everyone reviewed and signed off on it, was the entire engineering org wrong?

No, everyone was right. That is the problem.

The design document was written in natural language, which is far too abstract to express the real issues that will arise from the implementation of whatever complex system is being described.

The situation described above where actual software is written is the best case scenario. In most cases, the document serves to block progress rather than enable it.

A design document allows all of the planning and ideas to take place in the world of abstraction, and as it is abstraction through natural language there are infinite ways to prove, disprove, undermine, or overwrite the various ideas contained in the document. A developer who wants to block the document can say "this won't scale because of x", a security engineer who doesn't want to be responsible for a new vulnerability can say "we don't support that type of connection here, so you can't build it that way", a product manager can say "this won't match arbitrary requirement a, because it first needs to do b" and all would be right, because no software has actually been written. In each contributor's head, there is a narrative describing the final outcome based on their own interpretation of what is written, and for each of these people that narrative will be different. In many cases drastically so.

As each individual maintains their own idea and interpretation of the system, there is inevitable conflict and confusion over what the document is actively describing, and this is where progress breaks down.