What gardening has taught me about developing software and vice versa

Gardening as a metaphor for developing software was, as far as I can tell, first mentioned by Andy Hunt and Dave Thomas in their 1999 book, The Pragmatic Programmer. When it first occurred to me to write on the topic, I hadn’t heard the idea before, as I haven’t yet finished reading the book. It’s on the top of my list, I swear! And knowing those fellows came up with the same idea, I certainly get a feeling of validation.

An enterprise integration garden, the sort of thing I’m seeing in my dreams these days

I’m fairly new to gardening, at least in the outdoors, which presents unique challenges where I live. In central Texas, triple-digit temperatures occur between the months of May and September, and are practically an everyday thing in August at this point. Rain isn’t too scarce, but in the Spring months there can be a lot of it, and in the summer, turf grass dies without supplemental irrigation. Winters dip into the 20s Fahrenheit from time to time. So, any plant you expect to live for more than a year has to be hardy to both extreme heat and frost, to both drought and drenching. And then, there are the pests, such as grubs that feast on plant roots before they drill up out of the ground and turn into a flying, buzzing nuisance. So, I’ve certainly made a few mistakes, terminated the lives of some lovely green organisms before their prime.

Red tropical sage, a central Texas native, is hardy and easy to grow

Similarly — and I admit this might be one of the strangest context switches you’ll experience today — in programming, I never get the sense that I have a full grasp of whatever technology I’m putting to use. I get just familiar enough with a set of technologies to build a thing that makes some money for somebody and then hope that most of those technologies haven’t been abandoned when it comes to building something else.

So, for what it’s worth, here are some comparisons between software development and gardening that have crossed my mind while planting one of many Liriopes or writing yet another REST endpoint.

The end result will never match the original design

I created my first ornamental garden within a north-facing corner of my house. Initially, water from heavy rain poured off the edge of the roof and landed on cedar bark mulch I’d placed underneath, dislodging it and flinging mud around. Over the course of a year, much of it washed down into an adjacent low point that I had landscaped with river rock, which doesn’t really benefit from mulching. So, around the area under the eaves, I replaced the mulch with pea gravel, which keeps the soil moist enough and doesn’t float. Soon after that, I had gutters installed. If functional gutters had been present originally, I would never have needed to replace the mulch.

I suppose the gravel creates a nice contrast

In an interview with the authors of The Pragmatic Programmer, Hunt points out that software development is not really comparable to construction or even the major engineering disciplines.

It doesn’t work that way with software. […] The garden doesn’t quite come up the way you drew the picture. This plant gets a lot bigger than you thought it would. You’ve got to prune it. You’ve got to split it. You’ve got to move it around the garden. This big plant in the back died. You’ve got to dig it up and throw it into the compost pile. […]

I can attest to the idea that building things with wood or metal is not easy for someone with a software development mindset. I’ve managed to put together a 4'x8' tool shed with wood framing, and from that I learned that even such a simple structure requires planning of most details in advance. Any measurement recorded incorrectly results in wasted materials and time. I frequently caught myself cutting a board at the wrong angle or nailing something upside down, and then becoming annoyed because I’m used to having a backspace key for that sort of thing. In the end, it has to match the original plan, or it’ll be an ugly, possibly hazardous structure. In contrast, with a Java development environment, you can create a fully functional web server by running one standard build-tool command to generate one from an archetype. You can delete it five seconds later, and all that will have been lost is maybe a few cents’ worth of electricity. With gardening, you’re free to make a lot of mistakes. Your hand trowel is your backspace key. The implementation shapes the design.

In “You are NOT a Software Engineer!” Chris Aitchison points out:

Would you try to plan a garden in such detail that you would know where each leaf will be positioned before you plant a single seed? Would people expect estimates (or are they promises in your organisation?) on exactly how many flowers will have bloomed in one year? Would you have an incentive tied to that? Things that would be perfectly reasonable to plan for a bridge seem a little ridiculous when you are talking about a garden.

Leave room for growth

Surely it won’t get much bigger than that
WHAT

My local favorite gardening retailer, The Natural Gardener, pointed me to this great Texas-native perennial, Fall Aster. I wish I’d paid attention when they mentioned how big it would get. It looked like the second photo a year after planting something like the tiny plant in the first photo. It’s not just big, it also spreads aggressively by its roots.

