How My Early Struggles Shaped the Developer I Am Today
Introduction
Let me start with a personal story about my career.
I started my career at a small product company. The company itself was relatively small, but the product was not. It was a large system that managed access and identity, ensured compliance, and automated internal processes in big companies — from hiring an employee to managing their departure. Most customers were banks and insurance companies — very large enterprises — so the cost of an error was high.
The system had already existed for 15 years and had grown significantly. I had just started coding full-time and began receiving my first assignments. On one hand, I was living my dream: I was programming and getting paid to do it. On the other hand, everything was so complex it felt overwhelming. But there was a whole team building features, so I thought: it has to be me. No problem — I just need to work harder. I just need to learn more. That was true then, and it is still true today.
After about a year, I had already written my first features for a big client, but the complexity was still overwhelming. The worst part was that there was no quick way to find out if I had broken something, because the company relied on manual testing. You would write a feature, wait a couple of months until QA had time to test it, and by then you had already forgotten the details. After testing, it would take another few months to release. It felt incredibly stressful, slow, and exhausting. I started thinking that maybe programming was not for me.
Then I was assigned a project to introduce Team Foundation Server (similar to GitLab or GitHub) into the company. Through that project, I learned for the first time that you can build pipelines, run tests automatically, and get fast feedback. At that point, I realized automated tests were important — and pretty cool. If I pushed changes, I could quickly see whether I had broken something.
The only problem was: there was not a single automated test in the codebase.
Naively, I thought I had found the solution to many of our problems. We could build pipelines, automate the entire build and release process, and start writing tests. So I created a presentation about all the cool things we could do to improve our work.
By now, I know it is not that easy.
Of course, a junior developer explaining to senior engineers how they should change their way of working was not very well received.
At that point, I knew that if I stayed, I would not be allowed to change the way we worked — or even the way I worked. But working like that made me hate my job and my work.
So I left the company.
On my new project, we had a nearly greenfield system. We were a small team, and the product was at the very beginning. As it later turned out, I was the most experienced developer on the project. You might think that is a good thing. The only problem was that I had just two years of experience.
My experience from the previous project was still very fresh, and I quickly understood that if I did not make things better here, we would end up in the same situation very soon. Luckily, my colleagues and management were very supportive — and I am still grateful for that to this day.
So there I was. I knew I had to write tests. I had to keep the architecture clean. But how?
I started writing unit tests. It was hard, but I was motivated. Within a couple of months, we already had some tests. My teammates started writing unit tests too. Overall, I felt very positive that we would eventually build a comprehensive test suite.
After we had a few hundred unit tests, I started noticing that some tests were being deleted by my colleagues. I was frustrated. I thought they did not understand — or that they were lazy.
So I asked why there were fewer tests than before.
One teammate said: “Well, I made some changes and all the tests turned red, but the system worked fine. It was just refactoring.”
I looked at it, and he was right. It was not a bug — it was just refactoring. In that case, we needed to adjust the tests. But it felt like additional, unnecessary work.
The second argument was that these tests were useless because they were not catching any bugs, and that we should write more end-to-end tests instead — because those were actually catching bugs.
I had just read Clean Code and was convinced we needed to write unit tests, not just end-to-end tests. So once again, I was frustrated with my colleagues.
When I started working on more and more features after completing some infrastructure improvements, I began to notice something unexpected: the unit tests I had written were becoming more of an obstacle than a help.
When I first implemented a feature together with its tests, everything worked fine. There was no issue. But the moment I needed to make changes, the tests had to be modified — or even deleted. I realized that I was doing exactly what my colleagues had done before: disabling, removing, or rewriting tests. The unit test coverage was getting worse, not better, unlike in the beginning.
It was even worse than that. My colleagues had already formed their opinion about unit tests. Based on their experience, they were convinced that unit tests were not very useful and were painful to maintain. Luckily, we had pretty good end-to-end test coverage, and we had made those tests stable enough to rely on them.
I was quite happy with my job, but I felt it was time for something new. I wanted more ownership and more control over a project. So I joined a company where I would be the first programmer. Naturally, this gave me the opportunity to use all my previous experience and do things better this time.
I knew what had not worked in the past. I knew the pitfalls. But what I was lacking was the “how.”
That is where Unit Testing: Principles, Practices, and Patterns helped me tremendously. I was so hungry for knowledge that I preordered the book and read it as soon as it was released. It answered the questions I had struggled with for years — not just how to write tests, but how to write them in a way that brings real value.
For example, I learned how important it is to optimize tests for resistance to refactoring — and how to actually achieve that. I learned what to mock and what not to mock.
This time, we built a truly valuable test suite. I could confidently push to production if the pipeline passed. It was so much easier — and so much less stressful — to work that way.
After a couple of months, a new colleague joined the team. This time, it worked differently. I was writing tests, and my colleague started writing them too — without me even asking. At some point, I noticed that it was actually easier to start with a test first. Naturally, we developed a TDD-like workflow.
It was a joy to work on that project.
This whole experience shaped my principles, my way of working, and my work culture.