Code refactoring is the process of restructuring code without changing its external behavior. Refactoring improves how the sausage gets made. Incompetent refactoring is one of the many reasons software companies fail.
You prototype to get something out, receive client feedback and need to make it work for new use cases. Refactor. You learn a particular feature has to work across all screens. Refactor. You learn this feature interacts with another part of the product that changes the way the database should model entities of a given class type. Refactor. You need to make it work at scale. Refactor. You need to change the flow of data and add audit trails. Refactor.
Refactoring is time-consuming. In a perfect world, everything would be modeled perfectly from the start. But that’s not possible when building something new, and it’s suboptimal in the real world when developing an initial product. With current tools, iterative development wins.
Iterative development is having the vision for a bow and arrow but understanding that you should build a sharp stick first. You make string to attach an arrowhead to turn the sharp stick into a spear. Use additional string as a bowstring when building the bow. If you can make every development phase useful, that’s a huge win.
You’ll need to refactor the stick, arrowhead, and every part of the bow.
Refactoring is costly, but if done on occasion, it is healthy in the long run. Refactoring too often and too early is the bane of shipping. Pre-optimization is the root of all evil.
To Refactor or Not to Refactor
I’ve seen developers spend years refactoring. Developers will make the stick as sharp as humanly possible when it will eventually be replaced by an arrowhead. It’s easy to get lost in architecting software to support imagined edge cases. It can even be fun, but it’s a massive waste of time.
On the flip side, waiting too long to refactor creates technical debt. The debt can accumulate to the point of needing to rewrite the entire product from scratch. When to refactor is hard to determine.
The game Factorio lends itself well to coding analogies.
You start off doing things that don’t scale and slowly automate more and more processes over time. You destroy your old facilities and replace them with more optimized ones. You only refactor when you’re adding new functionality to that area. This applies to more than the codebase.
How teams are structured should change over time as well. Early on at a startup, things can be fuzzy. Everyone is highly invested in the company and does what they can to accomplish any task. This culture should be encouraged, but an ambiguous structure must eventually be defined. At scale, it’s necessary to refactor to have a directly responsible individual (DRI) for each task.
For operations teams, logical delineation comes into play at scale.
Let’s take an executive assistant– when an executive has 5 meetings/day, one great assistant can schedule all of them and do other tasks. When an executive has 12 meetings/day plus travel, restaurant reservations, events they host, CRM needs, follow ups, and needing to know who to prioritize to meet– having one great assistant doesn’t work anymore. The only way to solve the problem while keeping the same quality output is to hire an additional assistant and refactor. There are multiple ways to do it. I prefer having logical delineation where there’s a DRI for each task.
A startup is constantly undergoing iterative development as it scales. It’s on leaders to be conscientious about how this plays out.