More on this book
Community
Kindle Notes & Highlights
Started reading
August 4, 2020
The great thing about tech is that there is never only one way to do something. Instead, there is a series of trade-offs we all must make depending on the circumstances of our team and situation.
One key insight we share in this book is that software engineering can be thought of as “programming integrated over time.” What practices can we introduce to our code to make it sustainable — able to react to necessary change — over its life cycle, from conception to introduction to maintenance to deprecation?
Nothing is built on stone; all is built on sand, but we must build as if the sand were stone. Jorge Luis Borges
On a software engineering project, engineers need to be more concerned with the passage of time and the eventual need for change.
Within Google, we sometimes say, “Software engineering is programming integrated over time.”
A programming task is often an act of individual creation, but a software engineering task is a team effort.
The job of a software engineer, or a software engineering leader, is to aim for sustainability and management of the scaling costs for the organization, the product, and the development workflow.
A serial startup developer could very reasonably have 10 years of development experience and little or no experience maintaining any piece of software expected to exist for longer than a year or two.
With a sufficient number of users of an API, it does not matter what you promise in the contract: all observable behaviors of your system will be depended on by somebody.
Hyrum’s Law represents the practical knowledge that — even with the best of intentions, the best engineers, and solid practices for code review — we cannot assume perfect adherence to published contracts or best practices.
Given enough time and enough users, even the most innocuous change will break something;9 your analysis of the value of that change must incorporate the difficulty in investigating, identifying, and resolving those breakages.
Looking at code as an artifact with a (highly) variable lifetime requirement, we can begin to categorize programming styles: code that depends on brittle and unpublished features of its dependencies is likely to be described as “hacky” or “clever,” whereas code that follows best practices and has planned for the future is more likely to be described as “clean” and “maintainable.”
“Your organization’s codebase is sustainable when you are able to change all of the things that you ought to change, safely, and can do so for the life of your codebase.”
Everything your organization relies upon to produce and maintain code should be scalable in terms of overall cost and resource consumption. In particular, everything your organization must do repeatedly should be scalable in terms of human effort.
As the size of an organization (and the number of branches) increases, it quickly becomes apparent that we’re paying an ever-increasing amount of overhead to do the same task.
“If a product experiences outages or other problems as a result of infrastructure changes, but the issue wasn’t surfaced by tests in our Continuous Integration (CI) system, it is not the fault of the infrastructure change.”
We’ve found that expertise and shared communication forums offer great value as an organization scales.
If you have a hundred engineers writing Java, a single friendly and helpful Java expert willing to answer questions will soon produce a hundred engineers writing better Java code.
Knowledge is viral, experts are carriers, and there’s a lot to be said for the value of clearing away the common stumbling blocks for your engineers.
One of the broad truths we’ve seen to be true is the idea that finding problems earlier in the developer workflow usually reduces costs.
Bugs that are caught by static analysis and code review before they are committed are much cheaper than bugs that make it to production.
Jevons Paradox: consumption of a resource may increase as a response to greater efficiency in its use.
Even a relatively simple trade-off of the form “We’ll spend $$$s for compute resources to recoup engineer time” had unforeseen downstream effects.
time doesn’t only trigger changes in technical dependencies and software systems, but in data used to drive decisions.
Contrary to some people’s instincts, leaders who admit mistakes are more respected, not less.
Be evidence driven, but also realize that things that can’t be measured may still have value. If you’re a leader, that’s what you’ve been asked to do: exercise judgement, assert that things are important.
Programming is the immediate act of producing code. Software engineering is the set of policies, practices, and tools that are necessary to make that code useful for as long as it needs to be used and allowing collaboration across a team.
“Software engineering” differs from “programming” in dimensionality: programming is about producing code. Software engineering extends that to include the maintenance of that code for its useful life span.
Hyrum’s Law: with a sufficient number of users of an API, it does not matter what you promise in the contract: all observable behaviors of your system will be depended on by somebody.
Every task your organization has to do repeatedly should be scalable (linear or better) in terms of human input. Policies are a wonderful tool for making process scalable.
Process inefficiencies and other software-development tasks tend to scale up slowly. Be careful...
This highlight has been truncated due to consecutive passage length restrictions.
Expertise pays off particularly well when combined with e...
This highlight has been truncated due to consecutive passage length restrictions.
“Because I said so” is a terrible reason...
This highlight has been truncated due to consecutive passage length restrictions.
Being data driven is a good start, but in reality, most decisions are based on a mix of data, assumption, precedent, and argument. It’s best when objective data makes up the majority ...
This highlight has been truncated due to consecutive passage length restrictions.
Being data driven over time implies the need to change directions when the data changes (or when assumptions are dispelled). Mist...
This highlight has been truncated due to consecutive passage length restrictions.
People are inherently imperfect — we like to say that humans are mostly a collection of intermittent bugs.
The critical idea in this chapter is that software development is a team endeavor. And to succeed on an engineering team — or in any other creative collaboration — you need to reorganize your behaviors around the core principles of humility, respect, and trust.
People are afraid of others seeing and judging their work in progress. In one sense, insecurity is just a part of human nature — nobody likes to be criticized, especially for things that aren’t finished.
Linus’ real achievement was to lead these people and coordinate their work;
The Genius Myth is the tendency that we as humans need to ascribe the success of a team to a single person/leader.
And what about Michael Jordan? It’s the same story. We idolized him, but the fact is that he didn’t win every basketball game by himself. His true genius was in the way he worked with his team. The team’s coach, Phil Jackson, was extremely clever, and his coaching techniques are legendary. He recognized that one player alone never wins a championship, and so he assembled an entire “dream team” around MJ. This team was a well-oiled machine — at least as impressive as Michael himself.
Being a genius is most definitely not an excuse for being a jerk: anyone — genius or not — with poor social skills tends to be a poor teammate.
It turns out that this Genius Myth is just another manifestation of our insecurity. Many programmers are afraid to share work they’ve only just started because it means peers will see their mistakes and know the author of the code is not a genius.
If you keep your great idea hidden from the world and refuse to show anyone anything until the implementation is polished, you’re taking a huge gamble. It’s easy to make fundamental design mistakes early on. You risk reinventing wheels.2 And you forfeit the benefits of collaboration, too:
Remember: team members might not literally be hit by buses, but other unpredictable life events still happen. Someone might get married, move away, leave the company, or take leave to care for a sick relative. Ensuring that there is at least good documentation in addition to a primary and a secondary owner for each area of responsibility helps future-proof your project’s success and increases your project’s bus factor.
Programming is hard. Software engineering is even harder. You need that second pair of eyes.
the earlier we find a problem, the cheaper it is to fix it.
Software today is written by teams, not individuals, and a high-bandwidth, readily available connection to the rest of your team is even more valuable than your internet connection.
So, what “hiding” boils down to is this: working alone is inherently riskier than working with others. Even though you might be afraid of someone stealing your idea or thinking you’re not intelligent, you should be much more concerned about wasting huge swaths of your time toiling away on the wrong thing.
The moral is this: do not underestimate the power of playing the social game. It’s not about tricking or manipulating people; it’s about creating relationships to get things done. Relationships always outlast projects.

