How I design software
Designing software is challenging, and I don’t think there is a right or wrong way of doing it. I tried several software design methods in my career, and they all lacked something and never left me confident about the system I built.
I tried the code-first approach, where I prototype software by coding it first; I always felt lost looking at the code later. I wasn’t confident answering questions about the system and often missed things.
I tried a diagram-first approach where I drew the system. Most of the diagrams I tried were
- too into the weeds, so I needed help looking at them, or they needed to be higher level. It feels like a marketing brochure.
I’m not saying diagrams are not helpful; I find them not powerful enough without companion documents. For example, I could see the high-level components when Elon shared the Twitter architecture diagram. Still, it barely described any deep technical substance about Twitter or what even those components are.
Twitter architecture diagram shared by Elon
Of course, I also tried the design-by-powerpoint, where I presented several slides with bullet points showing the system. Some questions must be explained in slides, and you must catch something.
After experimenting with many approaches, I discovered that writing down the design while time-consuming has been most effective for me. Of course, this isn’t something new; I think Seth Godin puts it nicely: the natural way to design software is to spec it out all in writing.
I wanted to share the process with you in this article and discuss its limitations at the end.
This is how I approach software design.
Suppose I want to write effectively, whether medium articles, design docs, or poetry, I find it best to have no distractions. I block 2–3 hours of uninterrupted time slots: no meetings, emails, or notifications. I use a clutter-free note app. I like to use write-monkey for Windows & Focus for Mac or, recently, just VIM. I go full-screen dark mode; only me and what I type.
In the following sections, I will produce a collection of design documents for each type of stakeholder (people interested in the project). Some of these documents are high-level, some are deeply technical, and the audience can be different.
Maybe the essential piece of design documents; I can’t count how often the stakeholder called me out because I have a feature in the software for which I don’t have a use case. I just felt it was cool to add, and I said it. While this might be nice in hobby projects, building commercial software must be approached pragmatically.
A workflow and use cases help minimize the scope and focus of the work. Almost all pieces of the software link back eventually to a customer requirement based on a specific workflow or need.
I started writing the workflow of how the software will be used in detailed length. I leave nothing out. A magical thing about stating the obvious helps the ideas and creativity freely roam. This step produces many questions for the project’s stakeholders.
I compile the questions from the workflow step and meet with the stakeholders to get a final say on the workflow. Part of the workflow would then turn into what we call in Agile a min-ship. The final workflow becomes available for non-technical people interested in the project. Does the workflow address the requirements?
The workflow document has no particular structure; it's just a document. The goal is to identify clearly how the software will be used. Feel free to be creative here. Include UI elements, talk at a high level, and describe so anyone reading this document knows what and who your software is for.
The next step is opening a new page and writing down the design overview. The design overview explains how users interact with the software and what happens. It is a technical workflow representation; I can freely use technical terms in this step.
The design overview includes write-ups of software components, the UII, UX, frontend, backend, protocols, databases, etc. It also has how the components interact, referencing the workflow document when applicable. For example, to solve this use case in the workflow document, we may use HTTP/2 because we anticipate many client requests. This document still needs diagrams.
Some items in the design overview won’t be linked back to the workflow, such as asynchronous jobs or health checks without direct user input. I think some call these non-functional requirements.
The design overview also helps me articulate things I have never considered. Here is where things started to form: what database would I need, what reverse proxy should I use, how would the backend scale be better, and would the eager vs lazy approach be better? I leave nothing out; I include any technical problem I might face here.
The design overview document is sent and reviewed with the technical stakeholders for comments. It is like an RFC.
While writing the documents, components will start to form. These components will get their document (if necessary), and I can go into detail.
I open a new page for each component and write in detail what that component is, what it interfaces with, what it computes, what it outputs, etc. Reading this component, it's as if you're reading the source code; I write down every possible nuance of any limitations or security considerations. I am allowed to go full technical here.
This document doesn’t make sense in some projects, as I can describe the component entirely in the design overview. Still, with time, I often find myself writing the component document anyway as I discover more about this component. Some components may become so big they end up as their projects.
Design Overview Diagram
After writing all the pieces, the final step is to draw the design overview diagram. It is a diagram of how all those components communicate with each other. I don’t use special software here, blocks, squares, and arrows with text. Simple. Google Slides work perfectly.
Multiple diagrams for each component are likely based on the system's complexity. Plus, I would schedule reviews with team members now and then.
Limitations of this approach
One limitation of this approach is the time it takes to produce and keep the documents up to date. Sometimes, I must remember to update the records to fix bugs or introduce features. Ownership also becomes critical here as you leave the project; rarely do the documents update themselves, and the following software designer might prefer another approach.
Another limitation is that it's hard to present these in a meeting when the participants haven’t read the document and are unfamiliar with the project. So, I find PowerPoint helps here; creating a few slides from the workflow and design overview solves this, but keeping all these documents and slides up to date becomes another challenge.
Nothing is free. I don’t know; what do you guys do when designing software? I would love to see it.
In this article, I talked about my approach to designing software by writing several documents. While it is time-consuming, returning to these documents always has the answers.
I don’t claim that this approach is perfect (I talked about its limitations), but I find relief when I go back to the document and see everything is spilled out.