So you've just started your first job as a programmer. You've been working hard to learn everything you need to start, you've sent thousands of CVs, and - finally! You got it! Your first job.
It's your first week. You are after onboarding and you've been given access to the codebase. You're getting familiar with the system and want to write the first feature. So you get to work. You create all of the logic for a new feature. A day or two passes and it's done! Your first commercial code is finished.
You are proud of your work and want others to make use of it. It's time to release the code to production. Or is it?
There is still a long way to go. Writing a seemingly working code is only part of your job. There are many factors crucial in writing good code, which will bring great value to the product.
Wait a second. You want to release your work, but how do you know that the code is working correctly? You can say that it's compiling without any errors and warnings and you traced thoroughly the entire flow ten times with console logging every piece of logic. But does it mean your code won't cause any problems?
Testing the code is a fundamental skill for every developer. It's essential to avoid errors, which often can be very hard to predict. When the codebase is small, it is possible to keep it under control and effectively track every issue, but the fact, that a codebase is small now does not mean it will not grow bigger in the future.
We can divide testing into two main categories:
An automated test is a piece of software that runs parts of your code in a closed environment and matches if the results of code’s execution (e.g., function return value, state) meets the expected outcome.
In manual testing you play the end user’s role, trying to cover as many use cases as possible.
Both approaches help find flaws in your codebase and assess the new code’s impact on other parts of the system. It's not obvious right away, which of them are connected.
Also, don't be scared to experiment on staging (pre-production environment) - even if you break something, it won't affect the end-users and probably it will be easy to fix it. Staging exists to facilitate testing.
With all that new knowledge, you took care of proper code testing (and probably found some new bugs). The application doesn't break while manually testing and every automated test succeeds. You know that your code works and this time, it's not only your hunch! It's finally time to release it to the wide public, right? Wrong!
Your teammate reviewed your code and gave a lot of feedback. Something about possible improvements, slightly different implementations, naming. But why? It works anyway.
Long work on a single feature makes you blind to some flaws in your design and alternative solutions.
Your goal is not only to create code that works. There's a great chance that someone will have to go back to this code in the future and change something. Is it easy to understand and change after a few months? Your goal is to make the code as maintainable as possible. It is important to gather feedback from your teammates. Other developers (not necessarily more experienced ones) can find many mistakes only because they are not affected by your current mindset.
Code review is an excellent way of learning - both for the person reviewing and the person being reviewed. It gives a place to share your knowledge, exchange views and start constructive discussions. The feedback from code review will help you find gaps in your understanding and knowledge and point you in the right direction when learning new skills.
It can also fight our laziness. Sometimes choosing an easier solution is tempting. We need to watch after each other, not write low-quality code.
Writing high-quality code has a lot of advantages. One can say that it slows down the development process, but it's only part of the truth. Writing code quickly and inconsistently with set standards and good practices is usually faster at this very moment. However, every time you take this kind of shortcut, you incur technical debt.
We can define technical debt as the consequences of poorly written code, usually incurred to save time. The longer you will wait to pay it off - the harder it will be to deal with consequences, which include:
- difficulties in implementing new features (slowing down the development process),
- deterioration of work comfort.
Every debt needs to be repaid. If possible - it is better to avoid it at all. Writing high-quality code will make you a better programmer. You will be forced to find the best solutions possible. Often it means seeking additional knowledge that might be needed to do so.
You may quickly discover that the current codebase isn't perfect. That's fine. Always try to leave it a bit better than you found it. Do not always go for a full refactor - it's usually not essential at this very moment. You can correct some minor flaws which you encounter on the fly.
You addressed every advice, every comment that was given to you. You fixed every mistake and improved every piece, which could be better. Now your code is up to every standard. It's perfect. Oh no... Someone just commented that we already have an implementation for what 80% of my code is responsible for.
Usually, you are not the only one working on a codebase. The familiarity of the code and the general domain knowledge is crucial while developing the code further. You can acquire this knowledge in two ways:
- while working on the code - the most "natural" way and also longer-lasting,
- through communication with the team.
Without proper communication, you can waste a lot of time trying to understand the code, its intentions and implementing solutions, which might not be accurate.
It would be best if you also were careful not to make anybody else's day harder. Because other people will have contact with your code, you should, as far as possible, make it understandable, high quality and free of shorthands, which are obvious only for you.
It's essential to consult your changes with other people from your project (or make sure they know what you are doing). They might have knowledge that will point you in the right direction during development. Someone might also await your changes so they can continue their work. That's why it's crucial to keep that person in the loop about the progress.
You are a part of the team, but you should always take full ownership of your code. It's your job to test it and, by no means, you shouldn't blame anyone else if anything goes wrong. "But someone else was checking it" is no explanation.
If it does go wrong - do not fall apart either. Take it easy. Try to find a fix. Take advice from others if needed. Mistakes are an integral part of our work. They will happen and we have to know how to deal with them - it is one of the skills we need to develop. We shouldn't look for excuses. They don't solve any problems. At most, they create new ones.
You will witness "fuckups" and one day be the source of it. Just accept it. Learn from them and improve your skills. But don't treat them like something that should happen. Just find the right balance.
There is a long way from writing a seemingly working code to releasing it to production. Writing is only a part of a programmer's daily work. Aspects like testing, looking after quality or general teamwork are crucial in providing our clients with the best products possible.
Please note that most of the topics covered in this article are explained very briefly. It targets programmers with very little or no experience and its goal is to provide a general idea of how a programmer's work looks without getting into too much detail.