Every morning, I wake up knowing I’m one of the luckiest people in the world. Having the privilege to be an engineer at Gusto is definitely one of the things that back up my belief.
I’m extremely grateful for the support, trust, and freedom provided by the team. Learning opportunities and resources are abundant — sometimes I feel like a kid swimming in a huge ball pool, and all I want to do is scream and play!
With that being said, there is no better time than first year anniversary to reflect on and summarize what I learned in the past 6 months since my first 6 months @Gusto retrospect.
Here is a list of the things I learned.
Everything is an optimization problem.
All problems, from as small as where should I go for dinner to as big as what should the engineering team work on next quarter, are optimization problems. To solve a problem, you need to know your priorities, resources, and constraints. And you need to be honest with yourself.
Nothing comes for free.
An advantage of rephrasing everything as an optimization problem is that it helps you realize nothing comes for free: everything you decide to do comes at a cost of not doing all other things you could have been doing. After all, time, the most valuable resource we have, is limited.
Sometimes we will get carried away by our emotions and think doing something that seemed small doesn’t really make a difference. Everything has a cost. Everything makes an impact. The only question is what’s the cost and how big is the impact.
From a personal level, it might mean the night you spend on a meetup event is at the cost of not finishing the chapter of the technical book you have been reading. From a business level, it might mean the quarter your team spends on improving the performance of the app is at the cost of not building that new feature which your competitor might be working on and might attract a lot of customers.
Acknowledging nothing comes for free makes us conscious about the decisions we make — don’t do things because they help but because among all options, they help the most according to your current priorities.
We are not only competing with all competitors out there, but also all other versions of our-future-selves.
The tricky thing is that, in most cases, even if we are aware of our constraints and options, we still don’t know which option will move the needle the most. All we can do is to make an informed guess, test our hypothesis, and iterate fast.
You have 24 hours a day. No more. No less.
This point is a continuation of the previous two. There were times at work I want to slack off. Sometimes I regret slacking too much. These regrets normally come around 6 pm when I am hungry, want to go home, and realize I haven’t got enough work done for the day.
Find the balance between Product and Engineering.
There was a period of time I was extremely passionate about reducing our technical debts. Each existence of a technical debt is like an ant biting my heart one second at a time. They are complicated. And nothing feels better than turning a mess into something that’s clean, elegant, and well-designed.
A conversation changed my point of view. During our team’s offsite hackathon, while I was having fun reducing N+1 queries in our code base, a product manager sitting across me asked: “how is that gonna benefit our customers”?
It was an enlightening moment for me. Not that I didn’t see the benefits of improving the performance of the app by reducing N+1 queries, what stroke me was the fact that I didn’t care to ask the question in the first place.
The more projects I work on, the more I feel the tension between product and engineering. On the product side, we want to get features out as soon as possible. On the engineering side, we want to make sure the code is functional, maintainable, and even extendable. I had a hard time reconciling both sides until that question came across:
how is that gonna benefit our customers?
I believe we should ask ourselves this question before making any decisions. Running a business is for sure solving an optimization problem, and benefiting customers should be on the top of the priorities list.
Context is the king.
Almost all questions in the world can be answered by a simple sentence: it depends.
Before doing anything, let it be starting a user interview or writing a helper method, be aware of the context of your problem.
For the users you are about to interview: what is the time of interview in their time zone? what would the state of their mind be? would they be sleepy because they just have lunch? do you need to get them excited or help them relax? why do they agree to do the interview? will their intents affect the result?
For the helper method you are about to write: where do you want to put it? is the file you about to put the code being actively worked on by your teammates? why do you need this method and how will it be used? do you need it because the design of the current code does not suit the feature you are building? does it make sense to refactor the code so you don’t need to write not only this helper method but also ten other helper methods?
Engineering is NOT about coding at all.
There are so many things that should happen before you actually sit down and code out the final implementation. Once you know what you should do, coding it out should be as easy as writing 1, 2, 3 on paper.
The hard part is figuring out the right approach you should pursue. Sometimes it means you should refactor the code you are about to work with before proceeding. Sometimes it means you should spike on an implementation and see how it feels before committing to the approach. Sometimes it means to run your idea through couple senior engineers, and see how it sounds to them.
When you actually sit down and code, you should have confidence in your approach and have a clear idea about what code should go where. If you don’t feel confident or the coding part isn’t smooth, maybe something is wrong and you should stop and revisit the problem.
Engineering is much like building something with lego blocks. Putting pieces together isn’t hard. The hard part is coming up with the right design blueprint.
In a startup context, constantly improving the process of how things get done is as just important as actually getting things done.
At a fast-growing startup, things changes fast, from the challenges the company faces, the current strategy, to the scale of the company. By definition, a fast-growing startup is a company that needs to evolve constantly to catch up with the challenges it faces. That’s why it’s growing fast and is always in motion of researching, testing, and figuring things out.
The process of how things are done, the structure and protocols, is like the skeleton of a company. Since the company is growing and changing fast, the process should be revisited and improved constantly to adopt changes, to make sure the company is in a good position for upcoming challenges.
Find the middle ground between two solutions when stuck with a problem.
When stuck with a problem which might seem only have two options, each has pros and cons and none seems ideal, try to think of a middle-ground solution that combines a bit of both options. The middle-ground solution might not be the answer, but it would help you to see the context more clear and might inspire you to think from a different perspective.
Be aware of your audience.
Provide just the right amount of detail for your audience. Read your audience when presenting and adjust pace accordingly.
from my manager Nick
One feedback I got was sometimes during standup, I provided too many technical details without providing context about how they fit into the bigger picture. It made it hard for PM to get an intuitive sense of how the project had been progressing.
I later learned to think from the perspective of my audience-what they care about and how much context they have. It’s something I’m still trying to get better at.
Nick definitely set a great example for me. In many meetings, he acts as the glue that helps attendees with different backgrounds stay on the same page. He pays attention to how each attendee is reacting to the conversation. And whenever he notices someone is lost due to lack of context, he is able to provide them the context in an effective way.
It’s like dancing with two people at the same time. On one hand, you need to stay on the conversation, digest others’ opinions, and cultivate your own thoughts. On the other hand, you also need to pay attention to the audience: who is engaging, who is not, when is the right time to interrupt and help someone to rejoin the conversation.
By no means is this easy. Yet, it’s definitely a skill worth training for.
Be prepared — the real game happens before the game.
Always be prepared before coming to a meeting. If it’s a meeting you try to present an approach, talk to couple people who will attend the meeting individually ahead of time, and collect their opinions. If it’s a kick-off meeting for a new project, ask for the specs ahead of time. Think about the edge cases. Read relevant code. Think about which part of it will be challenging. If it’s a pairing session where you try to understand an area of code with the help of another engineer, go through the code yourself ahead of time and come in with a list of questions.
Meetings are expensive. It saves everyone’s time when you do your homework ahead of time.
The same principle applies to other things. Before doing anything, run through in your head the what, why, and how: what are you about to do? why are you doing this? (what are you trying to accomplish?) and how do you plan to accomplish your goal?
Communication skills are crucial to being a great engineer.
As discussed above, engineering is much more about understanding a problem and figuring out the right design, than sitting at a corner and coding. Both require you to communicate well.
There are couple different aspects:
- Ask the right questions and uncover assumptions. Often, asking the right questions solves half of the problem, if not all. Sometimes we miss some use cases not because they are really all that edgy, but because of the assumptions we have.
- Communicate on an abstract level. To validate your idea on how to implement something, you need to be able to talk about your idea so you can collect feedback before committing to it. You need to be able to talk about code on an abstract level.
- Talk about different things at the same time. A lot of things are going on when discussing which approach should be used. You are brainstorming different approaches. You are weighing the pros and cons of each approach. You are recalling a specific area of code that brings complexity. You are evaluating how difficult each approach might be. You are thinking about how an approach might affect a feature in the next milestone. All these happen at the same time. At one moment, you are talking on a high level about how the app should behave. The next moment, a coworker jumps in and tell you how the existing implementation makes something which might seem straightforward almost impossible. The flow of the conversation is like a ball in a pinball machine-it changes directions frequently while traveling at a fast speed. The more people involved, the more chaos it can get.
Be a team player, a stress reducer, and a value provider.
I used to be really focused on growing technically. I still am. For every project I got, I would first think about what I might learn from it. I would be really excited when I got assigned to a project with challenges I hadn’t faced before.
I was trying to be a solo assassin more than a team player. Until one day, I watched a reality TV show where an investor turned down a deal. He said to the founder seeking investment: “I couldn’t stand you. You bring me too much stress. I have enough stress in my life. I want people who can take away my stress, not the ones bringing me more.”
His words stroke me. I asked myself who were the stress reducers in our team. Couple faces came to my mind-the ones always take on responsibilities, check if the project was on track, and think about edge cases. Working with these teammates made me feel safe and secure, knowing our project was in good hands. I decided I want to become one of them-someone who takes away others’ stress and brings values.
Bring different opinions to the table.
When working within a team within a company, it’s very easy for everyone to accept the current way of doing things because that’s how everyone does things here. Sometimes we might get so caught up in our way of doing things that we assume that’s the only way without noticing the assumption. At moments like this, a simple question from a different perspective can wake people up.
Over time, I learned that at Gusto, we were hungry for different perspectives, different opinions, and different ways to do things. We were eager to be challenged.
Since then, I have been trying to learn more outside of work in order to bring in different practices to the table. I also value my perspectives more, especially when they seemed different than others’.
Be the changes you want to see.
Watch out for the “I wish” you say. Every time you say that term is an opportunity to make something better. Every time I take an action on an “I wish”, no matter how small it might be, it always pay back in many different ways.
Take notes often and introspect regularly.
I’m a subscriber to an ancient Chinese proverb:
The palest ink is more reliable than the most powerful memory.
If some piece of knowledge seems valuable, it is worth to and should be noted down. I still refer to notes I took about a year ago when I just joined the company. Introspection helps me make the most out of every experience and feel prepared about where I’m heading. That’s the reason for this post.
Cheers the bigger challenges and higher mountains in front of us 🙃.