Devenir un meilleur développeur front-end en utilisant les fondamentaux au lieu de l'heuristiqueNotre expérience montre que les éducateurs non techniques et les autodidactes s'appuient souvent non pas sur des principes théoriques, mais sur des méthodes heuristiques.
Heuristique - modèles et règles éprouvées qu'un développeur a appris de la pratique. Ils peuvent fonctionner imparfaitement ou de manière limitée, mais dans une mesure suffisante, et ne nécessitent pas de réflexion sérieuse. Voici quelques exemples d'heuristiques:
- "Utilisez
$(document).ready(function(){})
pour initialiser le code sur les sites jQuery" - "Le
var self = this
construction est nécessaire pour appeler une méthode dans une fonction de rappel" - «Les fonctions fléchées n'ont pas d'
return
»
En même temps, le principe théorique peut être utilisé pour trouver des solutions à d'autres problèmes. Il est invariablement fidèle et détermine souvent l'appareil même de l'un ou l'autre élément. Les principes théoriques comprennent, par exemple:
A noter: nous n'avons cité que des exemples heuristiques afin de souligner le caractère artisanal de l'heuristique par rapport à la rigueur des fondements théoriques. Aucun des exemples heuristiques n'est universel dans tous les cas, mais ils fonctionnent dans un nombre suffisant de situations pour que les développeurs qui les utilisent reçoivent du code de travail sans une compréhension complète de son fonctionnement.
Arguments pour une approche théorique
Nous avons souvent rencontré le fait que les développeurs sans formation technique ne sont pas enclins à résoudre des problèmes en utilisant des principes théoriques. En règle générale, cela s'explique par le fait qu'au début de leur carrière, ils n'ont pas eu l'occasion de les apprendre, et comme les méthodes heuristiques fonctionnent de manière satisfaisante, ils continuent de les utiliser.
Cependant, malgré l'apparente complexité, l'apprentissage d'une théorie peut être très utile. Pourquoi? Ensuite, cette théorie vous permettra de vous sentir confiant que votre solution fonctionne, ainsi que d'afficher indépendamment les réponses aux nouvelles questions, sans avoir à chercher les solutions de quelqu'un d'autre. À court terme, les algorithmes heuristiques peuvent sembler être une solution simple et rapide, mais ils conduisent souvent à des solutions imparfaites - voire pas du tout.
De plus, en s'appuyant sur des méthodes heuristiques, vous n'apprendrez jamais à résoudre des problèmes pour de vrai. Vous pouvez souvent réussir à trouver une solution de travail, mais tôt ou tard, vous arriverez à un arrêt, dont vous ne verrez pas d'issue. Les programmeurs C&P s'appuient sur l'heuristique dans leur travail.
Critères de niveau de compétence du développeur
Lors des entretiens avec les développeurs frontend, nous leur avons défini une tâche de programmation et leur avons dit qu'ils étaient libres d'utiliser toutes les sources, que ce soit Google ou Stack Overflow. De cette façon, il est facile de déterminer si le développeur est un adepte de l'heuristique ou de la théorie.
Les premiers, sans exception, copient du code à partir d'exemples plus ou moins adaptés avec Stack Overflow. Ce n'est que lorsque le code ne fonctionne pas comme prévu qu'ils ont commencé à le peaufiner eux-mêmes. Souvent, ils échouent.
Ces derniers ont tendance à rechercher des réponses dans la documentation de l'API. Ils y trouvent des informations sur le nombre de paramètres pris par une fonction particulière, ou la syntaxe spécifique de la forme développée de la propriété CSS souhaitée.
Dès les cinq premières minutes de l'entretien, vous pouvez déterminer exactement à quel type de programmeurs appartient le candidat.
Exemple
Prenons Bill comme exemple. Il a suivi plusieurs cours de formation, résolu un certain nombre de tâches en JavaScript et écrit des sites Web pendant son temps libre, mais il n'a pas vraiment appris JavaScript.
Une fois que Bill tombe sur un objet comme celui-ci:
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 } }
Un tel objet peut afficher une liste d'utilisateurs et s'ils se sont inscrits à un événement particulier.
Supposons que Bill doive récupérer une liste d'utilisateurs enregistrés. En d'autres termes, filtrez-les. Il est tombé sur du code dans lequel la méthode
.filter()
été utilisée pour filtrer la liste. Il essaie donc quelque chose comme:
const attendees = usersById.filter(user => user.registered);
Et voici ce qu'il obtient:
TypeError: usersById.filter is not a function
"Quelque chose de non-sens", pense Bill, car il a vu le code dans lequel
.filter()
fonctionnait comme un filtre.
Le problème est que Bill s'est appuyé sur la méthode heuristique. Il ne comprend pas que le
filter
est une méthode définie sur des tableaux, tandis que
usersById
est un objet normal qui n'a pas de méthode de
filter
.
Le Bill confus google le «
filtre javascript ». Il trouve de nombreuses références aux tableaux et se rend compte qu'il doit transformer
usersById
en tableau. Puis, en demandant «
javascript pour transformer un objet en tableau », il trouve des exemples en utilisant
Object.keys()
sur Stack Overflow. Après cela, il essaie:
const attendees = Object.keys(usersById).filter(user => user.registered);
Cette fois, l'erreur ne s'affiche pas, mais, à la surprise de Bill, le champ des
attendees
reste vide.
Le fait est que
Object.keys()
renvoie les clés de l'objet, mais pas sa valeur. En fait, le nom de la variable
user
est facilement trompeur, car ce n'est pas un objet
user
, mais un identifiant, c'est-à-dire une chaîne. Étant donné que l'attribut
registered
n'est pas défini pour les chaînes, le
filter
traite chaque entrée comme faux et le tableau reste vide.
Bill examine de plus près les réponses Stack Overflow et apporte la modification suivante:
const attendees = Object.keys(usersById).filter(id => usersById[id].registered);
Cette fois, le résultat est meilleur:
["5", "27", "39"]
. Mais Bill voulait obtenir des objets visiteurs, pas leur carte d'identité.
Pour comprendre comment filtrer les visiteurs, Bill ennuyé recherche un «
filtre d'objet javascript », examine les résultats de la recherche pour Stack Overflow et trouve
cette réponse avec le code suivant:
Object.filter = (obj, predicate) => Object.keys(obj) .filter( key => predicate(obj[key]) ) .reduce( (res, key) => (res[key] = obj[key], res), {} );
Bill copie ces lignes et essaie:
const attendees = Object.filter(usersById, user => user.registered);
Tout fonctionne - bien qu'il ne soit pas clair pourquoi. Le projet de loi ne comprend pas pourquoi la
reduce
nécessaire et comment elle est utilisée. De plus, Bill ne comprend pas qu'il vient de définir une nouvelle méthode non standard pour l'
Object
global.
Mais Bill s'en fiche - ça marche! Les conséquences ne l'intéressent pas encore.
Qu'est-ce que Bill a fait de mal?
Bill a essayé une méthode heuristique pour résoudre le problème et a rencontré les problèmes suivants:
- En utilisant
.filter()
sur une variable, Bill a obtenu une TypeError
. Il n'a pas compris que le filter
pas défini sur des objets ordinaires.
- Il a utilisé
Object.keys()
pour «transformer l'objet en un tableau», mais cela seul n'a donné aucun résultat. Il avait besoin de créer un tableau de valeurs d'objets. - Même après avoir reçu les valeurs et les avoir utilisées comme condition de filtrage, il n'a reçu que des identifiants au lieu des objets utilisateur associés à ces identifiants. En effet, le tableau filtré contenait un ID, pas des objets utilisateur.
- Au fil du temps, Bill a abandonné cette approche et a trouvé une solution de travail sur Internet. Néanmoins, il n'a toujours pas compris comment cela fonctionne - et ne perdra pas de temps à le trier, car il a d'autres choses à faire.
C'est un exemple artificiel, mais nous avons rencontré de nombreux développeurs qui résolvent les problèmes de la même manière. Pour les résoudre efficacement, vous devez vous éloigner des méthodes heuristiques et étudier la théorie.
Passons aux bases
Si Bill était un partisan d'une approche théorique, le processus ressemblerait à ceci:
- Pour identifier les données d'entrée données et déterminer la sortie souhaitée - au sens de leurs propriétés: «J'ai un objet dont les clés sont des chaînes représentant l'ID et les valeurs sont des objets représentant les utilisateurs. Je veux obtenir un tableau dont les valeurs seront des objets utilisateur - mais uniquement des objets d'utilisateurs enregistrés »
- Pour comprendre comment rechercher à l'intérieur d'un objet: «Je sais que je peux obtenir un tableau de clés dans un objet en appelant
Object.keys()
. Je veux obtenir un tableau car les tableaux prennent en charge l'énumération . " - Pour se rendre compte que cette méthode aide à obtenir les clés, et que vous devez transformer les clés en valeurs, et rappelez-vous de la
map
- une méthode évidente de création d'un nouveau tableau en transformant les valeurs d'un autre tableau:
Object.keys(usersById).map(id => usersById[id])
- Pour voir que vous disposez maintenant d'un tableau d'objets utilisateur pouvant être filtré et contenant des valeurs réelles que vous souhaitez filtrer:
Object.keys(usersById).map(id => usersById[id]).filter(user => user.registered)
Allez Bill de cette façon, il pourrait travailler pour nous.
Pourquoi les gens ne recourent-ils pas plus souvent à la théorie?
Parfois, ils ne la connaissent tout simplement pas. Le plus souvent, ils sont trop occupés et ne trouvent pas le temps d'apprendre cette façon de résoudre les problèmes - ils ont juste besoin de tout pour fonctionner. Ils risquent de transformer cette approche en une habitude qui deviendra un obstacle au développement de leurs compétences.
Pour éviter de telles erreurs, commencez toujours par une théorie. À chaque étape du processus, réfléchissez au type de données que vous traitez. Au lieu de s'appuyer sur des modèles familiers tout le temps, pensez aux types de données primitifs: tableau, objet, chaîne, etc. Lorsque vous utilisez une fonction ou une méthode, reportez-vous à la documentation pour savoir exactement quels types de données les prennent en charge, quels arguments ils prennent et quel est le résultat.
Avec cette approche, vous pouvez trouver une solution de travail dès le premier essai. Vous pouvez être sûr de son exactitude, car vous avez spécialement sélectionné vos actions en fonction de l'entrée donnée et de la sortie souhaitée. Approfondissez les bases de chaque opération (types de données et valeurs de retour), plutôt que les formulations commerciales floues (comme les "utilisateurs enregistrés").