notes

The Effective Engineer

(last updated )

cover

Description

Introducing The Effective Engineer--the only book designed specifically for today's software engineers, based on extensive interviews with engineering leaders at top tech companies, and packed with hundreds of techniques to accelerate your career.

  • Effective Engineers focus on value and impact— they know how to choose which results to deliver

  • An effective engineer is defined by the rate at which he or she produces value per unit of time worked

  • Leverage is defined by: $$\text{Leverage}=\frac{\text{impact/value}}{\text{time invested}}$$ aka the ROI of the effort put in.

  • Effective engineers aren’t the ones trying to get more things done, they’re the ones who get things done efficiently and who focus their limited time on the tasks that produce the most value.

  • they use this simple equation for leverage as their central guiding metric for determining how and where to spend their time

Part 1: Adopt the Right Mindsets

Increasing your Leverage in three ways

  1. by reducing the time it takes to complete a certain activity
  2. by increasing the output of an activity
  3. by shifting to higher leverage activitities Which naturally translates into three questions we can ask to increase the leverage of an activity:
  4. How can I get this done faster?
  5. How can I increase the value produced by this activity?
  6. Is there something else I can spend my time on which will produce the most value?
  • constantly keep one lesson in mind: focus on high leverage activities.

  • Mentoring activities included everything from:

    • reviewing code
    • outlining technical skills to learn
    • pair programming
    • discussing engineering tradeoffs
    • explaining how to priorise better
    • offering guidance on how to work well with different team members

Dedicate time on the job to develop new skills

10 suggestions to take advantage of resources available to you at work

  1. study code for core abstractions written by the best engineers at your company
  2. write more code
  3. go through any any technical, educational material available internally
  4. Master the programming languages that you use
  5. send your code reviews to the harshest critics
  6. enroll in classes on areas you want to improve
  7. participate in design discussions of projects your interested in.
  8. work on a diversity of projects
  9. make sure your on a team with atleast a few senior engineers whom you can learn from
  10. jump fearlessly into code you dont know.

Key Takeaways

  • own your own story — focus on changes that are within your sphere of influence
  • dont shortchange your learning rate
  • find work environments that can sustain your growth
  • capitalize on opportunities at work to improve your technical skills
  • locate learning opportunities outside of the workplace

Prioritization

  • the first heuristic of prioritizing high leverage activities: focus on what directly produces value
    • at the end of the day, what matters most is how much value you’ve created. value is measured in terms of products shipped, users acquired, business metrics moved, or sales made.
  • Don’t try to get everything done. Focus on what matters—and what matters is what produces value.
undefined

Protect your makers schedule

  • preserve larger blocks of focused time one your schedule.
    • schedule necessary meetings back to back
    • block off hours on your calendar
    • learn to say no to unimportant activities

Limit the amount of work in progress

  • prioritizing and serializing different projects so that I can maintain strong momentum

fight procrastination with if-then plans

  • (pp 106)
  • Simple strategy to fight procrastination, as described in the book Succeed by Halvorson
    • if-then plan in which we identify ahead of time a situation where we plan to do a certain task
    • when the cue triggers, the then behaviour follows automatically without any conscious effort
  • the concept of if then planning can help fill small gaps in our schedules.
  • ex- if I only have 20 minutes before my next meeting then i will do ___
    • Save a list of short tasks that need to get done but dont require a large amount of uninterrupted time.
    • ex- finishing a code review, writing interview feedback, responding to emails, investigating a small bug, or writing an isolated unit test.

Make a Routine of Prioritization

  • commit to an end of the week 30 minute planning session helps ensure that im spending time on the right activities.
  • review the priorities on sunday afternoon/monday morning
    • review what’s been accomplished
    • examine what was planned and not accomplished. understand why?
    • scope out what you hope to accomplish in the next week
  • daily prioritization sessions = small tweaks to what your currently working on
  • weekly sessions = opportunities to make larger course corrections

