The Pear Programming Blog

Growing Software

Back when I was young and dumb, I would avidly consume a lot of content related to programming: podcasts, books, you name it. At the time, there were many ideas floating around concerning how we should write code and the ones that really lived in my brain, rent free, were the principles exposed by Uncle Bob in Clean Code and in Clean Architecture. It was just beautiful. Everything nicely aligned and easy to maintain, concerns were nicely separated, you had your interfaces, everything was a healthy dose of OO principles put into practice.

Now, I don’t mean with this article to disprove or contradict what those books proclaim. Even because, even now, I don’t think they’re necessarily wrong. I just think that most apps won’t ever need architectures so complex that you’ll actually need to break away from whatever defaults frameworks give you.

Now, back when I was reading all this content, I tried really hard to make my web apps modular. I tried even harder to make my Android apps modular. However, I always ended the effort feeling drained and that my application wasn’t really that much better for it. In fact, it felt harder to change, because now I had a ton of indirections and interfaces for what was essentially a request trying to create or update a resource.

And here’s where I think lies the issue: In general, people tend to reach for more complex patterns too early. They don’t let the code grow and manifest its pains.

And I mean that quite literally. How can you know you need an abstraction or an entirely different app architecture before even taking the time to notice the places where your app is hard to change? I don’t think that’s possible. And because of this, we add complexity where none was needed.

Ok, but then what’s needed in order to avoid this curse of a premature optmization or abstraction? To me, it’s patience.

I once saw in some blog somewhere, I forget which one, that writing software isn’t at all like building buildings, and therefore to call us engineers gives us a false analogy. In reality, writing software is like tending to a garden. Gardens start as small things that we slowly grow, prune here, water there, remove some weeds, change the soil so that it can eventually reaches its full form and we can then enjoy watching the mix of colors from foliage and flowers. I feel like software is much the same. We try to just write enough to have a thing work, then we add functionality, refactor some code, change implementations, remove useless implementations and so on, so that, eventually, that software can be put into production and fulfill its purpose.

Following that analogy, doing all this requires patience. You don’t just prune a ton of branches from a plant because a manual says so. You do it when you see that the plant needs to be pruned. Same thing with software. You need to wait and see how it grows and, as it grows, it will make it painfully obvious where things need to be changed.

Studying architecture is important. Studying software design patterns also. But that’s like buying a shovel, a pickaxe, a rake or some scissors. They solve specific problems. But you need to know how and when to use them. Let your codebase grow and soon enough you’ll feel the pain in order to change something and that’s when you know the codebase needs a bit of work. Doing this you avoid doing over engineering, you keep things simple and your codebase will be all the better for it.