There are as many personal metaphors about writing software as there are people who write software. To say that programming lends itself to metaphor isn't quite right; software demands metaphor. I type with my hands, but everything I create is intangible and imaginary. The only way to talk about it, or to reason about it, is in a language-by-proxy. Otherwise it doesn't really exist. So writing software is a recipe, or a blueprint, or a polymorphic mammal that quacks or barks.
This one has to do with gardening, although I'm really no great gardener; my partner is generally the one to maintain our planters of parsley and cilantro, and I still get confused between the two. So this will be as maladaptive as any metaphor.
It's not about cultivating code, or about pruning technical debt. It's not features as flowers. It's concerned with the later seasons: as the autumn passes and winter arrives. What it means to harvest, to care for the soil, and to spend time in reflection while the ground is hard and little grows. What it means to reap knowledge of a domain, to maintain clear and coherent systems, and to use that understanding to continue growing ever more useful products.
How we allow the ground to lie fallow, how we plan to grow again in the spring.
The "ideal" trajectory of a business, in the world that we find ourselves in, is to grow constantly and continuously. This has certain implications for the products that we build. And if we could just keep adding features and their prerequisite lines of code without issue, constantly and continuously, I wouldn't have much to write about. I don't think that that's possible.
We start writing anything — a project, a feature, a variable name — when we have the least knowledge of how it will be used, and how it should be structured, and how it will be built upon. We're not prescient so we rely on conventions, assumptions, and intuition. This shaky ground does not firm up until we're at the very end of our process. We look back and say "well the name of this variable, and the structure of that service class, and composition of those jobs, aren't quite right."
This has certain implications for the systems that support the products that we build. We can hopefully refactor our intra-feature work before we open a pull request. We might set aside regular time to address technical debt and be able to go a little deeper. It is not often that we have the opportunity to address systemic issues that arise in the organization, the structure, the fundamental decisions that underlie our work.
The harvest requires that we interrupt a natural process. We kill part of a plant. We take its fruits. We bake a pie. Here is the least actionable advice I might ever write: every year, starting when the frost first sets in, pause new work for about a month. Reflect. Identify assumptions that have grown to be untrue; find fundamental metaphors that no longer make sense. Think especially about where past decisions have limited the way that your system could evolve in the future. Reap what you've learned. Sit with your new knowledge. Unearth for your hidden myopia.
What if this system were evented instead of callback-driven? What if we extracted this package as a separate running service? Could we make this whole thing asynchronous? What would happen if we folded this back into our monolith? What if we could server-render instead of host a single-page app? Is this actually still polymorphic or has it diverged? What if we could get rid of all of this locking? What if this were message-based instead of API-based? Could we build this to better suit ourselves instead of paying for a generic solution? Could we pay for this instead of maintaining it?
Rewrite your product from scratch. Okay, maybe don't: this probably introduces as many new bugs as it resolves. But rewrite a large subsystem. At least finish up that half-started migration to the new pattern in your service objects. We miss the opportunity for meaningful reflection and meaningful change when we run from sprint to sprint without making room for other rhythms in our work. We can be grateful for the pause and reflection automatically given by nature to our raised-bed gardening. We have to do the rest ourselves.
Have you found ways to set aside time to reflect on the software you or your team have created? Have you done the big-bang rewrite and it's gone perfectly, or not so perfectly? We'd love to hear about it; drop us a line below.
Thanks for your time and attention.