I work in big tech (which is notorious for poor WLB) and I manage to work 40-45 hours a week, as does most of my team.

Your manager is a big factor in your WLB. If they keep setting unrealistic deadlines, try to start there with upwards feedback.

Other than your direct manager, the key seems to be prioritization. For many roles there are 2-3 things you need to deliver in a week to drive impact and everything else that fills up your day (status meetings, emails, chat, 1:1s, small tasks) are nice to haves. I find I need to be intentional with my time to avoid working late.

Some pro tips:

  1. ⁠Schedule uninterrupted focus time (~4 hours a day) to make progress on deep work
  2. ⁠Try to group meetings together to avoid a swiss cheese calendar where it's hard to make progress on anything
  3. ⁠Start your week by identifying the 2-3 most important things to accomplish that week. If you're struggling to do that, ask your manager for help.
  4. ⁠Leave your laptop at work and set an alarm to go home. This worked well for a few people on my team that suffered from "one more thing" thinking. You're not doing your best works those last few hours of the day. You're better off starting fresh the next day.
  5. ⁠Say no to work that's not your top priority. Those extra projects and small tasks add up fast. You will be much more successful doing a few things really well than a dozen things just OK.

Key Takeaways 🔑

  • (pp 119)
  1. Write down and review todos. Spend mental energy on prioritizing and processing tasks instead of trying to remember them.
  2. Work on what directly leads to value. Regularly ask yourself if there’s something higher leverage that you could be doing.
  3. Work on the important and non-urgent. Prioritize long term investments that increase your effectiveness, even if they dont have a deadline.
  4. Reduce context switches. Protect large blocks of time in your schedule, and limit the number of ongoing projects.
  5. Make if-then plans to combat procrastination.
  6. Make prioritization a habit

Part 2: Execute, Execute, Execute

Invest in Iteration Speed

Move Fast to Learn Fast

Invest in Time Saving Tools

  • iterative identify your biggest bottlenecks and figure out what types of tools would let you iterate faster
  • When a tool halves the time it takes to complete a 20 minute activity that we perform 3 times a day, we save much more than 30 minutes per day
    • we tend to use it more often
    • faster tools can enable new development workflows that previously weren’t possible
  • ex- Reducing build time by 1 minute, when multiplied over a team of 1000 engineers who build code a dozen times a day translates to nearly one person year in engineering time saved every week.
    • therefor, its not efficient to just find or build time saving tools, you also need to maximize its adoption across your team.
    • the best way to accomplish this is by proving that the tool actually saves time.
  • another benefit of proving that your tool saves time is that is also earns you leeway with your manager and peers to explore more ideas in the future.
  • time-saving tools provide measurable benefits
    • thus you can use data to show that your investment garnered a ++ return.
  • start small. find an area where a tool could save time, build it and demonstrate its value.

Shorten Your Debugging and Validation Loops

  • Effective Engineers have an obsessive ability to create tight feedback loops for what they’re testing.

Master your programming environment

Examples:

  • tracking changes in version control
  • compiling or building code
  • running a unit test or program
  • looking up documentation for a certain function
  • jumping to a function definition
  • navigating to a specific place within a file

**Here are some ways you can do the above **1

  • Get proficient with your favourite text editor or IDE
  • Learn at least one productive high level programming language (ex python or ruby)
  • Get familiar with Unix shell commands
    • grep
    • sort
    • uniq
    • wc
    • awk
    • sed
    • xargs
    • find
  • Prefer the keyboard over the mouse
  • Automate your manual workflows. Once you’ve done something twice, think about automating it to third time.
  • Test ideas on an interactive intrepreter
  • Make it fast and easy to run just the unit tests associated with your current changes.

Don’t Ignore your non-Engineering Bottlenecks

  • dont wait until you’ve invested massive amounts of engineering time to seek final project approval.
  • Prioritize building prototypes.
  • Explicitly ask decision makers what they care about most.
  • Find out where the biggest bottlenecks in your iteration cycle are, then work to optimize them
    • ex, engineering tools, cross-team dependencies, approvals from decision makers, organizational process.

