
Theory instead of heuristics: getting better as frontend developers
- Transfer

Translating Becoming a better front-end developer using fundamentals instead of heuristics
Our experience shows that non-technical developers and self-taught people often rely not on theoretical principles, but on heuristic methods.
Heuristics - patterns and proven rules that a developer has learned from practice. They can work imperfectly or in a limited way, but to a sufficient extent, and do not require serious thought. Here are some examples of heuristics:
- “Use
$(document).ready(function(){})
to initialize code on jQuery sites” - “A construct is
var self = this
needed to call a method in a callback function” - “Arrow functions do not have operators
return
”
At the same time, the theoretical principle can be used to find solutions to other problems. He is invariably faithful and often determines the very device of one or another element. Theoretical principles include, for example:
- The official syntax for arrow functions
- Lodash API Documentation
- Rules of use and functions vertical-align
Please note: we quoted only heuristic examples in order to emphasize the artisanal nature of the heuristic compared to the rigor of the theoretical foundations. None of the heuristic examples is universal for all cases, but they work in a sufficient number of situations so that the developers who use them receive working code without a full understanding of its operation.
Arguments for a Theoretical Approach
We often came across the fact that developers without technical education are not inclined to solve problems using theoretical principles. As a rule, this is explained by the fact that at the beginning of their careers they did not have the opportunity to learn them, and since heuristic methods work satisfactorily, they continue to use them.
However, despite the apparent complexity, learning a theory can be very useful. What for? Then, that theory will allow you to feel confident that your solution works, as well as independently display answers to new questions, without having to look for someone else's solutions. In the short term, heuristic algorithms may seem like a simple and quick solution, but they will often lead to imperfect solutions - if at all.
In addition, relying on heuristic methods, you will never learn how to solve problems for real. You may often manage to find a working solution, but sooner or later you will come to a standstill, from which you will not see a way out. C & P programmers rely on heuristics in their work.
Developer Skill Level Criteria
When interviewing frontend developers, we set a programming task for them and say that they are free to use any sources, be it Google or Stack Overflow. In this way, it is easy to determine if the developer is an adherent of heuristics or theory.
The former, without exception, copy code from more or less suitable examples with Stack Overflow. Only when the code does not work as planned did they begin to fine-tune it for themselves. Often they fail.
The latter tend to look for answers in the API documentation. There they find information about how many parameters a particular function takes, or the specific syntax of the expanded form of the desired CSS property.
Already in the first five minutes of the interview you can determine exactly what type of programmers the candidate belongs to.
Example
Take Bill as an example. He completed several training courses, solved a number of tasks in JavaScript and wrote websites in his free time, but he didn’t really learn JavaScript.
Once Bill comes across an object like this:
const usersById = {
"5": { "id": "5", "name": "Adam", "registered": true },
"27": { "id": "27", "name": "Bobby", "registered": true },
"32": { "id": "32", "name": "Clarence", "registered": false },
"39": { "id": "39", "name": "Danielle", "registered": true },
"42": { "id": "42", "name": "Ekaterina", "registered": false }
}
Such an object can display a list of users and whether they have registered for a particular event.
Suppose Bill needs to retrieve a list of registered users. In other words, filter them out. He came across code in which the method was
.filter()
used to filter the list. So he tries something like:const attendees = usersById.filter(user => user.registered);
And here is what he gets:
TypeError: usersById.filter is not a function
“Some kind of nonsense,” Bill thinks, because he saw the code in which he
.filter()
worked as a filter. The problem is that Bill relied on the heuristic method. He does not understand that
filter
- a method defined on arrays, whereas usersById
- a regular object that does not have a method filter
. The confused Bill googles the “ javascript filter ”. He finds many references to arrays and understands what he needs to turn
usersById
into an array. Then, by asking “ javascript to turn an object into an array ”, he finds examples using Stack Overflow Object.keys()
. After that, he tries:const attendees = Object.keys(usersById).filter(user => user.registered);
This time the error is not displayed, but, to Bill's surprise, the field
attendees
remains empty. The fact is that it
Object.keys()
returns the keys of an object, but not its value. In fact, the name of a variable is user
easily misleading, since it is not an object user
, but an identifier, that is, a string. Since the attribute registered
for the rows is not defined, filter
regards each record as false, and the array leaves empty. Bill takes a closer look at the Stack Overflow answers and makes the following change:
const attendees = Object.keys(usersById).filter(id => usersById[id].registered);
This time the result is better
["5", "27", "39"]
. But Bill wanted to get visitor objects, not their ID. To understand how to filter visitors, annoyed Bill searches for a “ javascript object filter ”, examines the search results for Stack Overflow and finds this answer with the following code:
Object.filter = (obj, predicate) =>
Object.keys(obj)
.filter( key => predicate(obj[key]) )
.reduce( (res, key) => (res[key] = obj[key], res), {} );
Bill copies these lines and tries:
const attendees = Object.filter(usersById, user => user.registered);
Everything works - although it is not clear why. Bill does not understand what is needed
reduce
and how it is used. Moreover, Bill does not understand that he just defined a Object
new non-standard method for the global object . But Bill doesn’t care - it works! The consequences are not of interest to him yet.
What did Bill do wrong?
Bill tried a heuristic method to solve the problem and ran into the following problems:
- Using
.filter()
on the variable, Bill got itTypeError
. He did not understand that he wasfilter
not defined on ordinary objects. - He applied
Object.keys()
it to “turn an object into an array”, but this alone did not bring any results. He needed to create an array of object values. - Even after receiving the values and using them as a condition for filtering, he received only identifiers instead of the user objects associated with these identifiers. This is because the filtered array contained an ID, not user objects.
- Over time, Bill abandoned this approach and found a working solution on the Internet. Nevertheless, he still did not understand how it works - and will not waste time sorting it out, because he has other things to do.
This is an artificial example, but we have come across many times developers who solve problems in the same manner. To solve them effectively, you need to move away from heuristic methods and study the theory.
Let's move on to the basics
If Bill was a proponent of a theoretical approach, the process would look like this:
- To identify the given input data and to determine the desired output - in the sense of their properties: “I have an object whose keys are strings representing ID, and values are objects representing users. I want to get an array whose values will be user objects - but only objects of registered users ”
- To understand how to search inside an object: “I know that I can get an array of keys in an object by calling
Object.keys()
. I want to get an array because arrays support enumeration . " - To realize that this method helps to get the keys, and you need to transform the keys into values, and remember the
map
obvious method of creating a new array by transforming the values of another array:Object.keys(usersById).map(id => usersById[id])
- To see that you now have an array of user objects that can be filtered and which contains real values that you want to filter:
Object.keys(usersById).map(id => usersById[id]).filter(user => user.registered)
Go Bill this way, he could work for us.
Why don't people resort to theory more often?
Sometimes they just don’t know her. Most often, they are too busy and cannot find the time to learn this way of solving problems - they just need everything to work. They risk turning this approach into a habit that will become an obstacle to the development of their skills.
To avoid such errors, always start with a theory. At each stage of the process, think about what kind of data you are dealing with. Instead of relying on familiar patterns all the time, consider primitive data types: array, object, string, etc. When using a function or method, refer to the documentation to know exactly what data types support them, what arguments they take, and what the result is.
With this approach, you can find a working solution on the first try. You can be sure of its correctness, because you specially selected your actions based on given input and desired output. Go deep into the basics of each operation (data types and return values), rather than fuzzy business formulations (like "registered users").