Theory instead of heuristics: getting better as frontend developers

Original author: Alexander Kotler
  • 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 = thisneeded 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:

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.


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 usersByIdinto 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 attendeesremains 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 usereasily misleading, since it is not an object user, but an identifier, that is, a string. Since the attribute registeredfor the rows is not defined, filterregards 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) => 
          .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 reduceand how it is used. Moreover, Bill does not understand that he just defined a Objectnew 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:

  1. Using .filter()on the variable, Bill got it TypeError. He did not understand that he was filternot defined on ordinary objects.
  2. 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.
  3. 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.
  4. 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:

  1. 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 ”
  2. 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 . "
  3. To realize that this method helps to get the keys, and you need to transform the keys into values, and remember the mapobvious method of creating a new array by transforming the values ​​of another array:

    Object.keys(usersById).map(id => usersById[id])
  4. 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").

Also popular now: