This is an almost-true story about a young passionate developer. It was the late 2004 and he had just started working in a small company offering everything he desired: a good salary, working with his preferred programming language, approaching complexities, and modeling architectures.
This was not the first working experience of the young developer. But his very first project had proven to be problematic. At the time he believed features would never change. But he was wrong, and every feature change would require a complete refactoring, causing bugs and an enormous wasting of time. He had tried even some virtuous approaches like writing tests. But his tests required maintenance, and time to be written, and even more time to be executed.
As every young developer, he was growing up listening an experienced developer who used to say “watch out! premature optimization is evil!”, and then “write tests! tests! tests!”. Maybe he was just refactoring a small utility method when the experienced developer would come to him with a stern look warning “you’re not doing premature optimization, are you ?”, or “are you writing tests, right ?”.
But all these warnings were falling on deaf ears. Because the young developer couldn’t understand why premature optimization should be evil and tests should be good. From his own previous experience he knew that following specifications doesn’t work in the long run (because they tend to change), and writing tests was a wasting of time.
"Why on earth do I have to rewrite my code every time ? Why on earth do I have to write the code now and refactor it later, when I can write the best code in the world right now ? And why, why on earth do I have to spend all my time writing useless tests ?" was wondering the young developer.
One day, the young developer started working on a new project. He decided to ignore the experienced developer warnings; he wanted every piece of code to be fast, configurable, and robust, to overwhelm every specification change. Specifications were clear, but he would go beyond them. For example, when the feature was to build a product code ending with an uppercase ‘S’, he created a configurator object so that the ending letter could be decided via configuration, and via configuration could also be decided if the letter should be uppercased or lowercased.
When faced with the need for specific validations, he designed an extensive validator capable of handling not just the specified requirements but much more.
Upon completing the core of his project, a sense of perfection washed over the young developer. With triumph in his eyes, he exclaimed, 'The seasoned developer was mistaken!' He dedicated endless days and nights to perfecting his creation, which eventually saw its production release a few weeks later.
One day, the customer reported a bug to them. The seasoned developer examined the issue, only to be horrified by what appeared on the monitor. Where the young developer had envisioned a cathedral, the experienced developer found a slum. What seemed like patterns to the young developer appeared as an intricate network of classes to the experienced one. The seemingly faster-than-light code was, in reality, a convoluted mess of unnecessary complex algorithms. The experienced developer had no inclination to tackle such a daunting task. Reluctantly, he requested the young developer to resolve the bug on his own.
The only idea that his code was not considered beautiful by others made the young developer upset. He opened the project, full of rage… only to discover that the code was incomprehensible to him as well! There was no clear meaning behind the code. “This is why I’m not using this language anymore. It has an ugly syntax” was the first reaction of the young developer. But he knew deep down that this wasn’t the real problem. The real problem was him.
At the end of the day the bug was fixed, only to generate another bug, discovered the day after. Every fix was altering the thin balance inside the project, like a small black patch on a shiny white dress.
The young developer was now hopeless. His cathedral had begun to falter, and he felt the collapse was imminent. “Maybe I’m not the right person for this job. Why cannot I write code the right way ?” the young developer asked himself. In a mixture of depression and angriness, the young developer opened a project maintained by the experienced developer.
He was astounded by what he found: the code was incredibly readable, filled with comments and thorough tests. It reminded him of the code he used to write in his early days, with a few distinct differences. There were no overly complicated configurations; each line of code was meticulously tested, every method had a meaningful and concise name (limited to a maximum of ten lines of code), and each method performed only what was necessary. Furthermore, every file contained precisely the methods required for its designated task.
In that moment of dejection, the experienced developer approached the young developer. While sitting close to him, he started to refactor the code that was causing all those bugs.
They worked together for days, at times the experienced developer was writing and the young one watching at how the experienced developer was solving problems; on other occasions the young developer was writing and the experienced one supervising.
A few days later a new deploy marked the bug as fixed. The small portion of code that was causing bugs was now tested, easy to read, and stable. The experienced developer looked at the young one: “Do you understand now?”.
The young developer nodded. He was getting it now. The key to perfection wasn’t to predict the future, but to write code that could be easily changed, tested (so that a change would not cause any bug), and that fulfilled only the current requirements. And while he was realizing this, he noticed he was changing, he was becoming the almost experienced developer.
"Can we now refactor the entire project?" asked the young developer.
"Surely not! There’s no budget for that" flatly replied the experienced developer.
"But what if other bugs appear?" asked the young developer.
"We’ll call a freelancer to fix that shit" replied the experienced one.
And then, the almost experienced developer started writing good code, ready to learn one other lesson. But this is another story.
Moral for the young developer: Keep looking back at the code you wrote in the past, and don’t feel disappointed if your code doesn’t look beautiful as it used to be.
Moral for the experienced developer: When there is a young developer around, you’ll have to handle some of his shit. Your best chance is that sooner than later he will learn how to write decent code.
Moral for the freelancer: You might as well raise your rates :