Accelerate your software engineering career by sending small diffs

Every software developer gets carried away once in a while. There is this new cool, top requested feature and we want to code it quickly, so we disappear somewhere and, after a few weeks, we drop this huge diff (a.k.a. PR, CR) like a bomb. We are so proud of our work! Somehow, our team members do not share our level of excitement. Why is that?

Well, it turns out that huge diffs create a number of problems that make lives of both the author and his team harder:

  1. Getting huge diffs reviewed is challenging
    Finding someone willing to review a huge diff is difficult. Once this person is found, the progress depends on them finding a lot of time to properly review the changes.
    Occasionally, a huge diff draws attention from multiple reviewers leaving tens of conflicting comments. Each new iteration addressing these comments only sparks more comments.
  2. Keeping huge diffs up-to-date is hard
    While a huge diff is being iterated on smaller diffs are merged daily. This may result in merge conflicts which take time to resolve, create risk of introducing bugs due to bad merges, and make it harder to understand what changed between iterations.
  3. Huge diffs rarely receive good feedback
    Understanding of a huge diff is hard and time consuming. Reviewers often focus on less relevant but easier to understand details. Sometimes they give up and just rubber stamp the diff without leaving any useful feedback. In either case, obvious issues can easily sneak into the product.
  4. Huge diffs make it hard to pivot
    Sometimes, someone finds an issue that forces changing direction. In case of a huge diff it means a lot of time was spent on writing code that now needs to be rewritten or thrown away.
  5. Merging huge diffs may have significant negative impact
    When a huge diff is finally merged, it often wreaks havoc across the team. Many ongoing changes have to be redone, the number of reported issues increases significantly, dashboards and alerts get broken, etc.

The alternative to huge diffs is splitting the work to smaller, more manageable chunks. Each chunk should be a logically complete piece of functionality that can be independently merged and brings the feature closer to completion. It may feel like more work but it is a much more effective approach:

  • code reviews are faster as small diffs take less time to review
  • different diffs can be reviewed by different people – there is no longer a bottleneck of a single reviewer
  • smaller diffs are easier to understand so they get better feedback
  • it is possible to work on the next diff while having one in review
  • changes are localized so the risk of merge conflicts is reduced
  • course correction, if necessary, is easier because there is not much code impacted

Getting used to splitting the work to smaller chunks can be hard at the beginning but once you get used to it, it will become natural and your productivity will soar!

Accelerate your software engineering career by understanding adjacent layers.

As a developer you are always between something. If you work on UI, you are between the user and the rest of your application. If you work on web services or APIs, you are between the web framework and a database, a library, or another service. Your executable code is between the compiler and the runtime (JVM/CLR) or CPU.

While it’s possible to work just in your area, ignoring what’s above and below you is not a good long-term strategy. Knowing at least a little about adjacent layers is invaluable because it:

  • makes debugging “weird” issues easier
  • can help prevent mistakes made due to incorrect assumptions
  • allows choosing more optimal design choices

How can you learn about adjacent layers? Here are a few ideas:

  • If you are using a popular framework, a library, or a product like a database there should already be a lot of documentation readily available
  • In case of open-source projects you can simply check out the code
  • For libraries or services created in-house you can talk to the team who built them or read the code
  • You can also look at the code for JavaScript (or TypeScript) libraries because they ship as code. Minification and uglification can make it challenging
  • If you don’t have access to code and you’re working with languages like C# or Java, you can use decompilers that do a decent job generating code from the IL/bytecode
  • Your last resort is looking at or debugging the assembly, but this is hard in general and your mileage may vary.

Once you get a good grasp of your adjacent layers you can take it further and understand layers your code doesn’t directly interact with. Keep doing this and soon you will be one of only few people who understands the entire stack.

 Accelerate your software engineering career by tracking your work

Your manager doesn’t know what you’re doing. They do know about things you should be doing they care about but you’re doing much more than that. You’re probably doing much more than even you think you’re doing. So, if even you don’t know what you’re doing why would you expect your manager to know this?

To know what you’re doing you need to track your work. The reason to do this is to be able to easily answer the following questions:

  • What am I doing? – helps confirm you’re working on the right things
  • What am I not doing? – helps ensure you’re not dropping the ball on important work
  • What I’ve accomplished this year/half/quarter? – makes all career, performance review and promotion discussions much easier

There are many ways to track work. You’ll need to find what works for you. I do it in a very simple way. Each year I create a Google doc for tracking my work for the given year. It has two sections:

  • What I’ve completed
  • A weekly list of tasks or projects I need to work on

