📜 ⬆️ ⬇️

Theory instead of heuristics: getting better as frontend developers



Translation of the developer using the fundamentals instead of heuristics

Our experience shows that non-technical developers and self-taught developers often rely not on theoretical principles, but on heuristic methods.
')
Heuristics - templates and proven rules that the developer has learned from practice. They may work imperfectly or limitedly, but sufficiently, and do not require serious reflection. Here are some examples of heuristics:


At the same time, the theoretical principle can be used to find solutions to other problems. It is invariably true and often determines the device itself the work of an element. The theoretical principles include, for example:


Please note: we have quoted only heuristic examples in quotation marks - in order to emphasize the handicraft nature of heuristics compared to the rigor of theoretical foundations. None of the examples of heuristics is universal for all cases, but they work in a sufficient number of situations so that the developers who apply them obtain a working code without a complete understanding of its work.

Arguments in favor of a theoretical approach


We have often come across the fact that non-technical developers are not inclined to solve problems with the help of theoretical principles. As a rule, this is explained by the fact that at the beginning of their career they did not have the opportunity to learn them, and since the heuristic methods work satisfactorily, they continue to use them.

However, despite the apparent complexity, learning the theory can be very useful. What for? Then, that the theory will allow you to feel confident that your solution works, and also independently display answers to new questions without having the need to look for other people's solutions. In the short term, heuristic algorithms may seem simple and quick solutions, but will often lead to non-ideal solutions — if at all.

Moreover, relying on heuristic methods, you will never learn how to solve problems for real. Perhaps, quite often you will be able to find a working solution, but sooner or later you will come to a dead end, from which you will not see a way out. C & P programmers rely on heuristics in their work.

Developer Skill Level Criteria


Conducting an interview with frontend-developers, we set them the task of programming and say that they are free to use any sources, be it Google or Stack Overflow. Thus, it is easy to determine if the developer is an adept of heuristics or theory.

The first, without any exception, copy code from more or less suitable examples with Stack Overflow. Only when the code does not work as planned, they will begin to adjust 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 for example developer Bill. He completed several training courses, solved a number of tasks in JavaScript and wrote websites in his free time, but didn’t really learn JavaScript.

One day, Bill finds 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 specific event.

Suppose Bill needs to extract a list of registered users. In other words, filter them. It came across code in which the .filter() method was used to filter the list. Therefore, he tries something like:

 const attendees = usersById.filter(user => user.registered); 

And that's what he gets:

 TypeError: usersById.filter is not a function 

“Some kind of nonsense,” Bill thinks, because he saw the code in which .filter() worked as a filter.

The problem is that Bill relied on the heuristic method. He does not understand that filter is a method defined on arrays, while usersById is a regular object that does not have a filter method.

Baffled Bill google " javascript filter ". He finds many references to arrays and understands that he needs to turn usersById into an array. Then, using the query “ javascript to turn an object into an array ”, it finds examples using Object.keys() on Stack Overflow. 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 attendees field remains empty.

The fact is that Object.keys() returns the keys of an object, but not its values. In fact, the name of the user variable is easily misleading, since this is not a user object, but an identifier, that is, a string. Since the registered attribute for strings is not defined, filter treats each entry as false, and the array goes empty.

Bill looks at the answers to the Stack Overflow closer 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 the objects of visitors, not their ID.

To understand how to filter visitors, annoyed Bill searches for a “ javascript object filter ”, examines the results of a search on 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 why reduce needed and how it is used. Moreover, Bill does not understand that he just defined a new non-standard method for the global Object .

But Bill doesn't care - it works! The consequences of it are not interested.

What did Bill do wrong?


Bill tried a heuristic method for solving a problem and encountered the following problems:

  1. Using .filter() on a variable, Bill got a TypeError . He did not understand that filter not defined on ordinary objects.
  2. He applied Object.keys() to “turn an object into an array,” but this in itself did not bring any result. He needed to create an array of object values.
  3. Even receiving values ​​and using them as a condition for filtering, he received only identifiers instead of user objects associated with these identifiers. All because the filtered array contained ID, but not user objects.
  4. Over time, Bill abandoned this approach and found a working solution on the Internet. Nevertheless, he still has not understood how it works - and will not waste time trying to figure it out, because he has other things to do.

This is an artificial example, but we have many times encountered 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 get to the basics


If Bill were a proponent of the theoretical approach, the process would look like this:

  1. Identify the specified input data and determine the desired output - in the sense of their properties: “I have an object, the keys of which are the lines representing the ID, and the values ​​are the objects representing the users. I want to get an array whose values ​​will be user objects - but only objects of registered users »
  2. Understand how to iterate 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 brute force . ”
  3. Realizing that this method helps to get the keys, and you need to transform the keys into values, and recall map is the obvious method of creating a new array by transforming the values ​​of another array:

     Object.keys(usersById).map(id => usersById[id]) 
  4. See that you now have an array of custom objects that you can filter and that contains the actual values ​​you want to filter:

     Object.keys(usersById).map(id => usersById[id]).filter(user => user.registered) 

Go Bill this way, he could work with 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 mistakes, always start with theory. At each stage of the process, think about exactly what data you are dealing with. Instead of relying on familiar patterns all the time, consider the primitive data types: array, object, string, etc. When using a function or method, refer to the documentation to know exactly which data types support them, which arguments they take, and what results they get.

With this approach, you can find a working solution at the first attempt. You can be assured of its correctness, because you specifically selected your actions based on the given input and desired output data. Understand the basics of each operation (data types and return values), rather than vague business formulations (such as “registered users”).

Source: https://habr.com/ru/post/458642/


All Articles