1.1 Objets et classes
Aujourd'hui, tu vas découvrir comment fonctionne un programme typique en JavaScript. Et l'info principale : chaque programme en JavaScript est constitué de classes et d'objets. JavaScript est un langage orienté objet, et tout y est objet : nombres, chaînes, fonctions et même classes.
Alors, qu'est-ce que les classes ?
Je vais commencer par une analogie. Imagine que tu veux construire un petit bateau. D'abord, il te faut un plan, puis tu l'apportes à l'usine où, à partir de ce plan, ils construisent le bateau. Ou une dizaine. Bref, autant que tu veux. À partir d'un seul plan, ils construisent des dizaines de bateaux identiques, c'est ça qui est important.
En programmation JavaScript, c'est exactement pareil.
Plans
Un programmeur est comme un concepteur. Sauf qu'au lieu de dessiner des plans, le programmeur JavaScript écrit des classes. Et à partir des plans, on crée des pièces, et à partir des classes — on crée des objets.
On commence par écrire des classes (faire des plans), puis, lors de l'exécution du programme, sur la base de ces classes, JavaScript crée des objets. Exactement comme les bateaux sont construits à partir des plans.
Un seul plan, mais de nombreux bateaux. Les bateaux sont différents, ils ont différents noms, transportent différentes cargaisons. Mais ils sont très semblables : ce sont tous des bateaux avec une construction identique et peuvent effectuer des tâches similaires.
Ou encore une autre analogie...
Fourmilière
Une fourmilière est un bon exemple d'interaction entre objets. Dans une fourmilière simple, il y a trois classes de fourmis : la reine, les guerriers et les ouvrières.
Le nombre de fourmis de chaque classe est différent. Une seule reine pour toute la fourmilière, des dizaines de guerriers, et des centaines de fourmis ouvrières. Trois classes et des centaines d'objets. Les fourmis interagissent entre elles, avec d'autres fourmis et avec des fourmis d'autres classes selon des règles bien définies.
C'est un exemple idéal. Dans un programme typique, c'est exactement pareil. Il y a un objet principal qui crée des objets de toutes les autres classes. Les objets commencent à interagir entre eux et avec le «monde extérieur» du programme. À l'intérieur de ces objets, leur comportement est programmé de manière rigide.
Ces deux explications sont deux faces d'une même médaille. La vérité est au milieu. Le premier exemple (sur le plan et les bateaux) montre le lien entre la classe et les objets de cette classe. L'analogie est très forte. Le second exemple (sur la fourmilière) montre la relation entre les objets qui existent pendant l'exécution du programme et les classes qui ont été écrites.
D'abord, tu dois écrire des classes pour tous les objets existant dans le programme, puis décrire leur interaction. Ça a l'air compliqué, mais c'est plus facile qu'il n'y paraît.
En JavaScript, toutes les entités pendant l'exécution du programme sont des objets, et la rédaction d'un programme consiste à décrire différentes manières d'interagir entre les objets. Les objets appellent simplement les méthodes les uns des autres et leur transmettent les données nécessaires.
Documentation
Mais comment savoir quelles données transmettre aux méthodes ? Tout a déjà été inventé avant toi.
Habituellement, chaque classe a une description qui indique à quoi elle sert. De même, chaque méthode publique a généralement une description : ce qu'elle fait et quelles données doivent lui être transmises.
Pour utiliser une classe, il faut avoir une idée générale de ce qu'elle fait. Et aussi savoir précisément ce que fait chaque méthode. Et il n'est pas nécessaire de savoir comment elle le fait. Une sorte de baguette magique.
Voyons le code — copier un fichier :
const fs = require('fs');
// Ouvre les fichiers
const src = fs.createReadStream('source.txt');
const dst = fs.createWriteStream('destination.txt');
// Copier le contenu de source.txt dans destination.txt
src.pipe(dst);
// Fermer les fichiers après la copie
src.on('end', () => {
src.close();
dst.close();
});
Si tu lis ce code ligne par ligne, tu peux deviner ce qu'il fait dans les grandes lignes. Bien qu'il faille un peu d'expérience et de pratique. Ainsi, après un certain temps, ce code te semblera familier et compréhensible.
1.2. Conception de programme
Concevoir un programme est tout un art. C'est à la fois simple et compliqué. Simple parce qu'il n'y a pas de lois strictes : tout ce qui n'est pas interdit est autorisé. Et compliqué aussi pour cette raison : il y a tellement de manières de faire quelque chose qu'il n'est pas facile de trouver la meilleure.
Concevoir un programme, c'est comme écrire un livre. D'une part, tu écris simplement des lettres, des mots, des phrases. D'autre part, l'intrigue, les caractères des héros, les contradictions internes, les conflits, le style narratif, l'intrigue, etc. sont importants.
La clé est de comprendre pour qui tu écris le code. Et tu écris pour d'autres programmeurs.
Le développement de tout produit implique des modifications : ajouter ici, enlever là, refaire par là. Et ainsi, par petites itérations, naissent de grands, énormes et gigantesques projets.
La principale exigence pour le code est qu'il doit être compréhensible par d'autres programmeurs. Un code incorrect mais compréhensible peut être corrigé. Un code correct mais incompréhensible ne peut pas être amélioré. Il ne reste plus qu'à le jeter.
Alors, comment écrire un code bon et compréhensible ?
Pour cela, il faut faire trois choses :
- Écrire un code bon et compréhensible à l'intérieur des méthodes — le plus simple
- Décider des entités à inclure dans le programme
- Diviser correctement le programme en parties logiques
Qu'est-ce qui se cache derrière ces notions ?
Écrire un bon code à l'intérieur des méthodes
Si tu as au moins un niveau élémentaire en anglais, tu as peut-être remarqué à quel point le code peut parfois se lire facilement — comme des phrases en anglais :
class Cat extends Pet— la classe Chat étend la classe AnimalDeCompagniewhile (stream)— tant que le flux n'est pas vide ...a < b ? a : b— siaest inférieur àb, retournea, sinon retourneb
C'est fait exprès. JavaScript est l'un des quelques langages où il est facile d'écrire un code auto-documenté : un code compréhensible sans commentaires. Dans un bon code JavaScript, de nombreuses méthodes se lisent simplement comme des phrases en anglais.
Ton objectif en écrivant du code est de le rendre aussi simple et concis que possible. Pense seulement à quel point ton code sera facile à lire, et tu commenceras à avancer dans la bonne direction.
En JavaScript, il est d'usage d'écrire un code facile à lire. Idéalement, chaque méthode devrait tenir entièrement sur l'écran (longueur de méthode — 20-30 lignes). C'est la norme pour toute la communauté JavaScript. Si le code peut être amélioré, il doit l'être.
La meilleure façon d'apprendre à écrire du bon code est la pratique constante. Écris beaucoup de code, étudie le code des autres, demande à des collègues plus expérimentés de faire la revue de ton code. Et souviens-toi qu'au moment où tu te diras «ça ira comme ça», ton développement s'arrête.
Décider des entités à inclure dans le programme
Tu dois écrire du code compréhensible pour d'autres programmeurs. Si 9 programmeurs sur 10, en concevant un programme, créent les classes A, B et C, alors tu dois aussi créer les classes A, B et C dans ton programme. Tu dois écrire du code compréhensible pour les autres.
Un excellent code qui fonctionne, rapide, non-standard — c'est un mauvais code.
Tu dois étudier les projets des autres : c'est la meilleure, la plus rapide et la plus simple façon d'acquérir toute la sagesse qui s'est accumulée pendant des décennies dans l'industrie informatique.
Et, d'ailleurs, tu as déjà sous la main un excellent projet populaire et bien documenté — React. Commence par lui.
Examine les classes et les structures des classes. Réfléchis pourquoi certaines méthodes sont faites statiques et d'autres non. Pourquoi les méthodes ont ces paramètres-là et pas d'autres. Pourquoi ces méthodes-là, pourquoi les classes portent ces noms et se trouvent dans ces packages.
Quand tu commenceras à comprendre les réponses à toutes ces questions, tu pourras écrire du code compréhensible par les autres.
Cependant, je te mets en garde contre l'examen du code dans les méthodes de D3.js. Le code de nombreuses méthodes a été réécrit pour maximiser la vitesse d'exécution — sa lisibilité est très discutable.
Diviser correctement le programme en parties logiques
N'importe quel programme est généralement divisé en parties ou modules. Chaque partie est responsable de son aspect du programme.
Par exemple, un ordinateur a une unité centrale, un moniteur, des claviers, et ce sont toutes des parties distinctes, peu dépendantes les unes des autres. De plus, leur interaction est standardisée : USB, HDMI, etc. Ainsi, si tu renverses du café sur le clavier, tu peux simplement le laver sous le robinet, le sécher et continuer à l'utiliser.
Par contre, un ordinateur portable est un exemple d'architecture monolithique : les parties logiques existent, mais elles sont beaucoup plus intégrées. Avec un Macbook Pro, pour nettoyer le clavier, il faut démonter la moitié de l'ordinateur portable. Renverser du café sur un ordinateur portable est une bonne raison d'en commander un nouveau. Mais pas de café, hein.
1.3 Créer ses propres classes
Tu commences juste à programmer, donc tu dois commencer petit — apprendre à créer tes propres classes.
Tu en as déjà créé, bien sûr, mais tu dois apprendre à comprendre quelles classes doivent être dans le programme, comment elles doivent être nommées, quelles méthodes elles doivent avoir. Et comment elles doivent interagir entre elles.
Liste des entités
Si tu ne sais pas par où commencer, commence au début.
Au tout début de la conception d'un programme, tu peux simplement écrire sur un bout de papier la liste des entités (objets) qui doivent être dans le programme. Puis les programmer selon ce principe : chaque entité — une classe distincte.
Exemple
Supposons que tu veux programmer un jeu d'échecs. Tu auras besoin d'entités comme : l'échiquier et 6 types de pièces. Les pièces se déplacent différemment, ont des valeurs différentes — c'est logique qu'elles soient des classes distinctes. Et en général, au début, plus il y a de classes, mieux c'est.
Rencontrer un programmeur débutant qui, au lieu de deux classes, a écrit dix — c'est rare. Mais au lieu de dix, écrire deux, voire une seule — ça, les débutants adorent. Donc plus de classes, mesdames et messieurs les programmeurs. Et votre code deviendra plus compréhensible par tous, sauf peut-être par vous-mêmes 😛
Échecs
Supposons que nous avons décidé d'écrire des classes pour les échecs : à quoi ressembleraient ces classes ?
L'échiquier — est-ce simplement un tableau 8 par 8 ? Mieux vaut faire pour elle une classe distincte qui stocke à l'intérieur une référence au tableau. Ainsi, dans la classe «échiquier», tu pourras ajouter de nombreuses méthodes utiles qui, par exemple, vérifient si une case est vide ou occupée.
En général, au début, tu peux toujours suivre le principe : Le programme a différentes entités, et une entité a un type. Ce type — c'est la classe.
GO TO FULL VERSION