Key Takeaways 🔑

  1. The faster you can iterate, the more you can learn.
  2. Invest in tooling. Faster compile times, faster deployment cycles, and faster turnaround times all provide time saving benefits the more you use them.
  3. Optimize your debugging workflow.
  4. Master the fundamentals of your craft.
  5. Take a holistic view of your iteration loop.

5. Measure What you Want to Improve

Use Metrics to Drive Progress

Quote

If you cant measure it you can’t improve it —Peter Drucker, The Effective Executive

Good metrics accomplish a number of goals

  • helps you focus on the right things
  • when visualized over time, good metrics help guard against future regressions
  • good metrics can drive forward progress
  • a good metrics lets you measure your effectiveness over time.

Given the benefits of good metrics, its worth asking yourself

  1. Is there some way to measure the progress of what im doing? 2. If a task im working on doesn’t move a core metric, is it worth doing?

Pick the Right Metric to Incentivize the Behaviour You Want

  • the choice of which metric to measure dramatically impacts and influences the type of work that we do.
  • When deciding which metrics to use, choose one that
    1. maximize impact
    2. are actionable
    3. are responsive yet robust
  • A core metric: one systematically improved over time, leads you/r team to make the greatest & most sustainable impact.
  • an actionable metric is one who’s movements can be causally explained by the teams efforts.
  • a responsive metric updates quickly enough to give feedback about whether a given change was ++ or —. It is a leading indicator of how the team is currently doing.
  • A metric needs to be robust enough so that external factors outside of the teams control dont create noise.

Instrument Everything Early On

  • Ensure we have a set of dashboards that surface key health metrics
  • We need to build flexible tools that allow us to quickly track additional data.

Internalize Useful Numbers

undefined

https://kousiknath.medium.com/must-know-numbers-for-every-computer-engineer-6338a12c292c

Be Skeptical about Data Integrity

Some Strategies that you can use to increase confidence in your data integrity

  1. log data liberally, in case it turns out to be useful later
    1. build tools to iterate on data accuracy sooner
  2. write end to end integration tests to validate your entire analytics pipeline
  3. examine collected data sooner
  4. cross validate data accuracy by computing the same metric in multiple ways.
  5. when a number does look off, dig into it early.
  6. make sure your data is reliable.

Key Takeaways 🔑

  1. Measure your progress.
  2. Carefully choose your top level metric. Different metrics incentivize different behaviours. Figure out which behaviours you want.
  3. Instrument your system.
  4. Know your numbers. Memorize or have easy access to numbers that can benchmark your progress.
  5. Prioritize data integrity.

6. Validate your Ideas Early and Often

  • Validating your ideas early and often helps us get the right things done.

Find Low Effort Ways to Validate your Work

  • Iterative approaches lead to fewer costly errors and give us opportunities b/w each iteration to collect data and correct course.
  • The shorter each iteration cycle, the more quickly we can learn from our mistakes.
  • “What’s the scariest part of this project? That’s the part with the most unknowns and the most risk. Do that part first.”
  • Ask Yourself: Can I expend a small fraction of the total effort to collect some data and validate that what we’re doing will work?
    • we often hesitate to spend even 10% extra overhead b/c we’re in a hurry to get things done or were overly confident in our implementation plans.

Continuously Validate Product Changes with A/B Testing

Beware the one Person Team.

Set up necessary feedback channels to increase the chances of our projects succeeding

  1. Be open and receptive to feedback.
  2. Commit code early and often.
  3. Request CR from thorough critics.
  4. Ask to bounce ideas of your teammates.
  5. Design the interface or API of a new system first.
  6. Send out a design document before devoting your energy to coding.
  7. If possible, structure ongoing projects so that there is some chaired context with your teammates.
  8. Solicit buy-in for controversial features before investing too much time.

