• Get That Eng Promo

    Navigating your engineering career can be difficult, and one thing that can be especially frustrating is working toward promotion. Career ladders, managers, mentors, projects, deadlines, peer feedback, annual reviews–the list goes on. How do you know what to focus on next? To make matters worse, you might receive mixed signals: peers tell you that you should be promoted, but your manager says you need more time. While there’s more than one way to work toward promotion, I thought I’d share my perspective as someone who’s helped others move forward in their careers and gone through the process a few times myself.

    Some housekeeping up front:

    Promotion processes vary from company to company, often involving lengthy promotion packets, interviews with people at the next level, committees, executive decision makers, or some combination of these things. Managers may have historically introduced bias by playing favorites at your company, leading to a reliance on complex processes to increase the fairness and consistency of promotions. In fact, promotion processes can vary in complexity even within a company by engineering level or based on the organizational unit you are a part of. At Twitter, the process was more complex for higher engineering promotion levels. On the other end of the spectrum, your boss might simply decide it’s time for you to be promoted. That’s exactly what happened early in my career, and the lack of process and fanfare around the situation meant I didn’t really understand I had been promoted until later. The point is you should be aware of the specific process at your company as it affects how you and your manager plan for your growth and eventual promotion.

    Your promotion is yours to move forward, and part of that is gathering the courage to ask your manager for help. That might be harder to do if you’re receiving mixed signals from them and your peers. Start by telling your manager that earning a promotion is a goal of yours and ask for their help. From there, you can work with them to make a plan, set goals, and find opportunities to meet them.

    To earn a promotion you’ll need to consider how to build evidence, reach maturity at your current level, and gain peer support. Oh, and there’s one more thing to know.

    Building evidence for promotion

    The primary factor in getting promoted is doing work at the next level that leads to results that matter to your company. It’s worth mentioning that what matters is subjective, and in turn working on whatever is most interesting to you will not necessarily drive those results. What matters can also change over time in response to market shifts, changes in executive staff, etc.

    Optimizing for what matters does not mean you should be promotion driven in how you prioritize the work you do. Aside from being the wrong thing to do, people will notice if your priorities are self-serving, making this an especially good way to lose the respect and support of your peers. Instead, think about how to spend your time wisely: prioritize the most important things based on team goals mapped to company priorities. It’s a good idea to ask your manager if you’re not sure what the right prioritization is since it can vary situationally. For example, they might say it’s okay to work on refactoring some code short term or they might ask you to wait until your team completes a project with a tight timeline. Delivering what you say you will deliver, and letting people know when you’ll be late builds your credibility and helps gain your manager’s support.

    At the same time, your work should be challenging enough to help you close skill and experience gaps, eventually showing you are operating consistently at the next level per your company’s career ladder. You shouldn’t think of ladder criteria as a series of checkboxes. Instead, think about which criteria reflect your strengths and lean into those. If you find you don’t have the opportunities for such work, then ask your manager or tech lead for help. And if you can’t get stretch opportunities then consider whether you need to find a role on another team or at a new company to earn a promotion. How do you know when to switch jobs? There’s more to that than I want to cover in this post, but consider switching if you’re not content with the progress you’re making over long periods of time (everyone has good days and bad). Ask yourself whether you’re learning, feel challenged, have a supportive team and manager, and are fairly compensated.

    It’s easy to think you can just work harder to get promoted, but delivering an increased volume of work alone is usually not enough to earn a promotion as it doesn’t show you can operate at the next level. It can help you earn the respect of your peers, potentially leading to the mixed signals I mentioned earlier. Putting in extra effort on work demonstrating next level skills, however, can shorten the time to promotion as you’ll build evidence at a faster rate.

    I recommend keeping a log of your most important work and accomplishments, AKA an impact log, so you and your manager can periodically assess your progress. Recording your progress as you complete work is best because the details of what you did and why it matters are fresh in your mind.

    Reaching maturity in your current level

    Another important factor in getting promoted is reaching maturity at your level. This amounts to solving enough problems to be really good at your job–sort of like earning experience points and skills in an RPG. Tenure is sometimes used as a proxy for maturity, but it’s better to assess skill growth and results since people learn and grow at different rates. To be explicit, people are generally not promoted for competently delivering at their current level for long periods of time. They are promoted for growing the positive effect they have on the results their company wants to achieve while operating at the next level.

    Many tech companies don’t set a minimum time one needs to be at a given level to be promoted, but there is a sort of minimum practical time to gain the experience needed to operate at the next level1. Early in your career, reaching maturity at a given level happens more quickly since the bar to operate at early levels is lower than at more senior levels. At senior levels the bar is higher: there’s an expectation of higher productivity, broader scope, etc. All of this is to say the time it takes to be promoted depends on the level, opportunities you have to deliver, management support, and how you capitalize on all these factors.

    Gaining peer support

    Some promotion processes require peer review. This can come in the form of committees that may not be intimately familiar with your work, statements of support from people you work with, or both. Feedback from higher level peers is weighed more heavily in such cases, the idea being they are better able to assess your work at the next level.

    At Twitter we had promotion committees for staff+ engineering levels, which reviewed lengthy promotion packets and peer feedback then voted for or against promotion with simpler processes at lower levels. An executive made a final decision based on those votes and their own perspective. Committees like this may review many promotion recommendations in a single cycle, making it especially important to be crisp in how you and your manager frame your case for promotion given the time they can realistically allocate to each person. If you have a say in this framing then I recommend focusing on the most relevant work you’ve done, sorted from most to least impactful along with an explanation of how that work contributed to company results and demonstrates you’re operating at the next level.

    Additionally, it’s helpful to ensure your peers understand your work as it means they can better speak to it when providing feedback and a level of support for your promotion. This is another place your impact log can help: map it onto your company’s criteria for the level you’re aiming for and share the resulting document with your peers ahead of promotion. You can gauge their level of support by asking for feedback regularly (e.g. as you finish projects), as opposed to at the end of the year, so you can make adjustments to how you work more often.

    One more thing

    There’s one more thing that affects your ability to be promoted: your manager’s ability to advocate for you. They may need to convince their boss or an executive that you are ready, defend your promotion in front of a committee, or they may need to write a high quality promotion packet. This is part of the process you typically have little influence or visibility into.

    To make a compelling case your manager needs to show you’ve met the company’s criteria using the evidence you worked toward above, have the support of your peers, and they need to have credibility within the organization. Their credibility has a strong effect on their advocacy and it may change over time. Things like delivering on team goals increases your manager’s credibility and repeatedly missing expectations erodes it. Other circumstances like reorgs or new leaders joining also affect their credibility. For instance, if your team moves to report to a new leader then your manager will need to establish a new relationship with their management chain. This can cause either a positive or negative change in credibility.

    Earlier we talked about managers introducing bias to the promotion process, and it turns out executives sometimes do the same. This can be difficult for your manager to overcome, which is why it’s important for you to provide the highest quality evidence you can.

    Wrapping things up

    Whew! That’s a lot to take in, but you’ve made it to the end of this post. We talked about how promotion processes vary by company, organization, and even level, as well how you might go about asking for your manager’s help in career planning. We also talked about what it takes to get promoted: building evidence by delivering work at the next level, reaching maturity in your current level, gaining peer support, and the effect your manager’s credibility has on the process. You have a lot of influence on the first three of these, and less on the fourth. I hope you now have a better understanding of what you need to do to earn a promotion. Good luck!

    Follow me on Mastodon and Twitter, where I make jokes and talk about pizza.

    1. Some companies expect candidates to operate at the next level for some time ahead of promotion to mitigate the Peter principle. Twitter’s rule was six months, and I’ve heard of another large company requiring one year.

  • Evergreen Interviewing Tips For Now And Later

    Many tech companies are conducting layoffs thanks to economic conditions and over hiring. You may not have interviewed in a while and you might even find it intimidating. I’d like to share some suggestions based on my time as a hiring manager, and mistakes I’ve made interviewing.

    Some nuance up front: this is my perspective and yours may vary. This post applies situationally to finding a job as a software engineer or engineering manager. Use your best judgment.

    • Recruiters are friends. People love to dig on them, but they are the people who sell you to hiring managers. Their job is literally to get people hired into open roles. Treat them kindly, ask them about the process, and ask for changes to the process as needed.
    • Use your network: Ask friends to refer you to places they work. If there are no roles open then ask to chat with a recruiter anyway so you can share what you’re looking for and what you’re not looking for.
    • Afterward, ask your recruiter if they can reach out as roles open up. This is especially important now as there are fewer roles open today, but what may not be obvious is that hiring managers tend to get incremental headcount for positions at the beginning of the year.
    • In my experience, the least effective way to find jobs is via direct application to company websites. Companies receive many, many applications per position and it’s kind of a crapshoot as to whether you’ll hear back regardless of the quality of your resume.
    • Keep your resume succinct. Move old work experience to another doc and add a statement saying “prior work experience available upon request.” Don’t bother adding “references available upon request” — everybody knows that, and references are less commonly requested these days.
    • This is key: get lots of sleep the night before your interviews. Anecdotally, I’ve noticed my performance drops meaningfully at work when I don’t sleep well. My answers aren’t as crisp, I’m quicker to become frustrated, and I make more mistakes.
    • Schedule interviews close together so you’re able to compare offers. Don’t be scared to apply time pressure based on an offer you have in hand.
    • Order interviews from least to most interesting so you can practice and warm up at companies you’re less interested in.
    • Prepare for technical interviews: if your interview panel requires programming exercises then buy Cracking the Coding Interview and get a Leetcode subscription. I hate it, but it’s where we’re at. Do the programming exercises — don’t just read them and think “I got this.”
    • If your interview panel has architecture/system design interviews then ask your recruiter if the interview focuses on backend or client system design. If it’s the former and you’re not a backend engineer then read this book 2x to prepare.
    • Regardless of interview type, you should ask clarifying questions to better understand the problem before diving in. You might otherwise solve the wrong problem or take a suboptimal approach. In fact, not asking clarifying questions is a red flag to many interviewers.
    • It can be helpful to pause briefly to gather your thoughts before answering a question. When you need a moment to think, taking a sip of water gives you a visible reason to pause.
    • Behavioral interviews are common these days. You might be asked to tell someone about a time you encountered a given situation. If you have an example then give it, and if you don’t then say so (don’t make stuff up!) and ask if an example about a similar situation would help.
    • Don’t wing these! Come prepared with stories about situations navigated. Don’t write them down, but consider having a bulleted list to help you recall them. Have a list of your strengths and weaknesses in mind too. There are lists of behavioral questions you can use to practice.
    • It’s important to respond succinctly to behavioral questions. Briefly describe the situation, move on to how you handled it, and then share what you would do differently if you faced the situation again. Saying you’d act earlier is generally frowned upon. Don’t ramble.
    • You might be asked why you want to leave your previous company. Being laid off does not count negatively against you. It’s good to be honest. However, trash talking your former employer or colleagues comes off as unprofessional. Don’t do that. I recommend you share an honest and diplomatically phrased reason about why you’re looking, and primarily focus on what you want to learn/grow/do at the new job.
    • At the end of each question ask “have I answered your question?” and at the end of the interview ask “do you have the signal you need? If not, are there additional questions you need to ask to get it?”
    • This isn’t a thread about negotiation, but it’s to your advantage to interview for multiple roles. Some companies may lean on their reputation as an exciting place to work to give you a low offer. Having additional offers helps you in these situations.
    • Leveling varies across companies and interview processes are imprecise. This matters because leveling affects your compensation package. You can check https://www.levels.fyi for a rough idea of leveling and compensation.
    • Some companies may fail to gather the signal they need during interviews and attempt to downlevel you, promising a quick promotion. Don’t accept this. It’s generally untrue that one can be promoted quickly as it takes most people about 2 years to gather the evidence for promotion. Instead, ask if you can do additional interviews to give the team and hiring manager the signal they need to level you properly.
    • If you have substantial time at your current level then I recommend asking to interview at one level up. For instance, if you’re a mid level engineer with 3-4 years at your current level then ask if you can interview at Senior SWE.

    That’s all for now. I wish you the best in finding a new job. Follow @amdev on Twitter.

  • Encouraging Ownership

    The best teams I’ve been on have displayed high levels of ownership. Ownership is a cultural trait that helps teams avoid failure by providing people the agency to pick up important work. We’ll focus on unmanaged work in this post because that’s the sort of work that is often dropped, and talk a bit about how filling gaps can derail one’s primary work. If you’ve seen people pick up work that needed to be done regardless of whether it was their job, that’s ownership. When people contribute to the overall success of a team, that’s ownership. When they manage what otherwise would have been unmanaged, that’s ownership.

    Several years back a hacker named Geohot shared a Tweet containing a malformed string. That string caused a crash in Apple’s underlying string processing code, which was triggered by JSON deserialization in Twitter’s iOS app. People retweeted Geohot’s Tweet causing it to spread virally, crashing Twitter’s iOS client repeatedly on launch. This happened during my third week at Twitter! Someone dropped a note in the iOS team’s HipChat room. I was on the east coast and one of the few people online at the time, and while it wasn’t necessarily my job to fix this problem I decided to take a look anyway. I noted the quick fix was adding a try/catch around the code deserialization logic, but being new I didn’t know if that was an appropriate fix. An hour or so later a tenured teammate jumped on and put up a patch with the same fix I’d suggested. Someone on Twitter’s backend team added mitigation to stop the problem while the client fix could be released. This is a clear example of ownership, but not every example is so clear.

    With that story in mind, let’s chat about how ownership manifests on teams, how it can wane as teams change, and how to encourage it.

    How is ownership manifested?

    Organizational segmentation is often inversely correlated to a sense of ownership, which is why small teams tend to have higher levels of ownership baked into their culture. People pick up important work that’s outside their purview for many reasons, but two that stand out to me are a desire to be helpful, and simply because no one has discouraged them from doing so yet. This works on young or small teams because everyone fails if nobody picks up unmanaged work, it’s easy to recognize and celebrate such work, and leaders like you trust people to work on the right things. New people joining a team pick up ownership because it’s ingrained in the team’s culture.

    Over time ownership can become diluted, leading teams to optimize for local rather than global success. It takes effort for us to counteract this through both trust and recognition.

    How does ownership become diluted?

    Ownership can become diluted in more than one way. Personnel attrition absent knowledge sharing is a straightforward way to lose your team’s sense of ownership, but a less intuitive way to lose that agency is through growth. Teams tend to grow over time, and with growth come changes and new challenges. Your team may be changing right now, and you may have noticed some of these challenges, like keeping everyone on the same page being harder due to the difficulty of scaling communication. As communication becomes more difficult, teams organize into sub-teams to focus on specific things. Sub-teams are smaller, by definition, and so they have fewer communication issues within them. However, communication can remain difficult between sub-teams.

    Sub-teams still have their own charters and goals: things they own and things they’re supposed to get done. Someone on the team – maybe a manager, or some other leader – is accountable for the work being done and they might, even inadvertently, discourage people from taking ownership by optimizing for local success. 

    But how does organizational change map to work being unmanaged? Imagine a bunch of circles, each representing a sub-team and its charter. Sometimes the circles are far apart, sometimes they overlap a little, but there’s space between many of the circles. The space is unmanaged work, and if it’s important enough it still needs to get done.

    Sub-teams tend to form their own cultures based on their members. These can be managers, folks with tenure, or anyone who brings the team together. If we don’t encourage ownership, then the team’s sense of ownership will be diluted as the team changes, eventually leading to the failure of the broader team. Team leaders would ideally encourage ownership company-wide, but the reality is this varies from team to team and leader to leader.

    It’s an easily defensible position that focus is important, and the important unmanaged work is someone else’s job since it’s not within a given team’s charter. Not only is it a defensible position, it’s actually a correct position so long as some people continue to demonstrate ownership as the broader team scales, and that ownership continues to be encouraged. However, when recognition and trust for ownership are scarce there can be a subtle shift from “it’s not our job” to “it’s no one’s job”, one that’s often not noticed until it’s too late. The broader team fails when something important enough goes undone because it is no one’s job.

    Charters and Goals

    Earlier I mentioned charters and goals are important, and there’s certainly a difference between work that can wait, and work that’s worth setting aside goals for. Completing the former at the expense of team goals is gap filling. There’s a big difference between ownership and filling gaps. Ownership is organization sanctioned and recognized, though you may have to do some work to sell the value of prioritizing specific work. After all, not everyone has the context you have on likely points of failure. Gap filling is picking up work that eventually needs to be done, but isn’t necessarily as important as your primary work. Gap filling can result in unfortunate consequences like your primary work not being completed and your team’s goals not being met as a result.

    How can you tell the difference between work that can wait and work that’s worth setting aside goals for? I like to ask questions like what happens if nobody does this work? What’s the impact on the broader team and the business of completing the work? Does it need to be addressed now or can it wait?

    If it’s work that’s important enough to do now at the expense of local success, then I ask the people ultimately accountable for that success if they agree with my assessment. It’s up to me to convey the importance and value of the work relative to our team’s goals. If they agree, I do the work and it’s up to them to get me the time and space I need to complete it. Sometimes work is important enough, but I can’t personally make the time tradeoff or I don’t have the necessary expertise. In those cases I try to find another person willing to take the work on and hold myself accountable for ensuring it’s completed.

    Like any other prioritization decision there will be several inputs to account for and I may not get the buy-in I need to prioritize that work. Not everyone on a large team needs to take on unmanaged work, but having some percentage of people empowered to do so results in resilience when teams change.

    Encouraging Ownership

    We can encourage ownership by recognizing and making space for the important, unmanaged work their people do and ensuring knowledge about that work is shared. This incentivizes people to share the load and minimizes gaps that would otherwise not come to light until someone leaves the team. This is one way to eliminate single points of failure and while giving people space to learn new things. This is how you can build a culture of ownership over time. In the story above, we fixed the crash because we knew it was critical and we trusted our manager would appreciate our fixing the problem, even if it meant some other work slipped short term.

    I have explicit conversations about expectations and ownership with my team. For instance, I share that I expect our goals to be met, but they can come to me if they need to shift time to unowned work for a little while. I ask them to explain the value of that work and we decide together on the next steps. I also talk about how our primary work will eb and flow (e.g. slower during planning periods and when we’re waiting on experiment results), and how there are natural times in our schedule that allow for taking on unowned work. Finally, I set a rough percentage of how much of my team’s time, over a long time horizon, should go toward core work vs. work our team does not own. That percentage will vary from team to team.

    Ownership is a cultural trait that helps teams avoid failure by providing people agency, though not everyone on a team needs to demonstrate ownership for a broader team to meet its goals. Ownership can be diluted or encouraged as teams grow and change. Encouraging ownership requires us to set expectations, balance local and global priorities, provide recognition, and cover for their teams. Prioritizing unmanaged work requires assessing the impact of the work itself, and making space for people to bring that sort of work to their you.

    You should follow me on Twitter if you enjoy (or maybe don’t enjoy) puns.

  • Hey Amro, what’s on your desk?

    A mostly wire free desk aimed from the right side showing various work equipment: a large monitor, a small laptop to the right and one behind in a stand, two key lights hovering over the desk, a microphone, webcam, keyboard, mouse, trackpad, volume knob, and a notebook, pen, and more
    Amro’s desk

    I shared a Tweet with a photo of my current work setup and a few folks asked what I use so I thought I’d put together a blog post with all the hardware on my desk.

    I have conflicting goals in choosing the gear I use to do my work. For instance, I want to minimize visible wiring and also want a nice, tactile keyboard. There are decent wireless mechanical keyboards out there, but the ones I’ve tried don’t suit my needs (I have tried many).

    I do a lot of video conferencing for work so want my A/V setup to be of high quality. To that end, I use a mirrorless camera, decent lighting, and a good microphone. I keep personal stuff off my work laptop, so my personal laptop needs to be available to me for personal communication.

    Anyway, here’s a list of my gear:

    Desk: Fully Jarvis Standing Desk – A pretty nice standing desk. It’s fairly stable, though a little wobbly. I’d avoid the black desk top if I bought again as it shows dust easily. Wire management underneath is kind of a pain as the metal frame does not have through holes. I like it a lot otherwise.

    Desk mat: Grovemade Wool Felt Desk Pad (Medium/Light) – I like this mat quite a lot: it’s not scratchy, and is a decent mouse pad. My one complaint is it slides around a bit too easily, though my heavy keyboard helps keep it in place. It doesn’t have rubber or silicone on the bottom for friction.

    Monitor: Apple XDR Pro Display and stand – overpriced, but sharp image, and aesthetically pleasing. Nice for photo editing, which I do.

    Keyboard: GMMK Pro with Kailh Box White switches and these keycaps. Some assembly required, but really nice to type on. Clicky, but not so much actuation force that your fingers feel dead at the end of the day. I like a ten-keyless keyboard for its compact size, and I also like having a function row. The volume knob is a nice addition. I did need to modify the firmware slightly to get key mappings right for the Mac. That was kind of a pain, and also fun.

    Mouse: Logitech MX Master 3 – This mouse is comfortable to use for long periods of time and the battery life is great. one downside is the buttons tend to get shiny over time (ABS plastic?). The Mac version lacks Logitech’s Unifying adapter, and Bluetooth support is jumpy in my experience, so you should get the non-Mac version. It works fine with a Mac.

    Trackpad: Apple Magic Trackpad 2 in space gray – super nice, and great for switching between desktop spaces. Excellent battery life, but switching between machines is a little annoying. I put mine to the left of my keyboard.

    Cameras: Fuji X-T30 + 23mm f/2 lens and Logi 4K Pro Magnetic Webcam for Pro Display XDR – I had the Fuji camera laying around after getting a new mirrorless camera, and I bought the lens second hand off a friend to save money. Note this Fuji camera has been replaced by a newer model. If I were buying from scratch I’d probably look at a less expensive mirrorless camera. The Logitech webcam is decent, but the video quality is just so-so, and there’s no bokeh. It’s a nice backup in case something goes wrong, and I appreciate that it attaches to my monitor magnetically and looks nice.

    Camera arm: Elgato Master Mount – A stable camera arm with a nice desk clamp. The side of the clamp is low profile, and the clamp mechanism handle features a ratchet feature that makes it easy to secure in tight places.

    Video capture: AVerMedia Live Streamer Cap 4K – An excellent USB video capture device. While Fuji makes software that lets one use their cameras as webcams via USB, it does not yet work with M1-based Macs, the output is limited to 720p, and it only works in some software (e.g. works in Chrome, not in Slack or Safari). Initially I tried an Elgato Cam Link 4K, which mostly worked, but has issues playing nicely with other high-bandwidth USB devices on the same bus. For instance, video output from the Cam Link 4K freezes after a few seconds when using a Thunderbolt hub connected to an M1-based Mac.

    Lighting: Elgato Key Light Air x 2 – Proper lighting is important for optimal viewing, and key lights are a good place to start. A three point setup would be great, so do some research/planning.

    Headphones:Apple AirPods Max – Expensive, but they sound nice and switch between devices quickly and easily. The battery lasts quite a long time — I burn through about 30% in a typical workday. Amazon sometimes has discounts on these headphones, so I’d check there first.

    Headphone hook: Audio-Technica AT-HPH300 – Soft, inexpensive, and won’t ruin your headphones

    Microphone and interface: Shure SM7B, Elgato Wave XLR, Cloud Microphones Cloudlifter CL-1 – The SM7B is an iconic microphone that delivers excellent sound, but it’s expensive. Check out the Shure MV7 to get a similar sound at a much lower price. You have to put up with branding on the side though. I like the Wave XLR because the cables plug into the back, it has a large volume knob, and a capacitative mute button on top. The SM7B is a notoriously quiet microphone, and the Cloudlifter amplifies it by 20+ db without increasing noise substantially. You won’t need a Cloudlifter if you go with the MV7, and if you use it via USB you won’t need an XLR interface either. Another popular interface is the Focusrite Scarlett 2i2. I went with the Elgato over this as cables coming out the back of the unit makes cable management easier.

    Boom arm: Rode PSA1 – A classic boom arm. This may seem basic, but the boom arm stays where you put it. Others I’ve used tend to sag, etc. The desk clamp is just okay for me. If I were buying today I’d get the Rode PSA1+ instead, which fixes some minor annoyances with the PSA1. Following the trend, the PSA1+ does have prominent branding on it, which I find mildly off-putting. I’d still buy it though.

    Dock: OWC Thunderbolt 4 Dock – A true one-cable solution! All my peripherals plugs into this dock. One cable goes from this dock to my laptop and keeps my laptop charged. This is one of the cheaper Thunderbolt 4 docks on the market, but they all seem to follow the same reference design and OWC makes good hardware in my experience.

    Ethernet: Sonnet Technologies Solo 10G – A Thunderbolt 10gbps ethernet adapter. It’s nice, but no longer made. I’d recommend OWC’s current offering instead.

    Charging cable: Anker Powerline II 3-in-1 Cable – I use a U2F security key and occasionally need to charge my mouse and trackpad. This cable has the 3 most common plugs I need to charge my peripherals, and I can keep my U2F key attached to the USB-C plug for easy access.

    Laptops: Work provided 15″ 2018 Macbook Pro, and a 2020 14″ Macbook Pro for personal use – I won’t bother linking to these. The work machine is getting a bit old/slow, even for my use. The newer personal machine is a dream to use for programming, photo editing, and shitposting on Twitter.

    Laptop stand: OMOTON Vertical Laptop Stand – I use this relatively inexpensive, adjustable laptop stand. My Thunderbolt dock sits behind my laptop in the second groove. The logo is only present on one side so turn it around for a cleaner look.

    Did I leave something out? Lemme know on Twitter and I’ll add it to this list.

  • Approaching Code Review

    Code review is great way to maintain and improve your team’s codebase, and like a lot of team process having an intentional, positive culture around it makes it better. One of my earliest patches at Twitter was adding a short-lived token-based system for logged out requests (think login, signup, etc.). The patch itself wasn’t so large — a few hundred lines of Objective-C plus tests and integration, but it was important enough to require a fair bit of scrutiny in code review. This change was risky, and it wasn’t something we could easily test incrementally in production so we needed to get it right.

    Like all our changes, my patch went through code review and it ultimately took many revisions for me to get it right. Code review can feel intimidating, but in this case I felt supported as my reviewer displayed empathy and patience while helping me find mistakes. That review helped set the tone for how I’d work with others in the future so I thought I’d share a bit of what I’ve learned about approaching code review on large teams.

    My job as a reviewer

    My job as a reviewer is to help make my coworker’s contributions better by helping them catch mistakes as well as helping them improve their technical solution. My job is not to gate keep to get my way. One natural consequence of this is it enables authors to express creativity in their work, which leads to more engaged teammates. Of course, it’s really important to teach others when there’s a better way to solve problems and doing so gracefully is part of providing effective code review. That’s a core part of code review, but it’s not what this post is about.

    Sometimes there are established team norms one needs to follow for the sake of consistency in a codebase — e.g. stylistic things. We’re not here to talk about tabs vs. spaces, sorting imports, or whether braces belong on a new line either though (real talk: spaces, yes, and absolutely not 😇). I’ve found it’s helpful to move these sorts of things to automated linters, where possible, as it removes the need to raise them in code review altogether. This maintains consistency, simplifies and speeds up code review, and removes the potential for animosity over minor stylistic change requests.

    Speaking of norms, your team might consider setting one for the upper bound on the size of a typical patch. Exceptions will be made and that’s okay, but keeping patches small means reviewers don’t need to spend as much time on each code review pass. This is not only considerate of teammates’ time — it also helps make space for their other work. Sticking to reasonably sized patches also makes it easier for multiple people to work on the same project as it reduces the times which one person might be blocked waiting on another. I’ve seen larger patches work out fine on other teams — it depends on your team’s needs.

    Framing feedback

    Framing code review feedback in a way that’s clear and non-confrontational helps avoid the misunderstandings that sometimes result from written communication. Written communication can be devoid of the tone that smooths over mistakes in verbal communication. I ask myself how I might receive a message to help refine the wording so it’s more likely to be understood as I intend. Importantly, the wording I choose critiques the work I’m reviewing and not the person.

    Working relationships can also affect how you communicate in code review. Getting to know your teammates helps you understand their communication style, which helps you give each other the benefit of a doubt when reading, for instance, a terse reply. However, you won’t always have the luxury of knowing how others work and communicate. Whether you’re working with a new teammate or your team is so large that it’s impractical to know everyone, it’s important to consider how framing your feedback might affect how it’s received.

    Another way to approach communication, in code review and beyond, is leading with sincere curiosity. Curiosity helps disarm negative emotion when another person receives your commentary. For instance, something like “did you know we have a utility function for this?” along with a function name is better than sharing only the function name or a link with no additional context because it doesn’t unintentionally imply the author has done something wrong, is lacking expertise, etc.

    Context matters

    When reviewing code I try to keep in mind the author may have context I don’t and vice versa. They may have spent more time on the patch than the number of lines changed indicates, and they might have constraints I’m not aware of like deadlines or other urgent work to get to. I ask questions to gather the context I need to provide helpful code review up front. Do I clearly understand what the patch is supposed to do? Should it have automated tests? Does it have manual testing instructions so I can verify it works? A proper commit message? Documentation where applicable?

    I then leave comments where I think something can be improved. I like to prepend “optional: ” or “nit:” where I have minor suggestions that shouldn’t block merging the patch so the author knows they are non-blocking. The author makes the call on whether to address those comments. The patch is their contribution, after all.

    If a patch requires substantial rework — maybe I feel I’m leaving too many comments, or sense we’re talking past each other in code review, then I take the discussion to a richer communication medium. For instance, if we’re having a discussion on a code review tool, then I’ll send a private message on Slack to ask if we can chat there. If we’re talking on Slack then I’ll ask if we can have an audio or video call. There’s a bit more to this though: Slack is richer than a typical code review tool because it moves the conversation from a public space to a private one, and it enables live communication. The former can help dial down emotions, but it doesn’t necessarily help with tone as that requires intentional word choice, especially in written communication. It’s worth keeping in mind the culture one grew up with may also affect how they interpret your words.

    Earlier I mentioned tone helps bridge understanding. Moving to a richer communication medium is one way to add tone to the discussion. I’d be remiss if I didn’t mention it’s important to note any potential accessibility considerations and working hours for colleagues when switching communication mediums.

    Avoiding wording that make assumptions about the other person’s knowledge is part of understanding teammates may have different context. I try to avoid words like “obviously” or “just” because what’s obvious or simple to me may not be so obvious or simple for someone else. Perhaps they’re new to some part of the codebase, the team, or are earlier in their career.

    Wrapping up

    I’ve certainly done all these things wrong in the past, and I’ve been on the receiving end of code reviews from colleagues who have done the same. It wasn’t always clear to me when I made a mistake as a reviewer until later, but it was usually clear to me when I felt let down by the way someone delivered feedback on my work. Being cognizant of your job as a reviewer, framing, and context you have (and don’t) can help you avoid unnecessary strife with your teammates.

    There are also things you can do as an author to make code review easier on yourself and your colleagues, as well as ways you can defend your time and approach where needed. We’ll talk about those things in a future post.

    Follow me on Twitter at @amdev if you like puns or pizza.

  • Facilitating Instead of Dictating

    Early in my career I thought showing my worth on a team meant having my ideas win. I was far too attached to those ideas, which left me frustrated when they weren’t chosen and worst of all made working with others more difficult. Over time I learned the right approach wasn’t to dictate solutions, but to facilitate problem solving. This approach has benefited everyone involved, led to better solutions, and to better relationships.

    Being a Dictator

    Dictating solutions, be it as an engineering lead or a product manager or from entirely outside a team, creates a single point of failure and stifles the creativity of one’s team. The dictator becomes a bottleneck for the team, which slows down decision making, robs others of a chance to grow and contribute, and ironically stunts the dictator’s own growth as they spend time answering questions for others rather than looking ahead. Dictating solutions also alienates others and harms working relationships when mixed with poor communication or aggression.

    Often this sort of behavior isn’t malicious, the dictator may even believe they’re helping. People inadvertently cause harm in an attempt to be the go-to person, doing their best to remove a bit of the burden from others. That’s what I thought I was doing many years ago, and it wasn’t until I saw others facilitate that I realized the benefits of intentionally making space for others to contribute.

    Being a Facilitator

    Leading as a facilitator means coming to one’s team with a problem instead of dictating a solution, then working with them to find the right approach regardless of whose idea it is. This shows the team their input is valued, which helps them become invested in the work and it makes space for others to learn, teach, and show their creativity.

    Sometimes there’s a lack of ideas because the problem space is poorly defined or too big. In the former case I like to ask questions to help better frame the problem, and in the latter I like to break the problem down into smaller problems to be solved. If there are many problems I like to explicitly delegate finding a solution to each problem to a single person. They don’t have to figure it out on their own, but they’re responsible for coming back to the group with a solution.

    Being a facilitator also means admitting one’s mistakes and making peace with letting go of good ideas in the interest of moving the team forward. In the past I’ve made the mistake of coming to my team with a solution, and even when it was a good solution that action left them wondering what their role was aside from execution. This behavior is sometimes displayed by engineers who transition into management roles—that was certainly the case for me. Solving engineering problems was something I was comfortable doing and it was (and sometimes still is) easy to fall into wanting to overstep in the interest of being helpful. That’s a great way to waste talented minds and prevent people from learning. This isn’t limited to new engineering managers though—I’ve observed this behavior at various levels of leadership.

    These days I’m better at making space for others to thrive, and it comes from one simple question: am I coming to my team with a solution or a problem? I’m still a problem-solver at heart, so when I do have a suggestion I make sure to frame it as an option, one option, something to consider and not a prescription. Of course, sometimes I do need to step in, and it’s a fine line, but I try to do so by asking questions to ensure we consider key problems we need to solve. That’s because, as always, it’s about the problems, not the solutions.

  • Delivering Difficult News

    Earlier this year I was asked if some engineers from our team could help build a newly prioritized project. Doing so meant putting our team’s current work at substantial risk of failure. I knew canceling our project was the right thing to do because the incoming request was more important and because continuing our current work meant spreading our team too thin. Our team had put in a lot of time so I wanted to share the news empathetically, but delivering and receiving difficult news is never easy.

    I started by talking to my product manager. They quickly understood and helped me plan how we would deliver the news to our team. We drafted a list of points to communicate. Having a list was important because we didn’t want to leave out part of the message when speaking in different places or with different people. We detailed what was changing, why, what would happen next, and honestly that we made the decision. It was important to include we made the decision to avoid an “us vs. them” situation with the people who asked for our help. We shared the plan with our managers, then moved on to telling the team. We wanted to tell them as soon as possible out of respect and so they wouldn’t hear an incomplete message through some other channel.

    Having drafted the message we scheduled a 15 minute chat with each person on the team. These meetings took a full day and this process was slower than telling the team all at once, but it gave them a place to ask questions openly without the pressure that might come with speaking up in a bigger meeting. We took two or three minutes to share the message, and spent the rest of the time answering their questions earnestly. We gladly spent more time with people who had additional concerns as we wanted them to know we cared about them and their work. One person requested a retrospective, which we committed to having later in the week.

    Later that day we had a broader team meeting where we repeated the news the same way and answered questions from the group. This let the team settle into the decision together. By now the news wasn’t new to anyone, which meant the collective response was not one of shock. The people that initially requested our help attended the meeting so they could answer questions and explain why the new project was important for our users and product. And of course we held a retrospective later in the week, as promised.

    After the team meeting we sent a brief email with the same message to our team and adjacent people working with us. The idea was to ensure people who couldn’t attend earlier meetings received the message.

    While our team was disappointed that we cancelled the project, they understood the circumstances and took the news well. More than one person told us they appreciated how we communicated the cancellation. We helped with the other project, and worked to deliver a new, well received, project from our team some time later.

    It’s worth planning how you communicate difficult news. Our approach was to be honest, clear, and consistent. We were quick to communicate, accountable for the decision, gave everyone a chance to ask questions in a low pressure environment, repeated the message consistently in more than one place, and gave people multiple chances to share their concerns. We then worked to address them where we were able to do so.

    Follow @amdev on Twitter for occasional management and engineering thoughts, but mostly puns and pizza.

  • It’s About Managing Expectations

    Some time back my team was asked to take up a critical project on short notice. My product manager and I found out about the project on Monday evening and we were told it needed to ship on Friday the same week to 3 client platforms with a small team. We had just four days to make this happen and the date couldn’t move so we had to work with the other two project levers: changing the amount of work we would deliver, and putting more people on the project. The latter famously only helps so much. I want to share how we got many people on the same page and kept them there by managing their expectations.

    What are expectations?
    Expectations are things people believe will happen in the future. Unmet expectations can lead to unfortunate outcomes like duplicate effort, missed opportunities, or worse. Managing expectations is the act of making promises you intend to keep, making sure other people are on board with the plan throughout the process, and bringing them along when things change. Managing expectations helps us avoid unfortunate outcomes, sets a baseline for accountability, and builds trust that can lead to new opportunities.

    The first step my PM and I took was to get each other on the same page. That night we discussed our approach and how we’d divide the work. We also decided we would not block on each other when making decisions. This helped us move more quickly and cover for each other when issues came up. We wrote a plan early Tuesday morning detailing our recommended approach and the timeline on which we would deliver the project. We planned just one and a half days for engineering and half a day for QA. That meant we’d ship Friday on one platform and branch for release on the two others that required a longer release process. We chose this approach so we could understand the effect of our change in one market before going global with it. This gave us confidence and helped us get buy-in from a bunch of folks. We deliberately chose the smallest amount of work we could do that would meet our goals. We also let our team know something disruptive was coming and that we’d share more as soon as we could.

    Our plan included other solutions we considered and why we had ruled them out. We did this to avoid spending time going back and forth negotiating what we’d build. In this case our primary stakeholders were a few decision makers farther up and peers from other teams, some of which our change might affect. We made sure we had the go-ahead from the former, but later found out two peers had concerns about the plan. Given the tight timeline we’d gone for the simplest option, which was to turn off their unshipped features temporarily when our temporary change was enabled. We talked with our peers and shared our constraints with them, then agreed to keep their features enabled on a best-effort basis. Their features were complimentary so this was the right thing to do in the end.

    My take-away from this was it’s important to check my assumptions about the expectations others have of me and my team because approval from decision makers isn’t the same as a mandate. I now ask myself what expectations I have of others, and what expectations they have of me and I try to answer those questions before moving forward.

    Sometimes these expectations are clear, but what if they haven’t been said aloud and agreed upon? In my experience this ambiguity leads to misaligned expectations and in turn the sort of unfortunate outcomes mentioned above. I address this by asking questions that might seem silly in my mind and by stating my understanding of our shared expectations aloud. I’ve found others often have the same questions so they end up being not so silly after all. When stating shared expectations I talk about next steps, who is accountable for them, timelines, and expected communication cadence. This gives others a chance to correct our shared understanding. I also ensure decision makers are explicitly onboard with the plan and timeline, not just initially but also throughout the product process, even if the plan does not change. This is important because even if my team’s plan doesn’t change, the plans of adjacent teams or the company might change, and that could affect the relative priority of my work. Another mistake I’ve made in the past is assuming a lack of response to an update was the same as continued approval. I now like to ask for explicit confirmation or feedback on updates so I can work to address concerns if needed.

    With everyone on the same page, we shared the plan with our engineering team and asked if they could meet the timeline. This was mid-day on Tuesday. It was critical to have their okay on the plan because they were the ones that would make the changes we had in mind. They said yes, and we told our stakeholders we were good to go. We were now accountable for the work and the timeline. This wasn’t about taking blame if we failed so much as having an understanding of our goals, and knowing we needed to share progress and roadblocks along the way. We gave regular updates on our progress, which in this case was at least twice a day given the nature of the work. We also shared new decisions we made knowing we could adjust later if needed.

    Managing Expectations
    We’ve talked about how to get everyone on the same page, but we haven’t talked about how to keep them there. That entails communicating with people based on their role with some regularity. Here I ask myself what information the people I’m communicating with need to do their job and how often they need it. In other words, it’s not enough to “manage upward” — you need to manage communication in every direction.

    For instance, a high level decision maker likely doesn’t need to know every detail of my team’s project, but they probably want to understand whether progress is being made, whether it will ship when they expect, and if we need help. Our updates to decision makers on this project were on the order of a few bullet points, which we followed by answering any questions they had. Peers might expect more detailed updates relevant to their role.

    I mentioned we shared updates at least twice a day on this project, but communication cadence depends on the circumstances. I think about sharing updates at a cadence that keeps my work top of mind, but not so often that I’m not conveying meaningful progress. The idea is to make sure stakeholders don’t feel out of touch with your work. Knowing you’re making progress also helps when it comes time for them to shelve projects that aren’t working out.

    You made it all the way to the end of this post so I suppose you want to know how the story ended: we shipped on time with happy stakeholders and our change met the goals we set in our plan.

    Follow me on Twitter if you like puns, pizza, and performance reviews.

  • Software Engineering Isn’t Magic

    The other day I was chatting with a friend who is both very competent and early in their software engineering career. They had noticed it sometimes took others less time to solve problems than it took them, and when they’d ask for help, these folks knew the answer or could often point them in the right direction right away. It felt like magic.

    Thinking this is normal, but it’s not magic. When people come back with an answer quickly it’s because they’re aware of the problem, already understand how a system works, or because they’re pattern matching against previous experiences and happened to guess the issue. But if you’ve ever handed off a difficult bug only to have a peer come back the next day with what seems like a simple fix, it can trigger negative feelings.

    A couple of years ago I was trying to understand a strange bug in my company’s app that broke the theming system with a new beta release of iOS. After several hours I was able to figure out where our theming code now failed, but I was stuck trying to find the root cause of the bug. I asked the person who wrote the theming system for help and they came back the next day with a single, subtle observation about a behavior change in the underlying system libraries that allowed them to fix the problem. In this moment software felt like magic, but in reality this person had invested a tremendous amount of time learning the underlying system libraries. They’d spent hours debugging the problem to understand it. That isn’t magic — that is expertise and putting in the time.

    A year or two before that I was helping improve build times for our team when I hit a segmentation fault in a popular compiler. I remember feeling helpless until a more experienced engineer said something like “it’s just software and we can debug it like anything else[^1].” Ah, just because it’s a black box doesn’t mean it’s magic. It’s a system we can debug because we can observe its inputs and outputs. That gave me the boost I needed to go back to basics: I started commenting out code to see where the compiler failed. After a while I was able to pinpoint the problem (two particular operator overloads) and found a solution that let us roll out a major reduction in full and incremental build times.

    It’s okay for you to take longer than others to find problems or fix things, and it’s okay to need help from others. You’ll get better at what you do over time too. They’re not faster because they work magic — they’ve just seen this before. Sometimes you’ll see something that others haven’t seen, and suddenly you’ll be the magician.

    Thanks to my friend Joe (@mergesort) for helping me edit this post. You should follow him on Twitter. Oh, and I’m on Twitter as @amdev as well.

    [^1]: They meant literally build and debug the compiler

  • Thoughts on Teams

    People have different value systems. Someone may value very expensive headphones, or cameras and you may value sneakers. Someone may value working really hard, and you may value having time to live and travel. It’s best to not push your value system onto others, because it can harm relationships. It’s okay and good that people value different things.

    Related to value systems — how does one’s value system affect how they weigh tradeoffs? Is this refactor more or less important than shipping? Internationalization? Accessibility? Polish? What stage is your company at? What’s the right thing to do? How does one’s value system help define “right”? Can you think of a way to acknowledge a peer’s values and leverage strengths in a way that helps your team succeed and makes them happy?

    Value systems also affect motivations, which vary from person to person. Some people are motivated by public praise, or maybe the rush of shipping something new and exciting, knowing they built something really well, realizing a lot of people will use their work, just helping others, money, or most likely a combination of these things and others. It’s hard to change people’s motivations, but understanding them can help you improve your team’s performance as you work to fulfill them on an individual level. (The team’s needs should come first most of the time, of course.)

    Working hard at your job will sometimes net you rewards, but working hard alone isn’t enough. You have to work on the right things — generally the right things end up being whatever is important to the people making decisions. In my experience it’s easier to burn out working hard on the wrong things, but it can also be really gratifying serving unfulfilled needs. The lesson here is to think about your goals before working hard and choose the right things to work on based on those goals and what you value.

    Be kind, but also direct with others in business to avoid misunderstandings. Sort of related — don’t be a jerk or you’ll harm relationships and people won’t want to work with you.

    Try to be “on” at work. Make a todo list (however you like), and do either the most important thing or the thing you have time to do right now. Mark it off. Remove things that stay on the list for too long without progress and aren’t actually critical.

    Let people know where you’re at regularly and set expectations on when you can get back to them with what they need. This is a lot of what it takes to succeed. Once you’re good at your core responsibilities, look for problems that get in the way of your team’s success. Set out to fix those issues, and get help from your peers. Share credit with and publicly thank the people who help. You’ll build trust and get recognition. Take a broader view of “team” over time and repeat this process to drive bigger change.

    Is this similar to your experience? Lemme know on Twitter.

    People have different value systems. Someone may value very expensive headphones, or cameras and you may value sneakers. Someone may value working really hard, and you may value having time to live and travel. It’s best to not push your value system onto others, because it can harm relationships. It’s okay and good that people value different things.

    Related to value systems — how does one’s value system affect how they weigh tradeoffs? Is this refactor more or less important than shipping? Internationalization? Accessibility? Polish? What stage is your company at? What’s the right thing to do? How does one’s value system help define “right”? Can you think of a way to acknowledge a peer’s values and leverage strengths in a way that helps your team succeed and makes them happy?

    Value systems also affect motivations, which vary from person to person. Some people are motivated by public praise, or maybe the rush of shipping something new and exciting, knowing they built something really well, realizing a lot of people will use their work, just helping others, money, or most likely a combination of these things and others. It’s hard to change people’s motivations, but understanding them can help you improve your team’s performance as you work to fulfill them on an individual level. (The team’s needs should come first most of the time, of course.)

    Working hard at your job will sometimes net you rewards, but working hard alone isn’t enough. You have to work on the right things — generally the right things end up being whatever is important to the people making decisions. In my experience it’s easier to burn out working hard on the wrong things, but it can also be really gratifying serving unfulfilled needs. The lesson here is to think about your goals before working hard and choose the right things to work on based on those goals and what you value.

    Be kind, but also direct with others in business to avoid misunderstandings. Sort of related — don’t be a jerk or you’ll harm relationships and people won’t want to work with you.

    Try to be “on” at work. Make a todo list (however you like), and do either the most important thing or the thing you have time to do right now. Mark it off. Remove things that stay on the list for too long without progress and aren’t actually critical.

    Let people know where you’re at regularly and set expectations on when you can get back to them with what they need. This is a lot of what it takes to succeed. Once you’re good at your core responsibilities, look for problems that get in the way of your team’s success. Set out to fix those issues, and get help from your peers. Share credit with and publicly thank the people who help. You’ll build trust and get recognition. Take a broader view of “team” over time and repeat this process to drive bigger change.

    Is this similar to your experience? Lemme know on Twitter.