Effective teams write less software, and writing less software enables teams to be more effective. This may sound counterintuitive at first: Aren’t we all here as engineers to write software? Isn’t our productivity measured in lines of code? To dispel this illusion, we need to stop conflating what we sometimes do with why.
As engineers, we design and build solutions to the problems that our businesses face. Writing code of our own is often part of the answer. But just as we wouldn’t insist that every bridge be built with bespoke girders and bolts, or that all electrical plugs and sockets have their own form factors, we shouldn’t insist on custom-building every part of the designs that we craft. Instead, we should focus our teams’ finite energy on the places where they can deliver unique value. If we reward teams and individuals for reinventing the wheel rather than for the smart reuse of existing components, we’re dooming ourselves to costly, artisanal efforts rather than efficient shared platforms.
Build what you must, buy what you can, and write it all down
When we’re building something new, our work starts with mapping out an overall strategy, with an understanding of the organization’s context and needs, and writing the pieces that we must create ourselves. As the project progresses, we identify appropriate vendors and suppliers for the pieces we think are more efficient to purchase off the shelf than to build from scratch. The work ends with integrating all of these components into solutions for our customers. And since engineering is a continuous rather than one-time process, we ought to document our decisions for future maintainability, and to share what we’ve learned within our organizations and our broader communities.
Simon Wardley’s Wardley maps demonstrate that it’s important to consider how commercially available the component we need is, and where it fits in the value chain between other intermediate components and the end user. If something is a commodity with a common interface, such as electricity or blob file storage, it can be bid out to a number of suppliers on the basis of price and convenience. If the component is standardized enough to assemble from existing products, perhaps we can adapt them and make only small modifications, or add our own glue in between. Only if a component doesn’t exist in the marketplace, or if creating it would yield a unique competitive advantage, should we resort to custom work.
In order to understand which components we may need and how to assemble them, the very first step is to gather requirements on the problem we face today and how far the solution must scale. This allows us to identify which pieces are unique rather than commodities, and which pieces must be completed soonest to begin delivering value. For platform and infrastructure projects in particular, reaching out to the teams expected to use the infrastructure is essential. Disconnects between the teams that design tools and the teams that use them waste innovation. Internal platforms and tools especially need product managers and developer advocates to ensure that software meets user needs and will be enthusiastically adopted rather than abandoned on the side of the road.
Premature optimization for the wrong set of requirements artificially boxes us in and constrains our options. Of course you’re going to conclude that you need your own software if you insist that your product has to support streaming trillions of blockchain transactions, at 10 milliseconds latency, from interstellar space! Apply enough design constraints to solve your immediate problem, as well as to prepare for where you reasonably expect to be in a year. Along the way, write down the alternatives you considered and why you didn’t choose them. You might save time for someone else—or even yourself— during a future evaluation of which design pieces to revisit.
Focus on the impact, not the volume
Incentives matter, as does the tone that leadership takes. Focus on rewarding your team for the impact that they achieved relative to the resources, both present and future, that they expended. Rather than cheering on engineers for designing brand-new components, or for writing a certain number of lines of code, zoom out and focus on your employees’ impact.
What’s the hero’s tale of your team members? “Before I came along, customer X needed to spend 30 minutes per day manually inputting customer orders from a spreadsheet into the order system, but after doing requirements gathering, we realized that a majority of the spreadsheets could be automatically parsed and checked for exceptions. Now customer X is able to focus only on the most important cases—and we only needed to write the custom data-validation rules rather than writing an entire CSV-parsing stack we had to maintain!” Formulating your team’s accomplishments to articulate business value and trade-offs enables you to more easily reward team members for strategic engineering instead of tactical hacks.
The messaging platform Intercom has made a mantra out of “Run less software,” enabling it to focus its several hundred engineers on where it uniquely adds value, rather than on undifferentiated heavy lifting. Its leadership has recognized that every line of code written in-house requires ongoing care, feeding, and support. The more things can be outsourced to vendors, the less internal teams have to do themselves.
When any team decides to write its own code, it’s essential to implement a long-term maintenance plan for the code itself as well as a product strategy. Google’s Richard Bondi and Max Luebbe, in their talks at SREcon Americas, emphasize that without a clear purpose and strategy, scattershot user contributions to a codebase will saddle it with technical debt. This debt often manifests in sprawling feature sets, unclear ownership, or even spooky bugs manifesting far from the code that engineers are modifying.
Share what you make, and how you made it
If you identified a gap in the marketplace or a missing component that caused you to write something of your own, there’s value in open-sourcing your work. And when you share your technology, share the design patterns and motivations too, so that others can understand whether it’s right for their use case, and so that they can easily contribute. Unless the software you wrote is a critical competitive advantage, sharing it enables others to both benefit and participate in its maintenance.
And sharing code goes beyond traditional open source. At larger companies, efforts by individual teams may duplicate work already performed elsewhere within the enterprise—thus “inner-sourcing” curation and centralized platform-engineering efforts become necessary. Is the reuse of others’ technology rewarded? If your company does not have internal tech talks or common documentation and source repositories, consider instating them. Examine how employees learn about innovation that happens in the company’s other lines of business. And hire more technical writers to act as librarians of your commons!
Whether internal or external, sharing is also a responsibility. The maxim “Don’t reward unnecessary complexity” doesn’t only apply to companies, it applies to our communities too. (Just because something is a popular post on Hacker News doesn’t mean that it’s the right thing for your team or company to adopt.) Don’t dump hacks. And, most of all, don’t cultivate toxic communities that lack codes of conduct and are full of strife.
Bespoke software development should be a last, rather than first, resort. We must set up our teams and companies to reward impact from reusing code rather resume-driven whole-cloth development. Write less code. Do more engineering.