“What Got You Here Won’t Get You There” — Marshall Goldsmith
It took time to build the desk setup visible in the picture. Quite similar to how I have developed as a software engineer in the last 5 years. It took patience and hard work to grow and work with various organizations. I have been part of a wide spectrum of projects and technologies along the way and have recently completed 5 years.
Notice that I am using the term “Software Engineer” and not “Software Developer”. According to Udacity, there is a strong separation:
“The terms Software Developer and Software Engineer, contrary to popular belief, are not interchangeable. A developer knows how to code and may have the technical skills needed to build meaningful products. A software engineer follows a systematic process of understanding requirements, working with stakeholders and developing a solution that fulfils their needs. A Developer tends to work alone. A software engineer is part of a larger team”.
Abiding by the above definition, I call myself a software engineer. In essence, it does not matter so much. All of these roles have loose definitions which for some reason is quite fascinating to me. But the kind of work that I have done and continue to do resonates well with a software engineer. I thought it might be good to take a break and reflect on some of the main lessons I’ve learned in that time that continue to benefit me today.
You and your work should be replaceable
Wait, what?
Did I just say that?
This might sound counter-intuitive but in reality, this is something you should always have in mind while developing software. The software industry is fast-paced and you will soon get a better opportunity that will force you to switch jobs. The person who is going to replace you will thank you if you have designed the system considering that. SOLID principles are solid for a reason. You should always try to abide by them. Also when the system grows it becomes hard to keep track of decisions. That is why It is important to share and write what you know so that the other person doesn’t have to spend a significant amount of time decrypting information from the code.
Question everything, assume nothing
Remember this rule of thumb, whenever in doubt, ask questions about it. It means being knowledgeable about what it really means. Few of the biggest mistakes I’ve made was due to misunderstanding. Sometimes it’s as small as missing out on one of the edge cases thinking that will never occur in real life. Other times its bigger, like expecting another team to fix a specific problem or assuming an entire system works a certain way. In these cases, there is only one mistake and that is making assumptions. Being more explicit and elaborate about problems and solutions will help you curb smaller bugs and issues from the beginning.
Don’t dwell into technologies/frameworks, dwell into core concepts
Technologies and frameworks will come and go, there are so many of them in the market and it can be overwhelming. But they are all built on the core concepts. And if you understand the concepts switching between frameworks, languages and tools, will be effortless. Consider an example of Relational databases, there are so many of them, but if you understand the underlying principles, like ACID properties, indexes, transaction management, concurrency, you will not have to worry about the number of databases that are available.
People around you matter a lot
For a full-time job, you spend at least eight hours a day working, five days a week. That is a significant amount of your life. That means the people you work with have an incredible amount of influence over you and your overall happiness. The best teams I’ve worked with are the teams who I genuinely enjoy spending time with regardless of what we were working on. This means that I care a lot about who is getting hired to work in the team, who would eventually become my team-mate.
“Work with people where you feel a bit insecure” — Sundar Pichai, CEO of Alphabet and Google
When we’re open to learning from others, we benefit from their experience as well as our own and we can inherit their wisdom and knowledge. The people we surround ourselves with are the biggest influence on our behaviour, attitudes, and results. When we stay with someone for a while, we tend to inherit their habits. Sometimes deliberately and sometimes automatically. And that is why it is very important to take that into consideration when switching jobs. Not just title and salary.
Be a problem solver, not just a programmer
Growing as a software engineer requires you to understand that programming is just a tool. Recognize that your ability to write code is a tool in your toolbox as a problem solver. Because you are a problem solver first. Learn to recognize the most important problems in front of you, and be ready to apply different perspectives to solve the problem. Do not only apply the programmer’s perspective. You have to learn to take a holistic view of the system in front of you!
Referring to the definition of “Software Engineer” described in the beginning, you have to take a lot of things into consideration so that your user/client can benefit from the application/solution that you are providing.
Work at your own pace
Jeff Bezos’ view on work-life balance:
“If I am happy at home, I come into the office with tremendous energy. And if I am happy at work, I come home with tremendous energy.”
Don’t bite off more than you can chew. Everybody is different and is motivated for different things in life. You have to figure out your motivation. Do not follow what others are doing around you. Find your balance in life and work towards achieving that. It is important if you want to stay here for long. You have to consider this as a marathon. Run at your pace, take breaks and enjoy the journey.
Avoid destructive mindsets
There are plenty of things that can stifle you on your path to becoming a good software engineer, and often they are states of mind that can be difficult to recognize because they are internal and part of you. And there’s one thing I learned since I started programming, it’s that all unsuccessful developers typically share similar traits. Sometimes knowing what to avoid is more important than knowing what to do. For example, saying yes to everything.
Code without test is your biggest enemy
Writing tests is very important and better yet, learning to write tests before code is a cherry on top of that. A lot of programmers find the idea of writing tests before writing code absurd. They think that it is not useful and slows down the development process. In a sense, that is correct and it does impact the speed of development. But the speed of development would hardly matter if your system is not resilient.
An engineer’s job is to deliver code that is not only functional but readable and maintainable. And Test-driven development helps you do that.
According to Martin Fowler, TDD is:
- Writing a test for the next bit of functionality you want to add.
- Writing the functional code until the test passes.
- Refactoring both new and old code to make it well structured.
One of the most important aspects of TDD is that it shifts the focus to WHAT of a problem from HOW. And that is a mindset that will help you grow as a software engineer. Consider reading this if you are looking for an example implementation of TDD.
Become a collector
Well, this is going out of context, but hear me out. I mean collecting the resources that you stumble upon. Blog posts, videos, talks, and everything in between, save them and organise them in a way that can be used at a later point in time.
The above image is just an example. You can find better ways of managing it. You will definitely solve a problem multiple times, or implement the same solution multiple times, instead of looking around the internet on how you solved it in the first place, this will come in very handy.
Dig deeper, the devil is in the details
Recently I was working with Hibernate and Kotlin. I bumped into a problem where it was not possible to use data classes to create entities. I struggled for sometime before actually finding a nice article that explains the problem and the possible solution. And instead of jumping quickly to the solution and implementing it to my problem, I started digging deeper. I observed that there are a lot of libraries that have similar problems because of the compatibility issues with Kotlin. Next time when I see something like that I can quickly go through that article to refresh my memory and be done with the solution.
Try to dedicate your time towards understanding the internal working of different libraries and frameworks that you use. This will help you relate different frameworks, and understand why one is better than the other. You will start forming opinions on which one to use in a given situation. And when you see some new framework, you will be able to learn it quicker. The pace at which the industry is evolving this habit will help you stay relevant for years to come.
Final Thoughts
Being a good software engineer is hard, and it takes time to understand why. I have shared insights from my experience. There is no perfect recipe for success and you have to keep evaluating different options and ways to achieve it. But one thing to keep in mind is that you have to be very critical about yourself. Ask for feedback from people around you and change what is not working. You have to continuously redefine yourself.