Build Feedback loops for your decisions.

  • “Any decision you make should have a feedback loop for it. Otherwise your just guessing.”

Key Takeaways 🔑

  1. Approach a problem iteratively to reduce wasted effort.
  2. Reduce the risk of large implementations by using small validations.
  3. Use a/b testing to continuously validate your product hypothesis.
  4. When working on a solo project, find ways of soliciting regular feedback.
  5. Adopt a willingness to validate your decisions.

7. Improve Your Project Estimation Skills

Use Accurate Estimates to Drive Project Planning

  • “A good estimate is an estimate that provides a clear enough view of the project reality to allow the project leadership to make good decisions about how to control the project to hit targets.”
  • Use the estimate to inform project planning, rather than the other way around.

Concrete strategies to produce accurate estimates:

  1. Decompose the project into granular tasks. If a task will take more than two days, decompose it further; a long estimate is a hiding place for nasty surprises.
  2. Estimate based on how long tasks will take, not how long you/they want them to take.
  3. Think of estimates as probability distributions, not as best case scenarios. Instead of telling stakeholders a feature will take 6 weeks to deliver, we might say “there’s a 50% likelihood we can deliver this feature in 4 weeks and 90% chance we can deliver it within 8 weeks”.
  4. Let the person doing the actual task make the estimate. Different people take different amount of times to do the same tasks.
  5. Beware of anchoring bias. Avoid committing to a number before actually outlining the tasks involved.
  6. Use multiple approaches to estimate the same task. ex- decompose the the project into granular tasks, gather historical data on how long it took for a similar project, and count the number of subsystems you have to build and the estimate required for each.
  7. Beware the mythical man month.
  8. Validate estimates against historical data.
  9. Use timeboxing to constrain tasks that can grow in scope.
  10. Allow others to challenge estimates.

Budget for the unknown

  • we can better deal with unknowns by acknowledging that the longer a project is, the more likely that an unexpected problem will arise.
  • deal with this by separating estimated work time from calendar time. (A month of estimated work takes longer than a calendar month to complete.)

Define Specific Project Goals and Measurable Milestones

  • The exercise of setting a project goal produces two concrete benefits
    1. A well defined goal provides a filter for separating the must-haves from the nice-to-haves. (Defends against feature creep.)
    2. Builds clarity and alignment across key stakeholders.
  • Each milestone should be measurable — either it meets the criteria and behaves as promised or it didn’t.
    • Allows you to scrutinize every single task and ask “Is this task a prerequisite for this milestone?”

Reduce Risk Early

  • Effective project execution means minimizing the risk that a deadline might slip.
  • Tackling the riskiest areas first helps us identify any estimation errors associated with them.
  • A risk common to all large projects comes during system integration, which almost always takes longer then planned (!!!!)
    • Unexpected interactions b/w subsystems
    • different expectations of how components behave under edge cases (hyrum’s law)
    • previously unconsidered design problems
  • How can we reduce integration risk?
    • Build end-to-end scaffolding and do system testing earlier.
    • Stub out incomplete functions and modules and assemble an end-to-end system as soon as possible.
  • Front loading integration work provides a number of benefits
    1. Forces you to think about the connection b/w different pieces and how they interact.
    2. If something breaks the end to end system during development, you can indentify and fix it along the way.

Approach Rewrite Projects with Extreme Caution

They are troublesome for a number of reasons

  1. They share the same project planning and estimation difficulties as other software projects.
  2. We typically underestimate rewrite projects more drastically.
  3. It is easy and tempting to bundle additional improvements into a rewrite.
  4. Feature duplication during ongoing rewrite. (ex odas/sa)

Don’t Sprint in the Middle of a Marathon

(skipped this section bc meh. Can revisit)

Key Takeaways 🔑

  1. Incorporate estimates into the project plan.
  2. Allow buffer room for the unknowns in the schedule.
  3. Define measurable milestones.
  4. Do the riskiest tasks first. Reduce variance in your estimates by exploring the unknowns early on.
  5. Know the limits of overtime.

