The effective engineer 👍25 April, 2021
The Effective Engineer is a frickin good book. Everyone who works with digital products should read it.
Here's a few notes that summarizes what I wanted to keep remembering from it, intertwined with a few thoughts of my own.
Part 1: Adopting ther right mindsets
Have leverage in the back of your mind
Leverage = value produced / time invested. In the back of your mind, ask: Is this a valuable activity? Will that thing take too long? Low pri and quick – let's just do it.
Adopt a growth mindset
Learn what you need – there's nothing you can't do. Never think that you know everything – even about a single topic.
Invest in improving your skills
Learn new hotkeys, even though it may cost you slightly in the short term. What else do you need to learn or do to increase your throughput?
Learn on the job
Make sure you learn on the job – don't just do a job.
Questions to consider for evaluating a job:
- What goals does the company have for the next 12 months? Are this something only CXOs know? Do they revolve around expansion, profitability or culture?
- How do employees learn? Is there onboarding? Mentorship? Is there weekly demos? Talks and conferences?
- Are there any reviews or retrospects or postmortems after failurs and projects? (Or is it just "Next!")
- How talented do the team seem? If you want to grow, surrounds yourself with people who are more skilled than you in the areas where you want to grow.
- How much do employees decide their own work tasks? Little influence on own tasks can mean low trust in the team, killing motivation, joy and growth.
- Is there team work, or do employees work mostly alone? It's easier to learn from talented coworkers, than solely from Google.
Learn, learn, learn. You're responsible for your own learning. Read books, do online courses, request reviews from the harshest critics, say yes to tasks because you don't know how to solve them. Try new things – never stop learning and don't blame your surroundings. You don't need anyones approval to learn new things.
- Limit work in progress. Lean will say a lot of clever things about reducing incomplete work, but most important to me is that it gives clarity – The less things in my head, the clearer everything gets.
- Plan with implementation intentions. Don't just say you'll do X. Say you'll do X once Y is shipped. Or on Thursday. It magically improves completion rate.
- Focus on important, non-urgent things. A majority of the time we overemphesize urgent things, leading to systemically underprioritizing important, non-urgent things. Ironically, this is often the root cause of the urgent things we do. So focus more on those non-urgent things.
- Have a system for your todos. Any system that works for you, works for you – Getting things done is a place to draw inspiration.
Part 2: Execute!
Invest in iteration speed
- Automate recurring manual work. ESLint, Prettier, Contiuous integration, automated testing and deployment, monitoring alerts. If you have to do something manually more than twice, then write a tool for the third time (Raffi Kriorian, former VP of Platform Engineering at Twitter).
- Shorten debugging cycles: More generally, shorten feedback loops. How fast you learn depend on how fast someone/something tells you how you're right or wrong.
- Measure what you care about: From performance to convertion, high level or detailed – what do you want to keep in focus? Measure it, and make sure it's a good metric – (See also Logz.io + Kibana dashboards)
Find good metrics
Think hard about the metrics you choose! I think business is in a plague of often shallow bad-metric driven growth, maybe driven by ad-platforms and A/B-testing "tips and tricks", that usually oversimplify things (Ad-networks are sophisticated, but since you pay Facebook based on simplified metrics such as per. click, it's also the correct metrics for them).
Click-through rate: Sounds reasonable to care about right? How many click the article headline? Or how is the convertion of impressiions to visitors for an ad? It's super important! But it only tells a part of the story.
A Long click, i.e. whether a user clicks and stays can tell more about how valuable the article or page was for the user, and whether or not we should keep it.
Weekly active users: Nice, gotta have that one? You might have rolled out a nice feature, or lowered the price – thinking that's the reason. But what's really happening can be something completely different: Users hate it and are dropping off in droves, while a positive news article or mention is piling on new customers – All you see is an increase of weekly active users.
Weekly active by cohort splits up active users in buckets based on time since signup. It would tell you correctly that piles of new users are coming in, while week 3+ users are fleeing – which indicates that you should consider undoing that price or feature change.
And and and...
And there's so much more I'd like to say on this topic! How is your support affected by using the time it takes to serve 1 customer as a metric? When you pay your sales force per sale or celebrate the top seller of the month, how does that affect the company trustworthiness or team spirit? What about your ability to deliver customers what you promise? When the CEO is judged by this quarters financials, how long will it take before your entire business is turned upside down by competitors? Is your company value even measured by its stock price?
But all that's for different post...
Measure / Instrumentize
Lau lists a neat little list of useful measurements to know (here adapted slightly):
- Number of active users + divided in weekly/monthly cohorts
- Number of requests per seoncd
- Page load times
- Distribution of traffic across different parts of a product
- Distribution of traffic accross device types
- (Distribution of traffic accross countries/cities/areas)
Validate your work
- Set a direction, but don't run blindly for it. Take one step at a time, and keep validating that your direction and target is still correct.
- MVP, The Eric Ries definition: "That version of a new product which allows a team to collect the maximum amount of validated learning about customers with the least effort". Consider spending 10% effort initially to validate that the other 90% are correct.
- Validate product changes with A/B testing. Yes, it'll take some time setting up. Yes, it'll be worth it.
- Don't be a 1 person team: Get feedback from others. Commit and push in smaller chunks. Design or plan, and get review before implementing.
Improve your estimation skills
- Estimation is usually optimistic: "Treat an estimate as the most optimistic prediction that has a non-zero probability of becoming true"
- Think of estimations as probability distributions: There's a 50% chance we'll be done in 4 weeks, and a 90% chance we'll be done in 8 weeks.
- Use planning poker cards when estimating in groups: The first one to take a stab at it, is often the most knowledgable. Use cards to avoid anchoring each other.
- Budget for the unknown: Issues, bugs and unanticipated work will arise – add extra for uncertainty.
- The one to implement, should estimate: Don't estimate on behalf of others.
- The mythical man month: 3 months of work is not the same as 1 month for three people.
- Log estimation and actual time spent: It'll give you a good multiplier for initial gut feelings. And use it to drive estimation based on previous projects.
Estimation is so hard. In the last few weeks, I've almost daily been asked to estimate different month-long projects. Twice I've humorously said "Well, estimating tech projects is a black hole." – it didn't make anyone smile.
The response that I am most happy with was something ala:
Last year we did a project X, which is similar. It took 3 months to set up, and we spent 200k over the initial 6 months. Similary, I think we can launch in 3 months here. This projects can not reuse any of those parts, plus some parts are a bit more complex because of Y and Z. I therefore think 300k is a better estimate for the first 6 months.
Define goals and milestones
- Goals are often motivating, and can bring a team together
- Splitting up a projects in parts lets us ship value faster and avoid the potential for it to become a "monster".
- Having milestones makes it easier to keep your eye on the ball, instead of thinking "while we're here, shouldn't we also..."
Personal mini rant
I am very guilty of "while we're here, let's also...". And I believe I am justified in doing so, because I often feel that tech debt (which is usually the "while we're here" part) is underprioritized. A manager, or whoever pushes from the outside, almost never see, care or put Fix <tech debt> on a todo list.
I usually progress on my tasks at 60% speed, and spend the remaining 40% doing house chores. I do this because those who set my agenda, never consider house chores a task.
Why has this happened? This can't be ideal, can it?
- One reason could be that I love house chores, and want to do it more than what's reasonable.
- Another explaination can be that I don't have managers that care about tech debt – Or that they don't bother, since I'm going to take that responsibility anyway.
- A third can be that it is my tactic of avoiding the energy it takes to explain why we must clean, and the potential frustration of getting a no.
- Maybe I'm just not really working in a team team. We work quite (too?) independently, and it's easier for everyone on the "outside" not to be bothered with details.
I think that the last reason might be it, and maybe it actually is ideal (for my current situation)? ... The nice thing about it, is that I can double my perceived productivity by ignoring tech debt and maybe adding a bit of overtime when it's really necessary.
- Set up end-to-end scaffold early: Avoid postponing the risky tasks, by getting the app running early with all the large building blocks.
- Don't do large rewrite projects: Think thrice before deciding to rewrite "everything". If you do, split it up into several, shippable smaller rewrites.
It's a marthon – running should not be normal
- Additional work hours must be the exception: Not the rule. A motivated employee is a 5x employee. A burnt out employee is a -2x employee.
- Don't sprint towards deadlines: Deadlines are usually arbitrary. It's often better to be late than cutting corners and accumulating tech debt and demotivated people.
- Extra hours don't equal extra work: Extra hours are people debt. This debt has high interest costs.
A 1980 study found that 60 hour work weeks continued for more than two months yield less output than what could have been completed with 40 hour work weeks.
The quote is slightly modified, but that's the essense. I find I immediately want to question it, or get around it 😅. But what if your boss doesn't pressure you to work? or What if my job is my hobby, does hobby time count? 😆 ... Seriously though, what if you program as a hobby? What's work?.
I don't know, but expecting employees to work more than 40 hour work weeks is not great. If I work in weekends, I try not mention it or create any PRs – so I don't contribute to it becoming normal. And I might be better off taking more personal time outside of work, and get away from the computer more in general?
Part 3: Build long term value
Make a sustainable review process
- Use pullrequests I don't even explain this. Do it.
- PR reviews can be your greatest source of learning: Learning to code well through PR reviews from great programmers is my favorite, most effective way of learning. Don't just slap an approve on it – give constructive feedback.
- Review extra thoroughly for new employees: It's not just that new employees have a lower understanding of the systems. They also need to learn your style and standards. Companies have different standards, and culture. It's not that more correct code is always better; high standards also come with a cost. But new employees should be taught our standards so they know what's expected from them.
- Higher code quality = more agile: Trying to make changes in a stinking debt-ridden code area easily takes more than 10x the effort.
- Use tests and linters: Don't make your reviewers responsible for checking that you haven't broken unrelated code, comment on code formatting or consider common pitfalls. Add a ticket reference if applicable and a screenshot if there's UI changes. Be nice to your reviewers ❤️, so they can look for the things that matters most.
Use good abstractions
Making good abstractions is a learned skill, like writing an essay, so maybe lean more on feedback for that? Concrete tips are difficult to find, but let's try.
One thing I find often is that we may overuse new abstractions to hide implementation details behind a utility class or different function. So reading code becomes an experience of jumping between a ton of different methods and classes, context switching all the time. Of course, we want to have small functions with few parameters, but if you keep jumping sideways in abstraction level, your code can become a mess. A 100 line, readable function with lots of repetition, does not need to be generalized into a class. I find that DRY principle is often causing more pain that profit here. Two code paths that are very similar should not be generalized unless they share a common concept. Single layer of abstraction principle can be helpful by making you think (as a rule of thumb, though not always) that a function call should be towards a lesser abstraction.
According to Lau, good abstractions are:
- Easy to learn
- Hard to misuse
- Easy to extend
The purpose of tests are not only to ensure that functionality keeps working in the future. Tests also
- Offer a a great tool to refactor confidently and efficiently.
- Offer documention that's always up to date / correct.
- Let you confidently verify causes and fix bugs (by writing a test highlighting the bug before fixing)
- Let you quickly identify when and where an issue occured (especially with bisect)
- Allow you to move quicker, by reducing the amount of manual testing done to confidently ship.
- Lower the amount of bugs a user face, increasing perceived quality and user satisfaction
Repay technical debt
The all to common problem is that development organizations let their debt get out of control and spend most of their future development effort paying crippling interest payments (Martin Fowler)
Minimize operational burdon
During Instagram's early years, Krieger explained, its team consisted of no more than five engineers. That scarcity led to focus. They couldn't afford to engineer any solutions that would break frequently or require constant maintenance. Far and away, the most valuable lession they learned was to minimize operational burden.
Build systems that fail fast
This makes them easier to maintain! Crash on startup when config is wrong. Bubble up errors instead of swallowing them. Assert that assumptions are held. Validate inputs immediately, before passing them elsewhere. Resolve or close Sentry errors – keep your systems healthy.
Relentlessly automate tasks
Engineers typiically automate less than they should, for a few common reasons:
- They don't have the time right now (Gotta meet them deadlines)
- They forget it saves others time as well (i.e. it may not save them time to automate it)
- Missing UNIX skills (A lot can or needs to be done in a shell)
This is very related to spending time learning hotkeys – investment today, but pays of dividends in the future.
Hone your ability to recover quickly
You can move faster, more confidently if you got two things in place:
- A good error and system health overview, with e.g. Sentry alerts or data dashboards.
- Ability to roll back quickly to a previous version.
Invest in team growth
One of the biggest lessons I learned from Ooyala is that investing in a positive, smooth onboarding experience is extremely valuable.
"You're a staff engineer if you make the whole team better. You're a principal engineer if you make the whole company better. And you're distinguished if you improve an industry." (Mark Hedlund, former VP of Engineering, Stripe)
Yishan Wong (former CEO of Reddit) firmly believes the secret to your own career success is to "focus primarily on making everyone around you succeed."
I just like the quotes above a lot, because they make you think of those around you and how you can make them better ♥️
Make hiring everyones responsibility
Hiring a good engineer, is maybe done best by a good engineer, rather than a manager or HR person? An engineer knows exactly what the job is, and can tell more relatable stories on motivation to work there etc.
I have so far not been helpful at bringing in new employees to my jobs. It's hard. Like... I don't want to come knocking, is that it? And all those I want to work with, are already settled in nice, high paying jobs. For me to think that they would want to come work here, I'll have to genuinely love my job... And I guess that's also when I become a good recruiter? So maybe the best way to recruit good people, is having your existing employees love their jobs. And them emplore to find candidates.
- Make a process out of interviews!: Make interviews rigorous and fun. Pair program on a hobby project. Send in a PR to an open source project. Refactor a self-contained section of the code. But it should be on the candidates turf – their language. It's uncomfortable to learn new things in an interview
- Have a live coding session. It can be as easy as you want. Just let them use their computer. You want to see how someone uses their tools – navigating their IDE, how they use their terminal, git, googling and running programs.
Formalize an onboarding process
Research Google's EngEDU training program or Facebook's 6-week Bootcamp onboarding. You don't have to invest as much, but training an engineer for a couple of hours a day during their first month gneerates much more organizational impact than spending those same hours working on product.
- Ship production code on the first day
- Have a mentor the first month, working together an hour a day
- Have them learn or do things that align with your team culture: Set up IDE shortcuts, git aliases, automate something.
- Organize social events
Dang, this book is good. Read it, then come back here when you forget it for a refresh.
It resonated with me, and if you're still reading this summary then we should probably work together – cause I guess it did with you too.