Microsoft campus in 2018
Walking into work at Microsoft campus in the Summer of 2018.
28 January 2024

Five Lessons from Five Years of Software Engineering

Software Engineering

I began my career at Microsoft in July of 2018. A few months out of grad school for physics, I was wide-eyed and excited to learn more about software engineering. My love for programming came from work I had done in undergrad and as a graduate student to simulate nuclear interactions. This involved both building models in C++ and performing data analysis on the simulation output using Python.

By the time I started at Microsoft, I was a fairly competent programmer, but I had worked almost exclusively on my own until that point. Now, five years on, I’ve learned how to write great software collaboratively. I’ve found that beyond the expected technical abilities, success in this career depends on how you contribute to and rely on your team, understand others, and work to explain your own thoughts and work.

While I still have a long career ahead of me, with much more to learn, I wanted to share some of the most important lessons I’ve learned while they are still fresh in my mind.

Lesson 1

Your team is your development environment

Few great software projects are developed by a single engineer. Practically none within the industry. You will work with a team of people who have different strengths, weaknesses, and communication styles from your own. Put effort into learning about them, helping them reach their goals, and asking for help with yours.

This will look different for every person you work with, but the basic approach is consistent. Begin with a sense of empathy, remembering that the people you work with are fully human, just like yourself. Give them the benefit of the doubt if they miscommunicate or make a mistake. When they cross a line, tell them by communicating how you feel about their actions.

When a teammate is struggling, help them by directly asking for what they need. When you are struggling, find the people you trust and share what you are struggling with honestly. If you find that you are going to others for help and they are not encouraging your learning by helping you tackle a problem together, just stop going to those people.

I have sometimes found myself seeking help from people who I perceived as smart who used the vulnerability I exposed by asking for help as a way to lord power over me. These people are not worth coming back to. They may be smart, but they are not wise.

The phrase I always come back to with working on a team is “pull blame and push praise”. When an initiative fails, find the part you played in that failure and take ownership of it. When one succeeds, find ways to praise others for helping reach that success. This is not to encourage self-flagelation and an aversion to taking credit for wins. I would caution people to not take this saying too far. Instead, as a regular practice, it builds a culture where failures and successes are shared experiences.

Lesson 2

Alignment is about figuring out other people’s incentives

At Microsoft, there was an internal platform for recording outages. Once every two weeks, my organization would have a meeting where we looked at outages across all of the organization’s products. It was someone’s responsibility to compile an email agenda manually from the platform. When that person left, I was given the task.

The manual process took about 30 minutes to an hour once every two weeks. To give myself back that time, I wrote an Azure Function that communicated with the platform’s API, formatted, and sent the email at a regular 2 week cadence.

I thought this solution was brilliant. I took it to the team that maintained the outage reporting platform, confident that they would agree and merge my pull request. That did not happen. The pull request sat open for six months before eventually getting closed without merging.

What I had failed to consider was the benefits and drawbacks of what I had submitted against that team’s incentives. My solution was deployed differently from their .NET web service, it was written in Python which no one on the team knew, and it performed a task that was outside of that team’s charter.

Instead of going directly to that team’s engineers, I should have brought my solution to the team’s product manager. Rather than dumping code on the team’s doorstep, I should have presented the feature so they could determine if it made sense to expand their charter to include email notifications.

The engineers on the team were incentivized to run a reliable service for reporting outages across all of Azure. What I tried to give them was essentially a proof of concept that emails could be automatically delivered using Azure Functions as a platform.

They were not running their service using a microservice architecture, when they ultimately implemented a similar feature, it was added to their very successful .NET monolith that they understood well.

Lesson 3

Every project is more complex than it initially seems

When I started my career in tech, I was told to do by very best to estimate how long it would take me to complete a task, then double or quadruple that time.

I was familiar with the inherent problems of estimating project timelines from my physics research. As hard as I tried, I could never accurately plan how long it would take to build out an experimental setup or model.

Once, my research hit a six month snag as detectors were not reporting the count of particles that was expected for a given test source. I varied the geometry, checked the accuracy of the source, added and removed carbon disks to slow down the particles. Nothing seemed to add up.

Finally, my advisor and I decided that the schematics of the detectors must be wrong. The results we expected only made sense if the detector was a few millimeters back from where the the schematics said it would be. I drove one of the detectors from New York to Maryland to take an X-Ray and CT scan of it at NIST. As the image from the X-Ray developed, we saw clearly that the detector was several millimeters back from where the schematics said it would be.

Trust people when they tell you something will be hard. If your manager ever pushes back on your estimation and says she thinks it will take more time, listen to her.

Lesson 4

Plan before executing

I was exposed to the agile methodology too early and completely misunderstood it. Using the agile methodology does not mean forgoing planning. The philosophy was originally formed in the context of an industry that regularly produced “vaporware” by planning for an implementation so far out of scope that developers could never deliver on that vision.

Planning a software project gets harder the further out you plan. Planning too far out into the future become essentially useless as uncertainties in the implementation of the project build on each other.

However, planning is still an important step in executing the next iteration of work for a project. Having a loose intention of your next step written down somewhere is also helpful for focusing your efforts. When I start a task, I create a markdown document that has the goals and details for that task. Before I start coding, I write out a checklist of how I think the problem will be solved.

That checklist keeps me on track as I explore the solution. It also grounds me in the overall work so that I make sure everything I need to do is covered before I open up a pull request. Before I had this practice, I once changed a bunch of values in my team’s Helm chart, tested them by deploying the chart, then opened up a pull request with the work. I had failed to update the unit tests for the chart and the testing pipeline went red just as I had tagged my tech lead for review. Now, when I make my task checklist, if I am editing any Helm chart values, I always pair that with an item to check the Helm unit tests.

Lesson 5

Writing enables better thinking

Writing slows down and solidifies thought processes. I have found it much easier to hold on to conflicting or unrealistic ideas in my head. Once I write down those thoughts, their inconsistencies are often exposed and I can make better decisions.

Writing offloads memory into a semi-permament space. I like to keep an Obsidian document open all the time while working to store what I call “spare thoughts”.