8. Balance Quality with Pragmatism

  • Pragmatism — thinking in terms of what does and doesn’t work for achieving our goals. A more effective lens through which to reason about quality.
  • It possible to be overly dogmatic about code reviews, standardization and test coverage.— to the point where the processes provide diminishing returns on quality and actually reduce your effectiveness.
  • Where is time better spent?

The right abstraction increases engineering productivity

  • it reduces complexity of the original problem into easier-to-understand primitives.
  • It reduces future application maintained and makes it easier to apply future improvements.
  • It solves the hard problems once and enables the solutions to be used multiple times.

Good Abstractions Should be

  1. easy to learn
  2. easy to use (even without documentation)
  3. hard to misuse
  4. sufficiently powerful to satisfy requirements
  5. easy to extend
  6. appropriate to the audience
  • Simple abstractions avoid interweaving multiple concepts, so that you can reason about them independently rather than being forced to consider them together.

Key Takeaways 🔑

  1. Establish a culture of reviewing code.
  2. Invest in good software abstractions to simplify difficult problems.
  3. Scale code quality with automated testing.
  4. Manage your technical debt.

9. Minimize Operational Burden

  • Avoid re-inventing the wheel and writing unnecessary custom software that you will have to maintain.

Embrace Operational Simplicity

  • Effective engineers focus on simplicity.
  • Simple solutions impose a lower operational burden because they’re easier to understand, maintain and modify.
  • One of the core engineering tenets in the early days of instagram: Do the simple thing first.

Having too complex of an architecture imposes a maintenance cost in a few ways:

  1. Engineering expertise gets splintered across multiple systems.
  2. Increased complexity introduces more potential single points of failure.
  3. New engineers face a steeper learning curve when learning and understanding the new systems.
  4. Effort towards improving abstractions, libraries and tools gets diluted across the different systems.

Do the simple thing first. Always ask— What’s the simplest solution that can get the job done while also reducing our future operational burden?” Revisit sources of complexity and find opportunities to them away.

Build Systems to Fail Fast

  • Techniques can cause software to fail slowly. Software will continue to run after and error, but this is often in exchange for less decipherable bugs further down the road.
    • workarounds to handle software errors
  • A valuable technique to shorten the feedback loop (debugging) is to make your software fail fast.
Fail Fast — Jim Shore

In a system that fails fast, when a problem occurs it fails immediately and visibly … It actually makes it more robust. Bugs are easier to find and fix, so fewer go into production. By failing fast we can more quickly and effectively surface and address issues.

Relentlessly Automate Mechanical Tasks

  • Ask yourself: Will I save more time overall by manually doing a particular task or by paying the upfront cost of automating the process?
  • Two types of automation: automating mechanics and automating decision making. (the latter is more complicated)

Make Batch Process Idempotent

  • An idempotent process produces the same results regardless of whether its run once or multiple times. Therefore it can be retried as often as needed without unintended side effects.
  • When idempotence isn’t possible, strive for retryable or reentrant.
  • A retryable/reentrant process is able to complete successfully after a previously interrupted call.
  • Idempotence and reentrancy can reduce some if the complexity and recurring costs involved in. maintaining automated and batch processes.

Hone Your Ability to Respond and Recover Quickly

  • At some point, it becomes higher leverage to focus our time and energy on our ability to recover quickly than on preventing failures in the first place.

Key Takeaways 🔑

  1. Do the simple thing first.
  2. Fail fast to pinpoint the source of errors.
  3. Automate mechanics over decision making.
  4. Aim for idempotence and reentrancy.
  5. Plan and practice failure modes.

10. Invest in the Growth of Your Team

Key Takeaways 🔑

  1. Help the people around you be successful.
  2. Make hiring a priority.
  3. Invest in on-boarding and mentoring.
  4. Build shared ownership of code.
  5. Debrief and document collective wisdom.
  6. Create a great engineering culture.