
Recently, I conducted an interview with a JavaScript developer applying for a senior position. A colleague, who was also present at the interview, asked the candidate to write a function that would make an HTTP request and, in case of failure, retry several times.
He was coding directly on the board, so it would have been enough to depict something approximate. If he had just shown that he understood the essence of the task, we would have been quite satisfied. But, unfortunately, he struggled to find a successful solution. So, attributing this to nerves, we decided to ease the task a bit and asked him to convert the callback function into a promise-based function.
But alas. Yes, it was clear that he had encountered such code before. He had a general idea of how it all worked. A rough sketch of a solution demonstrating his understanding of the concept would have sufficed. However, the code he wrote on the board was complete nonsense. He had a very vague notion of what promises are in JavaScript and could not adequately explain their purpose. For a junior developer, this might have been forgivable, but for a senior position, it was not acceptable. How could this developer fix bugs in a complex promise chain and explain to others what he had done?
Developers consider the finished code self-evident.
During development, we constantly encounter reproducible materials. We copy code snippets so that we don't have to rewrite them from scratch each time. Accordingly, focusing all our attention on the key parts, we view the finished code we work with as something obvious – we simply assume that everything will work as it should.
And usually it does work, but when difficulties arise, understanding its mechanics pays off immensely.
Thus, our candidate for the senior developer position considered promise objects to be self-evident. He probably knew how to manage them when they appeared in someone else's code, but he did not grasp the overall principle and was unable to reproduce it during the interview. Perhaps he memorized a snippet by heart – it's not that difficult:
return new Promise((resolve, reject) => {
functionWithCallback((err, result) => {
return err ? reject(err) : resolve(result);
});
});I did that too – and we all probably did it at some point. We just memorized a piece of code to use it later at work, having only a general idea of how everything was structured. But if a developer truly understood the concept, they wouldn't have to memorize anything – they would just know how to do it and effortlessly reproduce everything necessary in the code.
Go back to the sources
In 2012, when frontend frameworks had not yet taken over, the world was ruled by jQuery, and I read a book , authored by John Resig, the creator of jQuery.
The book teaches the reader how to create their own jQuery from scratch and offers a unique opportunity to understand the thought process that led to the library's creation. In recent years, jQuery has lost its former popularity, but I still highly recommend the book. What struck me the most was the persistent feeling that I could have thought of all this myself. The steps outlined by the author seemed so logical and so clear that I genuinely felt like I could easily create jQuery if I just set my mind to it.
Of course, in reality, I would never have managed anything like that – I would have decided it was impossibly difficult. My own solutions would have seemed too simple and naive to work, and I would have given up. I would have viewed jQuery as something obvious, whose correct operation needs to be accepted blindly. Subsequently, I would hardly have spent time delving into the mechanics of this library, but would have simply used it as some sort of black box.
But my acquaintance with this book changed me. I began to delve into the source code and discovered that the implementation of many solutions is actually very clear, even obvious. Of course, coming up with something like that on my own is a different story. But it's precisely the study of someone else's code and reproducing existing solutions that helps us come up with our own ideas.
The inspiration you draw and the patterns you start to notice will change you as a developer. You'll discover that the beautiful library you constantly use, which you’ve come to think of as a magical artifact, operates not on magic, but simply solves a problem in a concise and ingenious way.
Sometimes you have to toil over the code, breaking it down step by step, but it is through these small, incremental steps that you can retrace the author's path to a solution. This will allow you to dive deeper into the coding process and give you more confidence in finding your own solutions.
When I first started working with promises, it felt like pure magic. Then I learned that they are based on the same callbacks, and my programming world turned upside down. So, a pattern designed to free us from callbacks is itself implemented with callbacks?!
This helped me view things from a different perspective and realize that what was before me were not some abstract pieces of code with an complexity I would never grasp. They are simply patterns that can be understood with curiosity and deep engagement. This is how people learn to program and grow as developers.
Reinvent the wheel
So feel free to reinvent wheels: write your own code for data binding, create a homemade promise, or even build your own state management solution.
It doesn’t matter that no one will ever use this – now you know how to do it. If you later have the opportunity to apply these developments in your own projects, that’s just great. You’ll be able to build on them and learn even more.
The point here is not to deploy your code to production, but to master something new. Implementing an existing solution by yourself is an excellent way to learn from the best programmers and hone your skills.
Source: habr.com
