How do I become a software engineer?
Over the years, I have been asked by a whole range of folks a variation of this question. Despite being in the middle of a career in the field, it has taken me most of those years to properly formulate an answer to that question. If you are hoping for a link you can read to get there, be prepared for disappointment. But if you want a realistic analysis of what it takes, well, here’s my two pence.
My own journey to being a software engineer was largely the result of circumstance. My parents had a home computer in the 90s when everyone thought that it was a solution looking for a problem. My father nurtured an interest in electronics, which is a field that bears many similarities to software engineering and is indeed, intertwined. When the internet arrived, in all its screeching and whining 56kbits glory, I couldn’t help but be fascinated by it. My mother was almost entirely prevented from making or receiving a phone call for the next five years as I set up my nest in front of the beige box.
All of this was very new to everyone, so I now look back with a feeling I had a head start. I was part of what is now (somewhat depressingly) considered a previous generation of computer geeks, at least when set against many of the people who ask the question today. I tinkered around with my toy projects using mostly trial and error, raw curiosity, and what scant information I could find over the course of my childhood. Therefore, I have often become vexed when asked how you get to the same place by others.
Today there is everything I did not have: An enormous amount of articles, videos, free and easy access to help, ubiquitous and cheap capable hardware, clear career outcomes (salary, lifestyle) and nowadays you can even attend code workshops as a child.
Yet despite that, I still have the feeling it’s harder for people to find their way into this career than it was for me. I have empathy for those who feel like this is the thing they want to do but they happen to want to start to do it in 2024. It’s overwhelming and competitive, and the bar is high. It also became a lot more serious when compared with the whimsical and experimental nature of the internet in the early 2000s. The upper bound of how complex a piece of software can be has dramatically increased in line with the relentless forward progress of technology. There was no distributed “cloud” and AI in the same way there is today in the year 2000. But, more than ever, it is an exceedingly accessible skill to learn compared to many others.
So this viewpoint is in part coming from my experience working with, managing and hiring software engineers in commercial enterprises, as well as my own personal experience as an engineer. With that in mind, I can encapsulate what is needed into three things: Practical experience, enthusiasm for the craft and problem-solving capabilities.
Practical Experience
Let’s start with what this is not. Practical experience is not: reading a two hundred-page programming book back to back; watching a twenty-part programming YouTube series; being in possession of several certificates; or online qualifications; or being in possession of a degree.
Those are indicators that perhaps you have tried to gain a level of practical experience. They are possible tools to get practical experience (or at least, should be). And crucially, to varying degrees.
Without practical experience, no amount of reading by itself on any one topic will progress you through a software engineering interview stage. The industry expectation is that you will have hands-on ability. The level of practical experience you need is tuned to the level of the role you are applying for, so this needn’t feel as daunting as it sounds.
In a modern software company, seniority in a general developer role is pretty much never a function of some piece of paper or course completion you have to your name. However it is almost invariably a function of (in part) projects participated in, the material contribution to those projects, and the business impacts and outcomes of those projects.
Practical experience is opening your code editor and writing code. It does not specify whether it is commercial work. If you have your editor open and are trying to write code right now, you just gained +1 practical experience.
The learning tools (that is, the resources, courses etc) should be used to gain practical experience whilst using them. If the tool itself doesn’t encourage you to do this as an integral and forthright part of its goals, then it’s an inefficient tool. If it does, but you didn’t do that part, you didn’t achieve anything. The optimum approach is to learn just about enough to unblock yourself from doing what you want to do next in your code editor and read no further until you get blocked again. You will be switching between your editor and the resources/google constantly. You will ideally have some personal toy goal to work towards (some application that does something simple). The absolute worst possible approach would be to read a whole book or complete a whole course and then sit in front of the code editor afterwards. Or to gain such a certificate and walk into a job interview without any evidence of practical application of the knowledge it purports to represent, or without knowing for what situations that knowledge is useful. Hopefully, at the very least, if you do take up this kind of thing, you will have already completed practical applications as part of the course itself.
This may seem hypocritical, given I myself have a Comp Sci degree, which my interest carried me into. But, this rates as a relatively middling but not awful “tool”. There were heavily practical elements, but also heavily non-practical elements at times. I have no regrets, mostly since the social side is so valuable, so there are trade-offs. Ultimately, I have hired several brilliant software engineers who do not hold a Comp Sci degree.
The near-term goal when setting out to learn how to code needs to be to get something, anything, working. Actually, it doesn’t even have to work. Beginning to code includes fumbling your way through; breaking things; copying things; and doing stuff that you don’t even understand. If you haven’t got your editor open and trying to do something within the first three hours you’ve gone horribly wrong.
You will often have barely any idea what you are doing and you will have a billion questions. Learning to code is the act of discovery and a continuous iteration cycle between problem and solution on a micro level, dipping up to the macro level occasionally to formulate a slightly longer-term plan. The code quality you produce will be poor and you won’t even know at first what makes code good quality in the first place. But, over time, problems start to become familiar. You will have a greater ability to bring order to the chaos and write better code moving forward. It is in the act of working through these iterations that the real tangible skill increase occurs. And this never ends. Developers are never “done” growing their whole career (if you ever sense this, it means you might need to work on something else or find a new role).
There exists no certificate or course that is in and of itself a magic bullet. There is no path where you learn a “module” in bulk and come out the other side writing top-tier production code. These resources are only as good as the practical experience they expose you to, and the quality of the human support/mentoring around that practical experience.
What language, framework and tools should I learn?
It largely does not matter. Pick something popular to ensure you will have support online and sufficient opportunities in the local job market. Consider leaning towards a “higher-level” language unless you have a specific reason not to or you just want the challenge! In other words, a language which automates low-level common tasks, like JavaScript, TypeScript, C#, Java, Python, etc. As opposed to “lower-level” languages like C++ or Rust. This will help you avoid getting bogged down in advanced complexities too early.
Every engineer has their preferences, including me. You might find yourself googling comparisons and getting a huge amount of contradictory information and even flame wars. Engineers can become attached to their tools. It is almost a stereotypical attribute of engineers and I often satire myself by pressing colleagues’ buttons on this topic in the workplace. It’s not anywhere near as important as it might appear.
For every language, framework and tool there is a portion of the engineering populace who hates it. A quick taster: TypeScript is awful, Java is f***** terrible, C# is a complete piece of s***, C++ has a whole Wikipedia article taking a dump on it, Rust is the worst language to ever exist and Python is a goddamn mess. Don’t over-worry yourself therefore with all the contradictions and tribalism. You might develop opinions like these at some point in the future, but you should let that happen off the back of your own analysis and experience.
If you have an experienced friend in the industry who you can rely on to help you along, this can be an invaluable asset. It could even be wise to consider going with their technologies of choice, as long as they meet the basic popularity requirement. Having a peer who is willing to help is a massive advantage when learning how to code.
Keep in mind this decision of what to learn doesn’t define your whole career. A very common pitfall I see is folks agonising over this decision. Your goal is to write software. When you reach a good level, the skill of writing software transcends individual tools or languages.
A useful analogy I have pulled fresh out of nowhere is to imagine someone who wants to become a passenger airline pilot. It would make no sense for such a person to agonise about the exact model of the two-seater starter plane they must learn on. To do so would be inconsequential to the goal. At the same time, you probably wouldn’t want to switch to a different model in the first few weeks of learning as that would be disruptive. And if your friend happened to have a Cessna and was a pilot himself, that seems like it might be useful, right? And it’s probably best not to train on an aircraft that is soon to be phased out, or one that only had ten units roll out of the factory.
Eventually, you work your way up to the Airbus fleet. You are now a pro pilot. But there are all these other technologies to master, like the Boeing fleet. Moving from Airbus to Boeing takes a bit of effort, but nowhere near the amount that was required to get you to the Airbus in the first place. That’s because planes are more similar than they are different on the scale of things, even though pilots typically swear by their sacred preferred aircraft and argue with each other online about who is right.
In the same way, languages and tools are all in the realm of software. Each language typically has similar or comparable mechanisms. Your initial decision may stick with you for some time, but you’re not boxing yourself away permanently in the long run. In fact, quite the opposite. Actually, in my experience, the far more challenging task encountered in a longer-term software career is tackling new problem spaces, not new tools. Your washing machine probably has a microcontroller with software built using C on it. There’s probably C involved in the latest AI software too. Yet those two things couldn’t be more different and with complexities that are orders of magnitude different.
For the actual objective data about popularity and sentiment between different technologies, the Stack Overflow survey is great.
Once you’re settled on a technology, search out the resources. Quality matters, yes. But you can always change the resource if it turns out to be vague, misleading or some other factor that amounts to “poor quality”. And there is a lot of poor quality out there. If there’s an “official” guide for the language or framework you are learning, consider it as a starting point. Make sure resources are up to date.
Since there are a lot of poor-quality resources out there, investing actual money in such things should therefore be done with caution. And absolutely do not have the mindset that this journey can be simply completed by exclusively using money to gain a certificate. What you need to gain is practical experience and you can use whatever means is appropriate to do that. That may or may not include a paid course alongside some discipline to put it into practice. And even if the resources you used turn out to be poor quality, as long as your editor is open and you are trying stuff, it is still useful.
I’ll also add a (maybe controversial?) point that recent innovations like ChatGPT are actually really good at introducing you to new languages and you can bounce problems and questions off of it iteratively almost like you would a peer. Don’t treat it as an oracle, but it’s a starting point.
Enthusiasm for the craft
The good news is that the fact you are thinking about maybe becoming a developer, and reading this post, greatly increases the chance you have some enthusiasm for the field. This will sound like I am a party pooper, but you still need to be accepting of the possibility you might simply not like it. In fact, you should self-evaluate this early and often.
If you are thinking of making life changes or spending money on this, definitely don’t do that until you are sure that you have enthusiasm for the craft. And the only way to find out is by trying it.
Once you’ve got a bit of code running, you’ll ideally want to return to it. Not just because you have set a goal to be a software engineer, but because you actually relish the act of solving the problem or expanding the solution. There will of course be momentary periods of frustration; sometimes intense frustration. But if you feel yourself drawn back to it that’s a sign you enjoy coding. If it’s a daily chore, you should consider if this is what you really want. The initial objective should be to find this out to your satisfaction as soon as possible.
The same goes the other way. Many people are interested in the idea but never actually get started because the scale of the challenge is daunting. But actually, if it turns out you enjoy it, you only need to find the time and energy for those first few hours and the natural enthusiasm will carry you much further without the same mental barrier. And if you don’t care for it, well, now you know!
In interview scenarios, I find it easy to detect when someone is genuinely interested and curious about software.
Problem-solving capabilities
I’m not an academic authority on such things, and so I have no idea if the nebulous notion of “problem-solving” is something certain individual humans happen to be good at, or if it can be nurtured. I reinforce my previous comments that just trying to code is the way to find out for sure.
If you can think rationally and analytically about a problem, and break it down into pieces, then you might have this skill. You will also want to naturally figure out “why” something does or doesn’t work, or why something is better than something else.
You need to be methodical and have attention to detail, keeping track in your mind where you are at and what you need to do next.
Most good software engineering interviewers you will encounter will be trying to get to the root of this ability and ascertain its maturity against the level of the role. After all, code is just the medium of expressing your problem-solving ability.
It also involves a good level of patience and focus. Software engineering drives even the most experienced devs to want to give up on some problem sometimes, so if you easily give up, you are probably going to need to find more resolve from somewhere. There are going to be times when the solution seems out of reach, and you need to think through logically what to do next (but having a quiet scream to yourself in the garden now and again is totally normal).
When it comes to professional software engineer roles, problem-solving also includes being able to be pragmatic about the work to meet deadlines or other constraints.
I’m stretching the definition even further here, but in a real software company, you will be working with many human beings to build software. Well-functioning software companies have a very high level of collaboration that might even seem unusual to people in other industries. Problem-solving in enterprise software is therefore distributed.
Having good communication is as important as coding when it comes to being a good software engineer. You should always be open to changing your mind, avoid being defensive and also admit mistakes! Taking such personal accountability advances your career and standing in a good software company hugely. Be diplomatic, reflective, transparent and actively participate in discussions. Prioritise building trust with your fellow engineers. Being this way ultimately gets the problem solved more seamlessly.
Just try it
There is pretty much nothing stopping you picking a language, following a decent guide and firing up your editor. That is what matters. Find out if you even like coding. Don’t put barriers in front of yourself and and don’t try to learn in an up-front passive way.