Being a software engineer is the greatest career there is. Period. Combining aspects of engineering by using battle-tested best-practices, approaches, and frameworks with the beauty of art by creating something unique. Add in the ever-evolving toolbox and endless opportunities to learn new things and… well…I cannot imagine doing anything else.
This is a long overdue love letter to software engineering. A love letter in which I share my perspective on what makes a great software engineer and talk about my own career and choices I made. Which I hope can be insightful to other engineers, but at the very least is an entertaining read.
Becoming a great software engineer
I’ve always had a passion for technology, computers and building networks using old computers my dad brought home. My love for software engineering truly kicked in a little later and I started working full-time as a software engineer straight away after getting my higher vocational education (HBO) bachelor. That was about thirteen years ago.
Thirteen years of hard work, practice, and learning with the goal to become a great software engineer. Throughout that time, as I grew as a person and a professional, my understanding of what it means to be a great software engineer evolved. I feel there are four essential skills that form the foundation: problem solving, passion, curiosity, and teamwork.
The art of problem solving
A key skill is problem solving. Which takes two things. First one is being able to decompose a big problem that’s highly complex into smaller problems that are more manageable and easier to understand. The second one is being able to solve these problems using programming languages, libraries, design patterns, design principles like solid and grasp and other existing techniques and structures that are commonly understood.
It takes years and years of hard work, practice, lots and lots of conversations and learning from mistakes to build a strong solutioning skillset. The best solution to a problem is one that is easily understood by others. Code is not written for the compiler, but for other people. Being able to open an application and understand the intent, the structure and the design philosophy allows you to become productive quickly and build on the existing code in a clean and maintainable manner.
The importance of passion and curiosity
A good software engineer will have a strong passion for coding and a natural curiosity to continuously push themselves to learn. A true sense of craftsmanship. A certain perfectionism and pride in the code they write. Their code must be clean, elegant, and easy to understand so that it can be maintained and extended, rather than “just work”. They apply the boy scout rule “always leave the code a little better than you found it” and consider refactoring a core part of their work. This sounds like a romantical version of the truth, and a professional environment is not without compromise. There is always some degree of technical debt present code bases and there is delivery pressure. But a good software engineer always pursue quality and balance it with commercial interests rather than letting the codebase relentlessly deteriorate.
A software engineers’ natural curiosity will be a determining factor in their growth. Besides the obvious learning from blogs, vlogs, meetups, conferences and looking at open-source codebases on Github, you learn from and get inspired by the people around you.
Even on concepts you think you have a good grasp on, never close yourself off from the opinions and perspectives of those around you. Let me illustrate with a personal example on unit-testing and refactoring.
I was working with a senior software engineer, who even more so than me, was extremely passionate about clean code and used frequent refactoring to ensure a healthy codebase. I was initially surprised to learn that he was not the biggest fan of traditional unit-testing. So, we had a conversation about it. His perspective was that unit-tests are often highly coupled to the internal structure of a software module as you search for the smallest piece of code that can be logically isolated. As a result, refactoring often requires unit-tests to be re-written or adjusted. This means that refactoring becomes more time consuming and is therefore done less often which negatively impacts the health of the code base.
What he preferred to do instead, is write automated tests that focus on the public interface of a software module, rather than the internals. Approaching it this way, he had more freedom to refactor the internal code for a module without impacting the tests. And in the end, he felt that the stability of the public interface should be the primary concern.
I personally like to position this approach between traditional unit-testing, which is focusing on the smallest piece of code that can be logically isolated, and integration testing in which software modules are combined as tested as a group. He was aware that pinpointing the cause of a broken test a bit less instantaneous as more code is executed as part of a single test. He felt this to be a very acceptable tradeoff for having more freedom to refactor.
This was a great conversation; It gave me a new perspective and I love talking to others that have the same passion and drive for building the best possible software.
To some, this section might read like an overly romantic view of software engineers. With the high demand for software engineers in the market today I certainly believe that there’s a percentage that don’t prioritize clean code, refactoring or learning as many design patterns as they can. I have no control over that. All I can do is share what I believe to be an incredibly fulfilling and worthwhile pursuit of excellence in doing something that you love.
Software is built and maintained by teams. The ability to collaborate well in a team is important. The potential of a software engineer is not purely based on technical ability, there’s also emotional and interpersonal skills.
Cultivating good teamwork, inspiring, and raising those around them is a clear sign of great software engineer. It also exposes them to different approaches and perspectives, like the example I shared earlier on unit-testing. So, the benefits are bilateral.
Looking at my own responsibilities and priorities now, there’s a big emphasis on teamwork with me leading engineering teams, coaching engineers and designing solution architectures together with these teams.
Do I have regrets about the choices I made?
I somewhat regularly get asked if I regret “stepping away” from coding. It’s a fair question, and the honest answer is No. Well sometimes. A little.
The choice is largely driven by the way that the working environment shaped me as a person. I grew on projects with a small team having end-to-end responsibility. In that context well-rounded engineers are generally able deliver more overall value than if they choose to dedicate themselves to the pursuit of truly excelling at one thing.
It also provided me with the perspective that there’s more to quality than the code written by myself as an individual. Quality is driven by controlling the entire delivery process as best you can, as well as establishing good teamwork and fostering the right culture. So rather than committing to becoming the best possible coder, I committed to making the biggest possible impact on quality by building a strong T-shape knowledge profile. This means I have built a few well-developed core skills (deep skills) like coding but augmented by a strong set of supporting skills outside that core area (broad skills) that span the software delivery process.
And while I didn’t start my career with the ambition to become a mentor or leader, over the years I build great appreciation for it through the support of amazing people that enabled me to fall in love with software engineering and supported my development as a professional and a person. Over time I started feeling that with my passion for software engineering, I could support other engineers cultivate their passion for the craft as well as create the right atmosphere and culture to engineers to thrive. I recently read a quote that said: “be the senior engineer you needed as a junior” and that’s what I try to do daily.
So why did I say I do sometimes miss coding a little? Well, because I do. Most of the coding that I do are quick spikes to understand important things beyond just the conceptual level. While it’s certainly loads of fun, in all honesty, it is quite different. Those codebases don’t require an ongoing focus on clean code, refactoring or managing technical debt. It doesn’t require the same attention, love and nurturing that really scratches my craftsman itch.
However, I do find that I am able to scratch that itch with solution architecture. Code and architecture are connected and evolve together to deal with additional (non) functional requirements. Both, on their own level of abstraction, strive to decompose complexity and achieve loosely coupled, highly cohesive components. They both aim communicating intent to others using recognizable structures, patterns, and naming. So, the challenges provided are more similar than most realize.
To me, coding, and solution architecture both belong in their own s-tier, triple diamond rank bracket. As equals, as brothers. There is literally nothing that comes close for me, and I feel blessed to have such a passion for my profession. I am still as much in love with software engineering as I was ten years ago. And I doubt that will ever change