As you’ve probably guessed, the analogy here is with scalability. Can an actual garden be designed with horizontal scalability, like a Cassandra database? Vertical stacking of vegetation in the physical space, like with hydroponics, might be analogous to scaling data storage “horizontally” by adding additional data replicas. I don’t know — given that any garden has physical space constraints, a garden has to be a monolith, albeit one with a much higher degree of pleasurability than a Java web server built in 2005.

Expect maintenance and value maintainability

A homebuilder doesn’t expect to hang around and do on-demand maintenance on the house they’re building for years after someone moves into it. You can’t take your CPU from Intel Corporation to a repair shop when it fries out, which occurs almost never with normative use. In contrast, a piece of software without regular maintenance is, by and large, useless software. A library that I find on GitHub without any commits in the past two or three months is usually one that I would consider “abandonware.”

Consider one tendency common among talented software developers, a desire to create patterns, even frameworks, to promote efficiency in developing sets of similar features. In his thorough article on the pros and cons of frameworks, Juan Carlos Arias Ambriz points out one way in which frameworks can fail us:

That tangle of weeds you’re walking through is growing thorns. Have you ever been in the situation where you’re using your framework and trying to add a library to it, just to realize that the library version you need doesn’t work well with the framework version that you’re using? Sometimes it takes more effort to make two pieces of code work together than it does to just write the code yourself. And since the frameworks and libraries that you use are often built on other frameworks and libraries that can have hidden incompatibilities that you can’t even anticipate, the problem can grow exponentially more complex, reaching a point where they’re impossible to manage if you want the project to keep growing.

Exponential growth of complexity brings exponential decline in maintainability. And there are other ways in which we get ourselves tangled up: we write hard-to-test code and afterward, we write tests, which then end up being convoluted and brittle. We neglect to write documentation for a function, and two weeks later we look at it again and can’t remember what it was supposed to do.

Then there are the maintainability anti-patterns at the organizational level, like having “rockstars” build major features and then having “junior” developers fix their bugs. I admit the former is a fun job to have and it’s not the worst thing in the world to create work for entry-level contributors. For my garden, ideally I’d rather not do the work of periodically reapplying mulch, trimming things back following frost periods, and so forth — I’d rather “outsource” that work.

A garden is a lot like a web app in that you have to keep yourself on “pager duty” to keep it alive. Some techie-gardeners have built automatic watering systems using Arduinos and moisture sensors that raise alerts about potential droopy-leaf conditions.

Prioritize that which is most worthwhile

DON’T: Mulch volcano

As an aside, the young (pear?) tree in the above photo will have a hard enough time in the Texas heat without someone having created a “mulch volcano” around it. The root system of this tree probably will start growing up into the mulch to avoid being smothered by it, and lower roots may rot. In keeping with the theme, this is sort of like having within object-oriented program code a class inheritance hierarchy twenty levels deep. A deep class hierarchy lends itself to tight coupling and weak encapsulation— the base classes suffer from code rot! Still with me?

In conditions of drought, water use can be limited, in which case gardeners have to make compromises and prioritize irrigation based upon the value of each kind of plant to the overall landscape. Generally, young trees should be given priority for watering, as they are sensitive and costly to replace. Next in line are perennials and fruits/vegetables. The lowest priority for supplemental water should be annuals and turf grass and other cheap vegetation maintained for appearances.

If you’ve worked at a scrappy start-up company, you know what it means to make sacrifices due to resource limitations. When deliverables are late, a team may neglect its commitment to open-source contribution. If traffic to your e-commerce site suddenly skyrockets and your web servers scale poorly, you’ll probably have to put R&D on hold while you put out fires. One may consider the challenges a developer might have faced at a small, travel-related business when COVID-19 struck: if they weren’t laid off themselves, half of their team might have disappeared. Maybe they were in the process of replacing a relational database full of years of production data with a NoSQL store for the fun of it, but that isn’t happening now.

Conclusion

Thanks for reading! Do you know of a way I could keep the ball rolling with this comparison? Please share in the comments.

Software developer in Austin, Texas, pursuing the art of explaining complex ideas in the simplest ways possible.