Junior Software Engineer Essentials
Your first steps as a junior software engineer can be quite overwhelming. Probably your first permanent job, encountering lots of technologies which you haven’t seen yet, and getting to know colleagues of which most seem way smarter then you are. So, where to start?
Progressing from junior software engineer to the next level will take time, dedication, processing feedback from peers and focussing on the right things at the right time. Just be aware that you’ll never truly master software engineering, as the more you’ll learn, it will become obvious that there’s still a ton of things you don’t know. And even in the skills you’ll already have, you’ll find ways to improve them even more.
What defines a junior software engineer?
In any role it’s important to know what exactly defines that role. It comes with a set of expectations, benefits and a progression path.
As a junior software engineer, the expectation is that you can complete a well defined task with the supervision of your colleagues or team lead. The architecture work should’ve been done up front by more senior developers, so that you have a clear path for implementation. Over time, you are expected to do some design work on components you maintain, but generally you won’t have to do any cross-component design work (yet). Also, you are expected to verify the quality of the code and solution you deliver and to perform bugfixes where necessary.
The benefit of being a junior software engineer? There’s no pressure to finish a task within a limited amount of time. People will expect that you need more time to complete a task, so you probably get assigned tasks with lower priority. This should give you time to focus on improving quality, as that is one of the expectations that come with the junior role. That won’t be perfect right away, but don’t worry, you’re only expected to make steady progress on your basic skillset and to learn from your mistakes. And you will make mistakes, but that’s not an issue, you will (or should) be guided in how to fix them and avoid them in the future.
As for the progression path, that one’s pretty straightforward. Moving up to mid-level developer generally means to become more autonomous. Expect to be in the junior role for about 2 to 3 years.
Quality, quality, quality…and did I say quality?
As a junior engineer you might want to prove yourself by finishing your tasks as fast as possible. But really, quantity is not what you have to prove and deliver, but quality is. Quality comes in two flavors: craftsmanship and discipline.
This is basically about having the discipline to perform the most basic quality checks, which don’t require too much experience to get right. Things like making sure that the code compiles, pull requests don’t contain leftover changes that you needed during debugging, unit tests aren’t broken and that you’ve manually tested and verified your feature in a test environment. Try to get this right quickly. What can help here is just writing down all those verification checks and applying that list before asking for a review, so that you don’t forget any.
Software craftsmanship is a never-ending effort to deliver quality code and features by applying a good code style, design patterns, best practices, automated testing, documentation and experience. This is your start in this journey, so it’s normal that you will get quite a bit of feedback on this by more senior developers, leading to lots of iterative work to apply that feedback. Gradually, you will get better and better at this. Teams will (and should) have quite a bit of patience with you while you try to improve on these skills.
Two books from which I learned a lot in terms of how to deliver quality and which I consider an essential read are:
- Clean Code: A Handbook of Agile Software Craftsmanship by Robert C. Martin
- The Clean Coder: A Code of Conduct for Professional Programmers by Robert C. Martin
Pro Tip: Focus on quality early and take your time to iterate and get it right. As a junior you should get the space for this, so use it!
A stable environment is important early on in your career, because it allows you to work on your skills. You can typically find this in bigger projects and teams, were you are supported by more experienced developers who can guide you with tasks and coach you in your progress.
Pro Tip: Focus on a limited set of technologies/languages and try to master them.
Because everything is new, it’s easy to try and chase every exciting technology you encounter. This will give you the feeling that you’re learning a lot, but generally it will be superficial knowledge about how a framework or library works. I would suggest to select one, or at most two (if you’re working full-stack) languages and use these as a basis to learn about writing quality software, best practices, refactoring and automated testing. Not everything will translate one-to-one to other languages, but most of it will.
Pro Tip: Frameworks can help you, both to be productive quickly and to have a structured way of working without having to think about all the complexities (yet).
Frameworks can be very complex if you want to get the most out of them, but can also be very friendly for those early in their software career. Certainly the opinionated frameworks give you a predefined structure and allow you to ignore most of the complexities that exist under the hood.
Automated tests are another cornerstone of delivering quality code and features. Unit tests make sure that isolated blocks of code logic work as you expect them to, while integration tests make sure that your component’s feature works as it should without having to deploy it somewhere. Initially learning to write these tests, and writing them properly (which is an art on its own), will take time and it will slow you down. But gradually you’ll notice that they give you confidence and that they accelerate your development cycle. You’ll notice that, if you’ve written some proper integration tests, that once you deploy the component to a development cluster that it will magically work. Refactoring code will go much smoother and your tests will work as a safety net.
One book on automated testing I really enjoyed was Growing Object-Oriented Software, Guided by Tests by Steve Freeman and Nat Pryce. It goes into TDD (Test Driven Development), but don’t let this scare you. There are plenty of good takeaways from this book that you can apply in any form of unit or integration testing. I’ve never practiced true TDD, meaning always writing tests first and the implementation afterwards, but I still apply many lessons I’ve learned from this book almost daily.
Chances are, that code you wrote the first time won’t support some new features that need to be added a couple months later. You can try to hack it in, but this leads to something we call “technical debt”, and the debt collector will eventually come. So instead it’s better to rework that piece of code such that it does allow to neatly integrate that new feature. By doing this consistently, and taking a minor hit in time spend per task, you avoid that suddenly you have to perform a change-the-world refactoring for what otherwise would be a rather minor feature.
Pro Tip: Refactoring code is a standard part of being a software engineer, and one of the primary ways to combat technical debt.
I can highly recommend the Refactoring: Improving the Design of Existing Code book by Martin Fowler, Kent Beck, John Brant, William Opdyke and Don Roberts. It gradually learns you how to refactor code. The examples are in Java, but most of these techniques can be translated to other languages as well.
Maybe not the most favorite thing for developers to do, but nonetheless a very important aspect of software development. Try to focus here on providing a quality readme for your components and to document the code itself with comments. I’ve got another article on the the art of developer documentation which goes more in-depth on how to write quality technical documentation.
Asking questions and feedback
Nothing’s worse then starting a task and not fully understanding the goal of the task. Therefore it’s important to keep asking questions until the task is clear, both functionally and technically. Certainly when you’re new to the project, it might seem like you have to ask an excessive number of questions, but this shouldn’t hold you back from exactly asking those questions. When you think you understand the task fully, try to explain it to others to verify that’s the case.
This feedback loop shouldn’t stop once you start the task. Try to ask for feedback early once you have a rough draft implementation or idea.
Pro Tip: Being a junior software engineer gives you a free ticket to ask questions and feedback almost endlessly, so do it early and often!
Also, nothing’s wrong with just saying “I don’t know”. Even as a senior developer you’ll be using that sentence quite often, so don’t be afraid to use it.
Many things can happen while you work on a task. You might get blocked, it might take longer then expected or you need assistance from another developer. Make sure to signal these issues early. Many of these issues might be solvable by simply discussing them with others, or the team can decide to allocate support to help you.
Also, try to articulate clearly what you’re working on, without mentioning too much of the code details (unless really necessary).
When I started out as a junior, I was rather clueless on what it exactly meant to be a junior software engineer and how I could progress my skills. I encountered and figured out most things along the way and luckily had a natural interest to seek out best practices, which brought me to most resources mentioned in this article.
I hope this gives some guidance to software engineers taking their first steps, but also to have this be a helpful guide for those coaching other junior software engineers.