In this blog I share some advice on how to grow as a software engineer that I have collected through my own experiences, reading and observations.
In the space of about 17 years I have personally grown from not knowing programming at all to being a Principal Engineer at Atlassian. I have built some cool things I am proud of and I have worked with some amazing people. I have been involved in mentoring, interviewing and promotions, and I have some practice in thinking about how to guide, level and grow engineers.
This blog is targeted at people who are entering into the software industry. The content of this blog was originally given as a presentation to University students. I cover a fair amount of ground in a relatively short period of time. I hope that my words can carry you into deeper thought and exploration.
Giving general advice is a difficult exercise as few things are universally true. I acknowledge my advice is likely shaped by my privilege as a white native english speaking male (hard to escape my own bias).
In order to grow as a software engineer, there are three parallel and overlapping areas that you will want to improve in:
- 👩💻 Technical proficiency
- 👀 Contextual awareness
- ✍️ Communication skills
In addition to talking about these areas, I will also give some general pointers:
- You are worth more than your outputs
- Be kind to yourself
- Adopt a learners mindset
- Dangerous accelerant: side projects
Let's do this.
How well do you know the programming language(s) and technologies that you are working with?
The foundation of your value as a software engineer is technical proficiency. You want to pursue an ever increasing understanding and familiarity with the programming language(s) and technologies that you work with day to day. A strong technical proficiency will allow you to craft robust, clean, valuable and creative solutions.
You will want to get a good grip on:
- Foundational language building blocks, such as: variables, loops, functions, conditions, type systems, type coercion, classes, objects, collections, input and output and so on.
- Language grammar and semantics (don't shy away from the hard parts - even if you don't use them right away, you might encounter them or find use for them at some point)
- Scoping rules (what things can be accessed when, and by what)
- Error handling
- Code reuse and sharing patterns
- Asynchronous behaviour
There are so many ways you can grow in technical proficiency, and I don't think there is any one right way. Find some option(s) that you find interesting and motivating.
Here are some ideas for how you can grow your technical proficiency:
- Read technical books
- Read industry newsletters
- Watch courses
- Attend meetups
- Attend conferences
- Read blogs
- Listen to podcasts
- Create your own side project (more on side projects later!)
- Get involved in open source (make your own project, contribute to another, read the source another)
- Experiment, fiddle! Find a way for you to run cheap little experiments to validate behaviour and try things out
- Seek understanding of why something does not work (or does work)
- Find (safe) people and learning communities you can ask questions to (eg twitter, reddit)
- Share your learning with others (blogs, meetups, book clubs)
My memory is pretty terrible, and knowledge that I don't use regularly tends to fade. I think that is a pretty common experience. So what I do is learn where I can find good information on particular topics, even if I cannot remember all the specifics about the topic.
"Get the fundamentals down and the level of everything you do will rise" - Michael Jordan
Over time, you should get comfortable asking deeper questions of your code. Knowing how to gather good answers to the following questions will increase your impact and effectiveness:
- How confident am I that my code is behaving how I expect? (types, testing, language familiarity)
- How do I go about troubleshooting problems in my code? (debugging)
Tip from @AndaristRake: logging is great for debugging (eg with
console.log()), but learning to leverage a proper debugger can power you up quite a bit
- How do I know if my code is working in production? (monitoring)
- How many people are using my code and how are they using it? (analytics)
- How can I use a server to do actions for me: tests, linting, releasing and so on? (continious integration)
- What are the performance characteristics of my code? (profiling, benchmarking)
- How do people learn how to use my code successfully? (documentation)
- How can people of differing abilities interact with the software I make? (accessibility)
- How can I (safely?) evolve my system over time? (migrations, evolutions)
Not all questions will apply to every language / stack, but you will get the broad idea
There is rarely a perfect solution to any problem in computer science. As software engineers, we are always balancing tradeoffs. Over time you will want to become familiar with identifying and balancing the benefits and drawbacks of solutions.
You will grow in your understanding relevant tradeoffs by:
- Compare answers to [↑ See: Ask questions about your code]
- [↓ See: Bare the consequences of your choices]
Weighing tradeoffs often involves considering many non-technical considerations as well [See: ↓ Area 2: Contextual awareness].
For your programming language, are there popular libraries or frameworks for solving common problems? Give them a go! See how they feel to you. Try to gain an understanding of the solutions benefits and drawbacks.
When we create code, it will generally go through a number of high level phases:
- Iteration and long term ownership
Ideally, you want to try to get experience with the entire lifecycle. You won't know how particular choices pan out straight away. Often it takes extended periods of time, multiple consumers, changing requirements and so on, to expose the true benefits and drawbacks of various technical choices. You can then feed these learnings into future decisions.
In order to successfully collaborate with other engineers, you will need to have a working knowledge of a version control tool:
git. At this point I wouldn't recommend you learn alternative version control systems unless you need to. A working knowledge of
git is a good mental model as well as familiarity with the basic commands.
git is also a gateway getting a server to automatically perform actions on your code (test, lint, deploy and so on).
Thankfully, there are lots of fantastic
git learning materials which a light Google search will reveal.
Your (beautiful) code does not exist in a vacuum. You will be more effective the more you can appreciate the multiple wider contexts that your efforts fall into.
Gain a good general 'full stack' understanding
For many engineers, you will be working on applications that span multiple layers of technologies. If you work in one of those environments, it is fantastic to gain a working understanding of all of the layers in that stack. Understanding more about the requirements, features, constraints, strengths and weaknesses of various layers in the stack you work in will help you to create solutions (or pieces of solutions) that plays into the strengths of various layers.
I am not advocating that you need to become a 'full stack engineer', rather, that you have 'full stack appreciation'.
Growing as an engineer also means helping the other people around you be successful too. Being a lone star on a project is not a healthy long term model for any project. Helping other people be successful has a multiplication effect for your project. What are the tools, processes and systems that can help your teammates be successful?
"We rise by lifting others" ― Robert Ingersoll
Having an understanding of the business (or project) you work for, and it's goals will help you align your efforts and advocacy. I have seen many initiatives and creative solutions be adopted because the driver of the solution understood the business goals and needs. You can burn time trying to redirect a business (or project) in a direction that you think is great, but doesn't line up well with it's goals. There is a time and a place for encouraging redirections - but it is helpful to know when you are pushing with or against the currently planned destination.
While software engineering and problem domain foundations don't really change all that often, there is a constant evolution of ideas and offerings.
There can be benefits in observing larger industry trends:
- Exposure to new techniques, projects and tools
- Sanity check your ideas against existing solutions
- Identity market opportunities
How can you keen up to date with industry trends? Similar methods to how you can grow in your technical proficiency:
- Read industry newsletters
- Watch courses
- Attend meetups
- Attend conferences
- Read blogs
- Listen to podcasts
- Join learning communities
The reality of creating software is that you will be communicating (a lot) with other people. Regardless of whether you are a solo open source developer or an employee at a mega software corp - communicating well with others is critical to your effectiveness.
I can almost feel some people cringe as they read this. You might be thinking:
"I just want to write code! I didn't go into software to become a people person!"
I can empathise with this. I am not advocating you need to become a highly articulate and eloquent socialite - rather, that you grow into being able to share clear and helpful information with other people. That doesn't sound too bad - does it?
Good communication leads to increased alignment and clarity, so that you, and the people you interact with, can focus on constructive things. Poor communication leads to a lot of friction, frustration and wasted effort for you, your teammates, your organisation and your users.
The code we write is just as much for communicating with your future self, and for other people, as it is for the machine to execute. Being able to have clear ways of communicating your intention and rationales in your code is essential for code that needs live more than a few weeks. Writing code that is easy to follow is a strong signal of engineering seniority as it demonstrates the understanding that code will need to be well understood by someone that lacks context at a later date.
Some general tips:
- Optimise for readability (this covers a lot of things)
- Avoid 'magic one liners'.
- If you really need hard to read code, hide it behind a nice API
- Use comments when you think something requires additional information that is not apparent looking at the code itself
- Types (and their names) can be a great way to communicate extra information
- Prefer explicit behaviour rather than implicit
- Only enforce style preferences that are backed by automatic tooling
Reviewing code (often through a 'pull request') is a common industry practice to help ensure software quality. There is so much to say about pull requests - you will find heaps of tips after a light Google search.
Pull requests are communication intensive. When you are creating a pull request, or reviewing it, you want to aim to be as clear as you can and who needs to do what. Pursing clarity in pull requests will lead to higher quality changes and for potential changes to be accepted / rejected faster.
Other people will need to make decisions based on information that you provide them. Here are some questions people might approach you, or your outputs with:
- Which solution should we adopt?
- Why should we invest in your idea?
- Why should I buy your product?
- Why should I adopt your open source project?
- Why should I hire you?
Using established persuasive communication techniques can help make connections between a need and a solution clear and straightfoward.
Persuasive communication is a skill that can be learned and improved. I personally was exposed to formal persuasive communication through a law degree (that I otherwise do not use much now). But a small Google search will reveal a number of blogs and courses on how you can learn and improve at persuasive communication.
For me, persuasive communication is not about tricking people, but about making your proposed value propositions clear and easy to follow. Doing this well will help others buy in or opt out more quickly, and for the right reasons.
I have shared three general areas for you to focus on improving in order to grow as an software engineer. Here is a collection of other thoughts that you might also find helpful.
My limited and subjective experience is that if you choose to define your self worth based on your outputs you will never be truly satisfied. Your self worth will rise and fall in proximity to your most recent success. I strongly believe the all human beings have dignity and worth is not tied to their outputs. Try to find a way to derive your sence of self worth from something other than your outputs. I am deeply and painfully aware this is no easy task, but I have found increasing joy in trying to decouple my self worth from my outputs.
You could spend all your time and effort becoming a great software engineer, and you would probably become one. Being good at your craft is awesome, but I think there is also so much more of the human experience for you to enjoy. If you work in software engineering, you will likely have many decades of working ahead of you. It's okay to take your time and enjoy the journey.
A great way to encourage your long term growth is to adopt a position where knowledge is not secret, but learnable (and forgettable!)
- Ask lots of questions
- Be okay with saying "I don't know" (espeically as you get more senior - it is license for more junior folks)
- Find ways that let you answer questions on your own quickly
- Be open to changing your mind on things. Try not to emotionally invest in technical positions because it can make it harder to change your mind when you should
- Challenge existing ideas
- It is okay to forget things (even basic things). It is very human. Be open about calling out that you don't remember something.
I have a love hate relationship with side projects.
Side projects could be things like:
- Creating an open source library
- Contributing to an open source library
- Making your own product
- Making your own game
- Creating digital art
- Soo many more things (I don't want to limit you!)
Side projects often put you in the drivers seat of a project and let you leverage your personal time to have more agency to execute on creative / risky things often with little consequences. Side projects are a powerful vehicle of personal growth on many vectors. However, they are a dangerous accelerant. It is easy to soak up significant amounts of your time with side projects. Speaking from painful personal experience - side projects can cost you more than were expecting to pay. Should you do a side project if you have the opportunity and inclination? For sure! But be careful.
I hope you find the advice I have shared helpful. Thanks to the people who helped review and give feedback on this blog.
You can follow me on twitter at @alexandereardon