The Missing README

## Metadata
- Author: [[Chris Riccomini and Dmitriy Ryaboy]] | [[3. Resources/Authors/Chris Riccomini and Dmitriy Ryaboy|Chris Riccomini and Dmitriy Ryaboy]]
- Full Title: The Missing README
- Category: #books
- Kindle: [Open in Kindle](https://www.amazon.com/dp/B08XM2CDZM)
- Document Tags: [[DevWork]]
## Document Notes
## Highlights
- M. Broadwell defines four stages of competence in Teaching for Learning: unconscious incompetence, conscious incompetence, conscious competence, and unconscious competence. ([Location 606](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=606))
- unconscious incompetence means you are unable to perform a task correctly and are unaware of the gap. ([Location 607](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=607))
- Conscious incompetence means you are unable to perform a task correctly but are aware of the gap. ([Location 608](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=608))
- Conscious competence means you are capable of performing a task with effort. ([Location 609](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=609))
- unconscious competence means you are capable of performing a task effortlessly. ([Location 609](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=609))
- Spend your first few months on the job learning how everything works. ([Location 625](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=625))
- Front-loaded learning does not mean sitting around reading documentation all day. We learn a little by reading and a lot by doing. ([Location 631](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=631))
- Run experiments to learn how code truly works. ([Location 649](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=649))
- Experiment by throwing an exception, printing a stack trace, or attaching a debugger to see the call path. ([Location 651](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=651))
- Spend a portion of each week reading. There are many different sources: team documentation, design documents, code, ticket backlogs, books, papers, and technical sites. ([Location 662](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=662))
- Conferences and meetups are good for networking and discovering new ideas. ([Location 700](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=700))
- Shadowing is following another person as they perform a task. The shadower is an active participant: they take notes and ask questions. ([Location 720](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=720))
- Pair programming is also a great way to learn. Two engineers write code together, taking turns doing the typing. It takes some getting used to, but it’s one of the fastest ways to learn from each other. ([Location 725](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=725))
- Don’t choose a project based on what you think you need to learn. Find problems you are interested in solving, and solve those problems using the tools you want to learn. A goal that intrinsically motivates you will keep you engaged longer, and you’ll learn more. ([Location 738](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=738))
- Asking questions effectively will help you learn quickly without irritating others. Use these three steps: do research, ask clear questions, and time your questions appropriately. ([Location 747](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=747))
- Limit how long you research a question. Set the limit before you start your research to encourage discipline and prevent diminishing returns (research will eventually stop being productive). Consider when you need to know the answer, and then leave enough time to ask a question, get an answer, and act on what you learn. ([Location 756](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=756))
- Describe what you know when asking a question. Don’t just share your raw notes. Outline what you’ve tried and discovered succinctly. ([Location 762](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=762))
- they need to focus. When they’re in the zone, don’t interrupt them. ([Location 786](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=786))
- Schedule a meeting, or use “office hours” if they exist. Write down questions and hold them until the meeting. You can do your research in the meantime. ([Location 805](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=805))
- Dunning–Kruger effect, a cognitive bias where people believe that they’re more capable than they actually are. ([Location 837](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=837))
- Messy code is a natural side effect of change; don’t blame developers for the untidiness. This drift toward disarray is known as software entropy. ([Location 881](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=881))
- Technical debt is a major cause of software entropy. Technical debt is future work that’s owed to fix shortcomings in existing code. ([Location 887](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=887))
- Prudent, deliberate debt is the classic form of tech debt: a pragmatic trade-off between a known shortcoming in the code and speed of delivery. This is good debt as long as the team is disciplined about addressing it later. ([Location 907](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=907))
- Reckless, deliberate debt is created when teams are under pressure to deliver. ([Location 909](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=909))
- Reckless, inadvertent debt comes from unknown unknowns. You can mitigate the danger of recklessly inadvertent debt by preemptively writing down and getting feedback on implementation plans and doing code reviews. ([Location 911](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=911))
- Prudent, inadvertent debt is a natural outcome of growing experience. Some lessons are only learned in hindsight: ([Location 913](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=913))
- good framework for discussing technical debt: State the situation factually. Describe the risk and cost of the debt. Propose a solution. Discuss alternatives (including not taking action). Weigh the trade-offs. ([Location 928](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=928))
- Changing code is not like writing code in a fresh repository. You have to make changes without breaking existing behavior. ([Location 950](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=950))
- safely modify existing codebases: Identify change points. Find test points. Break dependencies. Write tests. Make changes and refactor. ([Location 958](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=958))
- Test points are entry points into the code that you want to modify—the areas that tests invoke and inject into. ([Location 968](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=968))
- Breaking dependencies means changing code structure so that it’s easier to test. ([Location 972](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=972))
- leave code cleaner than you found it—will help your code get better over time. ([Location 992](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=992))
- Code smell is a term for code that isn’t necessarily buggy but uses patterns known to cause problems; it “smells funny.” ([Location 997](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=997))
- Frequent commits show how code changes over time, let you undo changes, and act as a remote backup. ([Location 1032](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1032))
- Separate subject from body with a blank line. Limit the subject line to 50 characters. Capitalize the subject line. Do not end the subject line with a period. Use the imperative mood in the subject line. Wrap the body at 72 characters. Use the body to explain what and why versus how. Chris’s post is worth a read; it describes good hygiene. ([Location 1040](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1040))
- Don’t ignore your company’s (or industry’s) standards because you don’t like them. Writing nonstandard code means that it won’t fit in with the company’s environment. ([Location 1102](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1102))
- A fork is a complete, independent copy of another source code repository. It has its own trunk, branches, and tags. ([Location 1116](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1116))
- Defensive code fails less often, and when it does, it is more likely to recover. Make your code safe and resilient. Safe code takes advantage of compile-time validation to avoid runtime failures. Use immutable variables, access modifiers to restrict scope, and static type-checkers to prevent bugs. ([Location 1186](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1186))
- Follow the “throw early, catch late” principle. ([Location 1277](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1277))
- Throwing early means raising exceptions as close to the error as possible so developers can quickly find the relevant code. ([Location 1277](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1277))
- Catching exceptions late means propagating exceptions up the call stack until you reach the level of the program that is capable of handling the exception. ([Location 1282](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1282))
- Measure all of the following data structures, operations, and behaviors: Resource pools Caches Data structures CPU-intensive operations I/O-intensive operations Data size Exceptions and errors Remote requests and responses ([Location 1460](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1460))
- Developers all know about stack traces, but there’s a less familiar kind of trace: a distributed call trace. ([Location 1481](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1481))
- Distributed call traces stitch all of these downstream calls together into one graph. Distributed traces are useful for debugging errors, measuring performance, understanding dependencies, and analyzing system cost (which APIs are the most expensive to serve, which customers cost the most, and so on). ([Location 1482](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1482))
- the cleverer your configuration scheme is, the more bizarre your bugs will be. Do not get creative with configuration—use the simplest possible approach that will work. A static configuration file in a single standard format is ideal. ([Location 1512](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1512))
- Logging config values shows users whether the application is seeing the expected configuration. ([Location 1529](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1529))
- To keep configuration changes safe, configuration should be version controlled, reviewed, tested, built, and published. ([Location 1547](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1547))
- Clean configuration is easier for others to understand and change. Delete unused configuration, use standard formatting and spacing, and don’t blindly copy configuration from other files ([Location 1551](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1551))
- A dependency is code that your code relies on. The time at which a dependency is needed—during compilation, testing, or runtime—is called its scope. ([Location 1632](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1632))
- The packages in the previous example use a versioning scheme called semantic versioning (SemVer), one of the most commonly used versioning schemes. The official SemVer specification is available at https://semver.org/. The spec defines three numbers: the major, minor, and patch version ([Location 1652](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1652))
- The most common dependency hell culprits are circular dependencies, diamond dependencies, and version conflicts. ([Location 1690](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1690))
- yourself if a dependency’s value outweighs its cost. Do you really need the functionality? How well maintained is the dependency? How easy would it be for you to fix the dependency if something went wrong? How mature is the dependency? How frequently does the dependency introduce backward-incompatible changes? How well do you, your team, and your organization understand the dependency? How easy is it to write the code yourself? How is the code licensed? What is the ratio of code you use versus code you don’t use in the dependency? When you do decide to add dependencies, use the following best practices. ([Location 1742](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1742))
- You don’t have to leave dependency management to build and package systems. Dependent code can also be copied, vendored, or shaded. ([Location 1751](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1751))
- Dependency shading can also isolate dependencies. Shading automatically relocates a dependency into a different namespace to avoid conflicts: some.package.space becomes shaded.some.package.space. ([Location 1760](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1760))
- Dependency scope, discussed earlier, defines when in the build lifecycle a dependency is used. ([Location 1810](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1810))
- Scoping has a hierarchy: compile-time dependencies are used during runtime, but runtime dependencies are not used to compile code, only to run it. ([Location 1811](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1811))
- tests serve other purposes as well. They protect the code from future changes that unintentionally alter its behavior, encourage clean code, force developers to use their own APIs, document how components are to be interacted with, and serve as a playground for experimentation. ([Location 1849](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1849))
- Test writing also forces developers to think about the interface and implementation of their program. ([Location 1855](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1855))
- Spaghetti code, or code that has too many dependencies, is difficult to test. ([Location 1857](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1857))
- Writing tests forces developers to keep their code well factored by improving separation of concerns and reducing tight coupling. ([Location 1858](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1858))
- Tests serve as a form of documentation, illustrating how the code is meant to be interacted with. ([Location 1862](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1862))
- Unit tests verify “units” of code—a single method or behavior. Unit tests should be fast, small, and focused. ([Location 1868](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1868))
- Integration tests verify that multiple components work together. ([Location 1871](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1871))
- System tests verify a whole system. End-to-end (e2e, for short) workflows are run to simulate real user interactions in preproduction environments. ([Location 1886](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1886))
- Synthetic monitoring scripts run in production to simulate user registration, browse for and purchase an item, and so on. ([Location 1890](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1890))
- Performance tests, such as load and stress tests, measure system performance under different configurations. ([Location 1892](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1892))
- Load tests measure performance under various levels of load: for example, how a system performs when 10, 100, or 1,000 users access it concurrently. ([Location 1893](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1893))
- Stress tests push system load to the point of failure. ([Location 1894](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1894))
- Acceptance tests are performed by a customer, or their proxy, to validate that the delivered software meets acceptance criteria. ([Location 1896](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1896))
- Test-writing tools like mocking libraries help you write clean and efficient tests. ([Location 1910](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1910))
- Test frameworks help run tests by modeling a test’s lifecycle from setup to teardown. ([Location 1911](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1911))
- Code quality tools are used to analyze code coverage and code complexity, find bugs through static analysis, and check for style errors. ([Location 1912](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1912))
- Mocking libraries are commonly used in unit tests, particularly in object-oriented code. ([Location 1918](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1918))
- Mocks replace external dependencies with stubs that mimic the interface provided by the real system. ([Location 1919](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1919))
- Test frameworks help you write and execute tests. ([Location 1932](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1932))
- Frameworks do the following: Manage test setup and teardown Manage test execution and orchestration Generate test result reports Provide tooling such as extra assertion methods Integrate with code coverage tools ([Location 1933](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1933))
- Tools that enforce code quality rules are called linters. Linters run static analysis and perform style checks. ([Location 1952](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1952))
- Static code analyzers look for common mistakes, like leaving file handles open or using unset variables. ([Location 1954](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1954))
- Code style checkers ensure all source code is formatted the same way: max characters per line, camelCasing versus snake_casing, proper indentation, that sort of thing. ([Location 1958](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1958))
- Code complexity tools guard against overly complex logic by calculating cyclomatic complexity, or, roughly, the number of paths through your code. ([Location 1961](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1961))
- Code coverage tools measure how many lines of code were exercised by the test suite. ([Location 1965](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1965))
- quality assurance (QA) teams with varying responsibilities, including the following: Writing black-box or white-box tests Writing performance tests Performing integration, user acceptance, or system tests Providing and maintaining test tools Maintaining test environments and infrastructure Defining formal test certification and release processes ([Location 1976](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=1976))
- Deterministic code always produces the same output for the same input. ([Location 2021](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2021))
- nondeterministic code can return different results for the same inputs. ([Location 2022](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2022))
- Random number generators (RNGs) must be seeded with a value that dictates the random numbers you get from it. ([Location 2035](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2035))
- Code that depends on specific intervals of time can cause nondeterminism if not handled correctly. ([Location 2049](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2049))
- test execution frameworks often use the same process for multiple tests, which means leaked system resources like network sockets or file handles won’t be immediately cleaned. ([Location 2082](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2082))
- Tests should not depend on a specific order of execution. Ordering dependencies usually happen when a test writes data and a subsequent test assumes the data is written. ([Location 2114](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2114))
- Unit Testing by Vladimir Khorikov (Manning Publications, 2020) is the place to go if you want more on testing best practices. ([Location 2138](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2138))
- Code reviews act as an archive for implementation decisions. Having older code reviews to consult provides developers with a written history. ([Location 2170](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2170))
- You can sanity-check what you’re doing by submitting a draft review: an informal review request intended to get quick and cheap feedback from teammates, which significantly reduces the risk that you go too far down the wrong path. ([Location 2202](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2202))
- Conduct code walk-throughs when making large changes. Walk-throughs are in-person meetings where a developer shares their screen and walks teammates through the changes that are being made. Walk-throughs are a great way to trigger ideas and get your team comfortable with changes. ([Location 2220](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2220))
- Start by triaging the review request. Some changes are critical and need to be reviewed right away. Most changes, however, are less pressing. ([Location 2258](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2258))
- Don’t drop everything you’re doing every time a review request arrives. Left unchecked, review interruptions can torpedo your productivity. Block off code review time in your calendar. ([Location 2265](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2265))
- Code reviews are most valuable if the reviewer really takes the time to understand the proposed changes. ([Location 2273](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2273))
- Don’t forget that code reviews are just code. You can still check out or download the proposed changes and play with them locally. ([Location 2324](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2324))
- Make sure to check tests for maintainability and code cleanliness. Look for bad test patterns: execution ordering, lack of isolation, and remote system calls. ([Location 2333](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2333))
- four software delivery phases, namely build, release, deployment, and rollout, ([Location 2388](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2388))
- Frequently merging is known as continuous integration (CI). CI reduces risk because changes quickly propagate to all developers, making them less likely to diverge from each other significantly. ([Location 2416](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2416))
- In feature branch–based development, many developers simultaneously work on long-lived feature branches, each associated with a feature in the product. ([Location 2421](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2421))
- rebase—to pull in changes from trunk—so the feature branch doesn’t diverge too far. ([Location 2423](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2423))
- Feature branch–based development is common when trunk is too unstable to release to users and developers want to avoid entering a feature freeze where feature commits are banned while trunk is stabilized. ([Location 2426](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2426))
- Building software takes many steps: resolving and linking dependencies, running linters, compiling, testing, and, finally, packaging the software. ([Location 2448](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2448))
- Packages should be versioned and assigned a unique identifier. Unique identifiers help operators and developers tie a running application to specific source code, feature sets, and documentation. ([Location 2467](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2467))
- Software is not just code. Configuration, schemas, images, and language packs (translations) are all part of software. Different resources have different release cadences, different build times, and different testing and verification needs. ([Location 2471](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2471))
- Release management is the art of publishing stable, well-documented software at a predictable cadence. Proper release management makes for satisfied customers. ([Location 2506](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2506))
- Release packages are usually published to a package repository or simply tagged and housed in a VCS like Git. ([Location 2519](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2519))
- Once published, never change or overwrite a release package. Immutable releases guarantee that all application instances running a specific version will be identical, byte for byte. ([Location 2537](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2537))
- Release schedules define how frequently software is released. Some projects have a predictable time-based schedule, releasing every quarter or year. ([Location 2548](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2548))
- Changelogs and release notes help your users and your support team understand what is included in a release. ([Location 2552](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2552))
- Changelogs list every ticket that was fixed or commit that was made in a release. To automate changelog creation, track changes in commit messages or issue tracker labels. ([Location 2553](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2553))
- Release notes are a summary of the new features and bug fixes contained in a release. Changelogs are primarily read by the support and development team, while release notes are for users. ([Location 2555](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2555))
- Deploying software is the act of getting software packages where they need to be to run. ([Location 2572](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2572))
- Automated deployments are more predictable because script behavior is reproducible and version controlled. ([Location 2575](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2575))
- Off-the-shelf solutions like Puppet, Salt, Ansible, and Terraform integrate with existing tooling and are purpose-built for deployment automation. ([Location 2585](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2585))
- Feature flags allow you to control what percentage of users receive one code path versus another. ([Location 2628](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2628))
- Circuit breakers automatically switch code paths when there’s trouble. ([Location 2629](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2629))
- Dark launches, canary deployments, and blue-green deployments let you run multiple deployed versions of your software simultaneously. ([Location 2630](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2630))
- Feature flags can be on-off Booleans, allow lists, percentage-based ramps, or even small functions. A Boolean will toggle the feature for all users. Allow lists turn on features for specific users. Percent-based ramps allow developers to slowly turn on the feature for larger swaths of users. ([Location 2647](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2647))
- Canary deployments are used for services that process a lot of traffic and are deployed to a large number of instances. ([Location 2677](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2677))
- Blue-green deployments run two different versions of the application: one active and one passive. ([Location 2685](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2685))
- Google’s Site Reliability Engineering book offers ([Location 2980](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=2980))
- technical design process helps everyone agree on a design for a large change. ([Location 3123](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=3123))
- solitary deep-thought work and collaborative group discussion. ([Location 3124](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=3124))
- define and understand the problem (or problems) that you’re trying to solve. ([Location 3161](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=3161))
- synthesize the feedback into a clear problem statement. ([Location 3170](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=3170))
- Don’t go straight from problem definition to “final” design. Consider relevant research, alternative solutions, and trade-offs. ([Location 3195](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=3195))
- Experiment with your ideas by writing draft code and running tests. ([Location 3209](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=3209))
- Good design takes creativity. Don’t expect to sit down and bang out a design in one shot. Give yourself large chunks of time, take breaks, change your scenery, and be patient. ([Location 3216](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=3216))
- Design documents are a scalable way to clearly communicate your ideas. The process of writing structures your thinking and highlights areas of weakness. ([Location 3233](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=3233))
- Two common pitfalls occur during the transition from proposal to documentation. The first pitfall is that the proposal document is abandoned and never updated again. Implementations diverge, and the document is misleading to future users. The second pitfall is that the document is updated, and the history of the proposal is lost. ([Location 3285](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=3285))
- A Philosophy of Software Design ([Location 3471](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=3471))
- High dependency leads software to rely on other code’s API or behavior. ([Location 3475](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=3475))
- High-dependency systems are hard to modify because they have tight coupling and high change amplification. Tight coupling describes modules that depend heavily on one another. ([Location 3476](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=3476))
- High obscurity makes it difficult for programmers to predict a change’s side effects, how code behaves, and where changes need to be made. ([Location 3480](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=3480))
- Inertia, the characteristic that we’ve added to Ousterhout’s list, is software’s tendency to stay in use. ([Location 3484](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=3484))
- Flexible abstractions—plugin architectures, wrapper interfaces, and generic data structures like key-value pairs—are another temptation. Developers think they can easily adjust if some new requirement pops up. But abstraction comes with a cost; it boxes implementations into rigid boundaries that the developer ends up fighting later. ([Location 3512](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=3512))
- We are uncovering better ways of developing software by doing it and helping others do it. Through this work we have come to value: Individuals and interactions over processes and tools Working software over comprehensive documentation Customer collaboration over contract negotiation Responding to change over following a plan That is, while there is value in the items on the right, we value the items on the left more. ([Location 3839](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=3839))
- Agile practices focus on collaboration with teammates and customers; recognizing, accepting, and incorporating change; and focusing on iterative improvement over big-bang development releases. ([Location 3846](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=3846))
- Scrum, the most popular, encourages short iterations with frequent checkpoints to adjust plans. Development work is broken into sprints. Sprint length varies, with two weeks being most common. ([Location 3853](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=3853))
- At the beginning of a sprint, each team has a sprint planning meeting to divvy up work, which is captured in user stories or tasks. ([Location 3855](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=3855))
- Progress is tracked in a ticketing or issue system. A ([Location 3856](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=3856))
- stand-up meeting takes place every day to share updates and call out problems. ([Location 3857](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=3857))
- retrospective to review finished work, discuss new findings, look at key metrics, and fine-tune the process. Retrospectives (retros) inform the next sprint’s planning session, creating a feedback cycle from plan to development to retrospective and back to plan. ([Location 3858](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=3858))
- Kanban does not use fixed-length sprints like Scrum. Instead, Kanban defines workflow stages through which all work items transition (for example, backlog, planning, implementation, testing, deployment, rollout). ([Location 3860](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=3860))
- By limiting ticket count, teams are forced to finish existing tasks before taking on new work. ([Location 3863](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=3863))
- Developers and product managers create new user stories, and tickets from the backlog are triaged. ([Location 3874](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=3874))
- Stories are assigned story points to estimate their complexity and are broken into tasks. ([Location 3875](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=3875))
- During sprint planning, the team chooses which stories to complete during the next sprint, using story points to prevent overcommitting. ([Location 3876](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=3876))
- User story estimates are a guess at the effort a story takes to implement. ([Location 3886](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=3886))
- Acceptance criteria define when a story is complete. ([Location 3887](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=3887))
- Backlog triage or grooming (in the tree-trimming sense) usually takes place before planning meetings. ([Location 3933](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=3933))
- The backlog is a list of candidate stories. ([Location 3934](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=3934))
- Triage is used to keep it fresh, relevant, and prioritized. ([Location 3934](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=3934))
- A sprint planning meeting is held once prework is done. Planning meetings are collaborative; engineering teams work with product managers to decide what to work on. ([Location 3938](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=3938))
- Sprint capacity is determined by looking at how much was completed in previous sprints. ([Location 3941](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=3941))
- stand-up meetings, also called scrum meetings or huddles. Stand-ups keep everyone apprised of your progress, keep you accountable and focused, and give the team an opportunity to react to anything that puts sprint goals in danger. ([Location 3954](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=3954))
- A review happens between each sprint. Reviews are usually broken into two parts: demonstrations and project review. ([Location 3979](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=3979))
- In a retrospective, a team gets together to talk about what has and hasn’t gone well since the last retrospective. The meeting normally has three phases: sharing, prioritization, and problem solving. ([Location 3998](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=3998))
- Reviews are focused on the work done in a sprint, while retrospectives focus on process and tooling. ([Location 4006](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=4006))
- Retrospectives normally take place between sprints, often right after review meetings. ([Location 4007](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=4007))
- Managers use product roadmaps for long-term planning. Roadmaps are typically broken into quarters: January through March, April through June, July through September, and October through December. ([Location 4015](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=4015))
- One-on-ones (1:1s) and progress-plans-problems (PPP) reports are used for communication and updates, while objectives and key results (OKRs) and performance reviews manage goals and growth. ([Location 4081](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=4081))
- Situation-Behavior-Impact (SBI) framework when providing feedback. First describe the situation. Then, describe the behavior: a specific behavior you find praiseworthy or problematic. Finally, explain the impact: the effect of the behavior and the reason it’s important. Here is an example: ([Location 4230](https://readwise.io/to_kindle?action=open&asin=B08XM2CDZM&location=4230))