Software design
When we founded FunnelStory in 2022, I was the only person writing code. We didn’t have a team yet. Today, the back-end is about 500k lines of code. We’re a team of 5, so on average each person manages about 100k lines.
I used to be able to remember how I wrote every package, API, and test. Now agents are writing thousands of new lines a week. I can’t expect to remember all of the codebase in fine detail. This is not just an AI problem. This would also be the case if our team expanded from 5 to 25.
As an architect, the only way to make sense of things is with abstractions. Just like how higher-level languages help you reason about programs better than machine code or assembly, abstractions let you reason about programs at a level higher than individual lines of code. At an architecture level, I think about the infra pieces, subsystems, components, and how they interact. Within the codebase we have to get into package design, defining interfaces, code readability, and testing. Abstraction has to work at multiple scales.
A few weeks ago I decided I needed to relearn software architecture and software design principles. I have a good intuition about these things, but when you’re dealing with a team of engineers and their agents, it’s really important to codify this kind of intuition in order to avoid slop. In my 15 years of writing software professionally1, entirely at startups, I rarely needed to think about how to design software and abstractions. We were too busy building something to get the company to the next stage.
I’m starting with A Philosophy of Software Design (Amazon) by John Ousterhout2. If you want a brief introduction, Ousterhout gave a talk (YouTube) that covers the highlights of the book.
The book has motivated me to start to write down some high-level principles for how we write Go code. While we already had a basic “style guide” and Cursor rules, they just described some patterns and code snippets, and not really design principles to follow.
A great perspective from its conclusion:
This book is about one thing: complexity. Dealing with complexity is the most important challenge in software design. It is what makes systems hard to build and maintain, and it often makes them slow as well.
[…]
The reward for being a good designer is that you get to spend a larger fraction of your time in the design phase, which is fun. Poor designers spend most of their time chasing bugs in complicated and brittle code. If you improve your design skills, not only will you produce higher quality software more quickly, but the software development process will be more enjoyable.
These days, while my agents are churning away on user stories or bug fixes, I’m spending most of my time reading and thinking about design principles. I think this is how software engineers should be thinking about staying relevant. AI can already do a lot, but where human engineers play an important role is bringing context and judgment.
Software engineering is what happens to programming when you add time and other people.
https://www.acm.org/articles/people-of-acm/2026/russ-cox
Time and other people is the context. Knowing proper design and having good taste is judgment.
-
I mean writing software for a paycheck. My first ever internship was the summer before my senior year of high school, in 2011. The year before I built the website for my sister’s college club for money, but I’m not really counting that one. ↩︎
-
Ousterhout created Tcl and also worked on the Raft consensus algorithm. ↩︎