It seems like the endless stream of data in a terminal is the farthest thing from a living, breathing being. Looking through the Stitch Fix codebase, what comes to mind is structures, information systems, methods of exchange – not a group of finches on a faraway Galapagos island.
A few weeks ago, I was listening to Randy Shoup (our VP of Engineering) give a talk on microservice architecture at our quarterly engineering summit. Over the course of that talk, an idea started to unfold in my mind. Architecture is not some mechanical, meticulously planned and hyper-predictable thing, but rather a living organism subject to the laws of biology just as we are. This led to an understanding that when we look at code as a living thing, we build more resilient systems and are more attuned to when and why they change.
So, a few biological principles to guide those technical systems…
Nature designs through need.
Living things evolve as their environment introduces new challenges. In the same way that animals lost the webbing on their feet as they moved out of water and onto land, code architecture will change as a direct response to new challenges.
Imagine a scrappy startup trying to get a product off the ground – they’re much more likely to build their system as a single application with a single database. On the other hand, an established company that’s facing scaling issues may be thinking about how to turn that now-huge monolith into a flexible distributed system. In both cases, the technology is naturally evolving to meet each company’s needs.
To go against this evolution, though, may invite failure. A startup that needs to grow a customer base and is instead focusing on building a complex distributed system for hypothetical future scaling pains might not make it past year one.
Evolution is inevitable.
No system can stay stagnant. This principle begs the question – do we encourage the evolution, or idly sit by waiting for it to happen? Imagine the difference between someone who exercises regularly and improves their health over time versus someone who fails to exercise, only to have a heart attack one day and a very serious chat with doctors the next.
There’s a responsibility inherent in building and maintaining a system – namely, to keep an eye out for points of pressure and respond accordingly. Here at Stitch Fix, we hit a point where we felt the pressure of slow load times and too many shared database connections. Some of the applications built in our early days had ballooned into unwieldy monoliths. We took the initiative and made decoupling our complex architecture one of our top goals this year. As different services break off into their own applications, our system becomes more limber and resilient. The pressure slowly eases, and our evolution is a gradual, gentle process over time.
But evolution can also be chaotic. Imagine feeling those scaling pressures and ignoring them, hoping that the bloated monolith will keep chugging along. The day will come when the pressure grows too high and the entire system crashes. Then comes the scramble to fix it, something that may derail roadmap work for months in an effort to remedy the earlier negligence.
Specialization allows for more unique solutions.
As organisms changed from single cell amoebas to more complex life forms, cells started grouping together into specialized functions. Just look at the human body and its organs – the heart as a constant I/O cycle, the liver as a high volume processing center, the nerves as a global information delivery system.
In the same way, once a system gets large enough to merit breaking into groups, those groups can then specialize, allowing for more relevant solutions. In the early stages, a Rails application with an SQL database and a plain HTML / CSS / jQuery front end might make sense. But after specialization, there might be better tools for the job. An application that uses a fixed set of queries over a huge database of colors, styles, and sizes may be the perfect candidate for a NoSQL database structure. Or, the internal styling tool that has to constantly reflect changing state could be a great place to throw out jQuery and use React.
Regeneration is a part of design.
It’s been said that every cell in our body is replaced over the course of seven years. And while the overall organism may look the same, it is composed of entirely new building blocks.
Code should work in a similar way. Even if a product serves the same business need over time, its individual parts should be in a constant state of evolution. And this requires a commitment to continuous improvement – questioning the assumptions that the code has been built on, asking whether the original solution to a problem is still the most effective one, and being willing to change parts of the system as needed. If we fail to do this, then the individual parts may degrade and eventually atrophy.
The system is a unified whole.
The human body is a single system made of disparate parts, and that system seeks to maintain equilibrium at all times. That means when one muscle is injured or strained, all the other muscles work harder to maintain a state of balance. If the injured muscle isn’t allowed to heal, then the constant tension on the other muscles results in chronic pain.
Even as we move towards a completely distributed architecture, it helps to realize that all these separate parts are intertwined. If one service goes down, it will inevitably affect other parts of the system – whether that’s by blowing up our logs, holding up downstream actions that need to happen, or impacting the various business partners who rely on our software. Alternatively, there may be a weak spot somewhere that affects the entire system. For example, if a company doesn’t have a strong testing culture, they may continually run into issues when pushing to production. In that case, the lack of test coverage is a weak spot that puts added pressure on all other parts of the system.
So, some biological food for thought. What’s reassuring, perhaps, is that nature has designed a system that causes organisms to constantly improve and adapt as a result of their changing environments. And if our code is subject to the same laws, then the good news is that we’re slowly moving towards a perfection of our systems. It’s just a matter of seeing the natural laws in play and embracing the evolution.