Whirlwind: What my first 'real' software engineering job taught me
Having speed makes others happy in the short term. Having velocity makes you happy in the long term.
One of the biggest lessons I learned was to prioritise ‘velocity’ over ‘speed’. This probably sounds meaningless to you, but allow me to explain. At some point around a year ago, during my one to ones with my manager, we were discussing the fact that I was heavily distracted and finding it tough to concentrate on tasks I wanted to work on. We established that one of the main causes of this was the fact that I would agree to help anyone who happened to ask for my help. Sales has an issue with something? Yes sure I’ll look now! Marketing wants some data on something else? Why not, I’ll look now. A more junior engineer would like help in a particular area of the codebase that I happen to be more familiar with? Sure, no problem, lets pair! I had high ‘speed’. I was helping others to accomplish their goals with no consideration for how to prioritize tasks to provide my team and the wider company with the maximum value I could provide.
Learning to prioritize, knowing when and how to say no, and most importantly when to say yes are crucial skills in improving your ‘velocity’. Velocity in this sense is being used to describe the pace at which you are delivering your maximum value. By constantly saying yes to others requests for assistance, I was failing to perform a value judgement comparing whether helping them to continuing with the task I was originally doing. As we all know, context switching is expensive. This led me to be known as one of the most helpful people at the company (I had more high fives than anyone else at the company!), but I also became known for being constantly busy and giving bad time estimates.
I believe it is innate in most of us to be helpful, however being helpful can actually reduce your overall effectiveness as an engineer. The best advice I can offer on this is best given in the form of a proverb of highly contested origin: “Give a man a fish, and you feed him for a day. Teach a man to fish, and you feed him for a lifetime.”.
Code bases that have been around for a while might look weird, but they might just be solving problems you’re not yet aware of.
I’m sure every single fresh-out-of-university experience-lacking engineer has had that moment where they join a company and see the code that powers it for the first time. Seemingly simple routines seem more complex than they need to be. Seemingly small problems have huge solutions. Craziness, in short. It can be terrifying. You’re fresh out of school, looking at this codebase, wondering what the heck is going on? Why is everything so complex?
It turns out that managing a huge codebase is a hard problem, and a junior engineer is rarely a good judge of the scale or scope of a given problem. It’s not that there isn’t bad code in the codebase, its just more likely that any junior engineer with 3 months on the clock has most likely not seen enough of the system to fully understand the problems it is solving.
As time went on, I learned more about the actual problems this codebase was addressing. What I perceived as overcomplications turned out to be problems I wasn’t aware of being solved. What I thought was badly designed code was actually just code I didn’t understand. It’s intimidating to work on such a large system, especially when the most ambitious project you’ve worked on prior to it was several orders of magnitude smaller and not subjected to the brutality of customers, but if you’re anything like me, you’ll learn ridiculously quickly.
Team culture is a real not-bullshit thing.
By far my favourite thing about my first job was the learning opportunities around me. I was surrounded by massively intelligent, kind, determined people who all were more than willing to help me get up to speed.
I believe this environment didn’t happen accidentally. The company was very careful to create a culture where this kind of collaboration could happen. Much more senior engineers spent probably weeks of their lives showing me the ropes and teaching me about anything and everything I wanted to know, work related or not. Every single one of these people was hugely passionate about what they do and loved to share their knowledge.
Outside of work, these people held clubs and sessions relating to areas of interest to them personally. I was particularly fond of but sadly nowhere near involved enough in an electronics session - the last activity of which was to build Tetris with nothing but ‘nand’ logic gates! This environment is perfect for a junior engineer to thrive in, and I am hugely grateful to have had a job where the conditions were so ripe for it.
As I became more and more established and newer members of the team were hired, I found myself in a position to pay it forward, if you will. What I learned during these encounters was that the educational aspect of it goes both ways. The field is such a vast one that everybody probably knows something somebody else doesn’t, so learning new things from these engineers was a common occurrence for me. The learning wasn’t always technical either. I developed people skills I didn’t have before. I began delegating. I grasped the best attitude to have towards people and the problems we faced together.
You, as much as anyone else, foster this spirit of reciprocal learning. Represent and grow it the best way you can.
Look for opportunities to lead a project, and just do it.
The average engineer at a startup seems to have to wear many hats. I found myself working on the core of the system in one language and on the billing system in another within the same week. I maintained SDKs in multiple different languages. I worked on our frontend as well as backend. This is a natural requirement at a startup; there just aren’t enough people to cleanly define peoples roles and have them stick to them. I think its fair to say anyone in this position will gain a diverse set of skills that don’t necessarily join up neatly. It also provides many opportunities for identifying problems with areas of the system that others just haven’t looked at recently.
These are amazing opportunities for the ambitious engineer. It is possible to pick one of these areas and become the leader of a project in a startup environment.
If you wish to succeed in convincing your team that the problem you’ve identified is worth solving, you’re going to want to become the domain expert on the topic. Read up on other solutions to the problem you’ve found. Talk to other engineers in the company about whether they’re aware of it or even if they’ve attempted to solve it before. Quantify the problem. The most effective metrics I’ve found are monetary savings or developer efficiency improvements. The question you should be answering is why it is valuable for you to spend your time on this project rather than something, or someone else. You’re not solving a problem; you’re instead executing on an opportunity you’ve identified.
It is important to remember here though not to outgrow your boots. This fresh into the field you can easily find yourself chasing rabbits and trying to solve huge problems that much more experienced engineers would struggle with. The best opportunities are the low hanging fruit.
Imposter syndrome is real, and it sucks.
I’m not going to write much about this since so much has been written on the topic already. In my experience everybody suffering from it likely thinks that they’re not the ones suffering with imposter syndrome; they’re actually imposters! They’re somehow flying under the radar, holding on by the skin of their teeth.
This is most likely not the case. Think about it logically. This field is generally well paid. The company is paying you for your time. In order for it to make sense for them to do so, you must be delivering value to the company in one form or another. You’re probably not special. You’re not fooling anyone. You’re a junior engineer who has probably passed through their probationary period and is doing their job well enough to warrant the money you receive.
In the first few months, focus on a year from now.
At a startup, you’re likely being brought on to wear many hats. Different kinds of work require different levels of context and different levels of experience. Its natural to gravitate towards tasks that require lower context and little experience, since these are the ones you’re most likely to deliver results on quickly. If you’re like me, you’ll feel that for the first few months you aren’t really delivering all that much value to the company, and you may even feel a little guilty about it. Why are they paying me to sit here and not know what I’m doing?!
It turns out that you aren’t the first software engineer hired fresh out of university, and they’re as aware as you are of your lack of experience. There’s no reasonable way you could contribute immediately. It takes time to acclimate to the ‘real world’ and to learn the code and company well enough to be able to deliver quickly.
Don’t make the same mistake I did and just focus on delivering as much as possible as early as possible. This pays off early but hurts you in the long run, since you’re not giving yourself the chance to properly dig into the code. Spend this early time figuring out what interests you in the code and how you can deliver value to yourself while delivering for the company. This might involve learning a type of system you’ve never seen before, or a programming language you didn’t know before. This is okay! That is what this period is for. You’re focussing on your own personal development in this time so that later you can deliver significantly more value.
If you instead continue on the path of delivering as much as possible as quickly as possible, you’ll reap the rewards early on but you’ll probably lose motivation as you continually work on projects that don’t get you excited.
Own your fuckups. They’re probably okay.
Every engineer is likely to do something that negatively impacts other engineers or customers. I personally recall accidentally leaving debug logging on a service which caused that service to use much more CPU and run slower for a bit. Thankfully we had CPU to spare, but this really shook me up. What surprised me was the completely accepting atmosphere I found myself in. I wasn’t told off, and instead was asked to look into making a mistake like this impossible to repeat. This meant what was a very minor mistake with no impact to anything really except the heat output of a data center turned into a real reliability improvement - since mistakes like this could very well turn into very serious issues if not mitigated.
I get that not every work environment is going to be like this, but if yours is, lucky you. Go forth, make new mistakes.
Productivity is not what you likely think it is.
Productivity in Engineering is really difficult to quantify. Lines of Code is not a good measure. Neither are commits. Your days where you write no code can be massively productive.
This may sound obvious, however it took a conversation between me and a colleague, Jim to realise this.
One day a year or so ago, I was having an extremely hectic day. I was all over the place. I was pairing with Engineers who had just joined the team to get them up to speed. I was writing docs. I was managing a contractor. I was participating in meetings As the day wore on, I became more and more aware of the fact I’d made very little progress towards the goals I’d set myself. I’d written zero code.
I ranted to Jim about how I felt like I had got nothing done. He then told me in no uncertain terms that if all I was valued for was LoC, I’d be a code monkey, and that in fact I’d had a hugely productive day. This conversation made me think. Other colleagues who I thought of as massively productive rarely wrote code too! Maybe I really was productive!
Communication is HARD.
I’d like to think that I am a good communicator. I have the gift of the gab and will talk for Wales if given the opportunity. I’m well known for being immensely friendly and constantly happy. I found regularly that I was misunderstood however. How could that be? This job taught me that it is possible to over-communicate. I was talking a lot, but not conveying much meaningful concrete information. When it came to collaborating with other engineers, I was great at talking about what we were doing but terrible at co-ordinating the work we were doing.
The way I began to solve this was pretty simple. I decided that any concrete decisions needed to be communicated in as few words as possible via writing. Anything more visionary could be discussed in person, but the outcomes needed to be written down. If there was stuff to be done, I assigned people to action them. If there was stuff that needed to be discussed, I scheduled a meeting and had an agenda. Not exactly rocket science, but an extremely useful lesson to learn.
This led to less words, more effectively spoken.
Giving talks is a great way to bring up others perceived value of you.
This links closely with the communication point I discussed above. I started giving talks to introduce others to what I was doing, and to open lines of communication that weren’t previously there.
One time, I gave a talk on a project I was working on related to Terraform. I was working on importing AWS resources into Terraform so that we wouldn’t have to recreate infra. This task was tricky, and involved many fiddly parts that didn’t quite work properly. Terraform is not really suited to import massive amounts of old infra. After the talk, a member of another team offered his assistance to me as he’d been working on Terraform recently too. I had no idea that others had experience with Terraform, and his assistance proved invaluable.
Other ways this is incredibly useful is to get the rest of an organisation excited about what it is that you do. It’s all well and good having your direct team-mates understanding the value of your work, but what about the salespeople? Marketing? The quickest way to pique their interest in my estimation was a talk.
When giving a talk to people who aren’t directly related to the tech you’re working on, it’s important to remember they likely don’t care that much or understand that well the “how”. They want the “what”, “why”, “who”, and “when”. Put yourself in the shoes of the audience member you most want to get through to. Ask these questions.
- What is this work to me?
- Why should I and those I communicate with care about this?
- Who does this benefit?
- When is it available?
Your talk doesn’t even necessarily need to be about what you’re doing. I gave a talk once on Silicon bugs. This was pretty irrelevant to the day-to-day, but people found it very interesting and that sparked a few conversations with people around the business I had never spoken to before. These cross-business links can prove invaluable.
At some points, you might be the most knowledgeable.
This is a scary realisation. As you dig more and more into the problems you’re solving, you’ll begin to specialise in particular areas of the product. As a junior engineer, you’re likely used to the comfort of having a senior engineer behind you to tell you when you’re doing well and when you’re not. Your specialties in understanding develop, and suddenly your senior engineer tells you that they don’t know! They’ve got useful general advice, but whether your approach is correct or not, they don’t know. You look up, and there is nobody to defer to now.
At this moment, you are probably the most knowledgeable on the topic at hand. You become responsible for seeking the answer.
Even more scary is when more junior engineers than you start to look up to you in the way you looked up to your senior engineer in the past. You look up again, and there’s nobody to ask for specifics! This is when you try to pass on to the junior engineers useful ways of figuring out the answer that you developed when you first realised there’s nobody to look up to anymore. These can range from simple “how to use stackoverflow” to more specific “what’s enough due diligence to verify you’re not going to break production?”.