by godelski | 2025-09-08 21:30:28+00:00
I have a hypothesis as to how much of this happens. There's a seemingly paradoxical idea: simplicity requires complexity while complexity can be achieved with simplicity.

I think a lot of this complexity happens with everyone's efforts to make things simple. The problem is actually in that there's multiple ways to define simple. I have a good example of this that happened just last week. I have some Papa John's gift cards from Costco, and was ordering a pizza with a friend. So we put in the gift card amount and find out it is just short of the order. No problem, we'll pay the difference with another card. Problem is... that's not possible. We had to edit the order so we could bring the price down. In fact, I think we see things like this happen with pre-paid Visa/MasterCard cards. The problem was that the programmer made too simple of an assumption: customers only need one gift card. How would we fix this? Well now we should probably write a method that allows an arbitrary number of gift cards and credit cards. Our method would need to allow this arbitrary splitting and the question then is how much we'd want to expose to the user (do we want them to split a purchase with two credit cards?).

I think all of us can hear a likely conversation in our head about implementing such a payment system. Some person is going to say that we're over complicating the problem. Especially when we're talking about credit cards, it probably is a safe assumption to make that the order will be completed with a single card. Except it's fucking pizza. How often do you end up venmoing your buddy after you order a pizza? You didn't actually make the things simpler, you just moved the problem elsewhere and actually added complexity. It's definitely more complex to have a whole other app to facilitate a second transaction than it is to just allow arbitrary payment cards.

I see this happen in code all the time and I think Unix Philosophy[0] can be really beneficial. You try to make your functions to very basic things and then put them together. I try very hard to write flexible code because the only thing I know is that the code is the goals of the code are going to change over time. So you don't write just to get a specific problem solved, you write to get your problem solved and for others to be able to use your building blocks. And your building blocks should just allow things to be modifiable. How many of those 50 million lines of code are redundant? I'd wager a fair amount![1] Not hard, you just use very minimal abstraction. Like if you write a function to calculate tax you don't fix the value of sales tax even though your business only operates in <state of your choosing>, you just expose the variable. Extrapolate this out. This is technically more complex if we're viewing the function in isolation, but it is simpler if we are viewing the program as a whole (and viewing it over it's progressive lifetime). Of course, you can go too far with this too and striking that balance is difficult. But typically I see code that is inflexible rather than too flexible.

[0] https://en.wikipedia.org/wiki/Unix_philosophy

[1] I hear people say they get a lot of utility from coding agents because it takes care of boiler plate and repetition. I think that says something. If you're doing something over and over (even with a bit of variation) then there's probably a better way to do this. Problem is that if you're just rushing to finish Jira tickets you'll probably never have the time to figure that out. If your manager just measures your performance in number of tickets completed they'll never care how many tickets your code created. Sometimes to go fast you gotta slow down. IMO the most time consuming parts of writing code are the planning and debugging (analyzing, rethinking, rewriting, not just fixing errors) stages. Writing lines is much smaller in comparison and can be done in parallel.