Each Monday morning I spend 10-15 minutes to update this doc. I go over last week’s work items and move completed ones to the ‘completed’ section. I strikethrough work items that are no longer needed or I decided not to do. I copy the remaining ones as this week’s tasks. Finally, if there is any new work, I add it.

I attach artifacts to most items in the ‘completed’ section. They are a tool I or my manager can use to showcase my work and support my career related discussions. Here are examples of what I include:

  • Links to design docs, posts, roll out plans, etc.
  • References to diffs where I influenced the design or prevented serious issues
  • Other teams’ projects I helped unblock
  • Details about why something I did was hard

There is no one correct answer as to what granularity to track the completed items at. I found including smaller work items is worthwhile. Some of them are too small to matter by themselves but they add up. The secret is to group them in coherent themes. For instance, adding a couple tests will not get you to the next level but if you have done this multiple times you might have significantly increased the test coverage for your team or product which could be an additional argument to support your promotion.

Starting to track my work was one of the best things I’ve done for my career. It takes just a few minutes per week but gives me the clarity I need and saves me a ton of time during performance reviews. If you’re not tracking your work, I strongly encourage you to start.

Accelerate your software engineering career by fixing something every week.

We, software engineers, are so used to living in pain that we stopped noticing it. We die a death by a thousand papercuts every day only to start fresh the next day. Flaky tests, broken builds, workarounds, outdated documentation is our daily bread. We live with all of that forgetting how much it costs.

Imagine an annoying issue you need to spend a few minutes on every week. Now, multiply this time by the number of people on your team – likely, they all are facing this issue. I also bet this is not the only “small” issue you and your team have. If you add all this up it may turn out that your team could use another engineer whose full-time job is just to deal with all these annoyances.

With time, it only gets worse because small issues tend to grow. One flaky test leads to a flaky suite and soon no one can tell what the quality of the product is. A convoluted function is patched multiple times without anyone really understanding it to the point when everyone prays that they don’t have to touch it. Missing test coverage results in multiple bugs reported by users.

The interesting thing is – most small issues don’t take a lot of time to fix. You yourself (i.e., not counting your team) may be able to recoup the time invested in a couple of weeks.

There are many examples of the positive impact of taking care of a small issue. Here is just a handful examples from my experience:

  • Fixing an acknowledged bug deprioritized consistently from release to release made lives of some users better (and discussing the bug repeatedly took more time than just fixing it)
  • Refactoring code that was incomprehensible made adding a new feature easier and faster
  • Updating an internal wiki helped save time spent on answering the same question again and again
  • A “flaky” test was a result of a product bug that could have serious consequences
  • Tuning a noisy alert prevented from waking up a team member who was on-call in the middle of the night

But wait, there is more! If you keep doing this regularly (a weekly cadence worked best for me) people will notice. Your team members may even start doing the same! And if they don’t, it will at least make it harder for them to make things worse – for example, it is much easier to ignore a new failing test if tens of tests are already failing than to ignore the first failing test in a suite. In any case, you are now helping to strengthen the engineering culture of your team leading by example.

And what if no one notices? Oh well, you made at least the life better for yourself – and this is already a win!

Accelerate your software engineering career by writing clean diffs

As a software engineer writing diffs (also called PRs – Pull Requests, or CRs – Code Reviews) is your bread and butter. You want to code your changes, have them reviewed, merge them, and start the process again. Repeating these cycles effectively is essential for delivering new features and building products quickly. There are not many things that can slow this process down like low-quality diffs. Some signs of a low-quality diffs are:

  • Compilation errors
  • Tests failures
  • Lint warnings

Low quality diffs leave both the author and the reviewer(s) frustrated. The author is frustrated because there is a lot of back and forth and they fell like they will never be able to merge their changes. The reviewers are frustrated because they feel their time is being wasted on diffs that are clearly not ready for review.

Sending a low-quality diff happens occasionally to everyone (e.g., this new file you forgot to include in your diff or that test you didn’t run due to a typo). However, when done repeatedly, it will have a detrimental effect on your career because your team members will simply try to avoid reviewing your code. This will prevent you from iterating quickly and will make it harder for you to adhere to schedules.

While spending a few minutes to double check your diff is in good shape may seem like a waste of time – especially if timelines are tight, it is an investment that in a long run will save you even more time. And once you build this habit it will become your second nature.