Définir les responsabilités des modules
Objectif : Répartir les responsabilités du gestionnaire entre données, interface et démarrage de l’application.
Quand un gestionnaire de tâches grandit, une modification apparemment simple peut obliger à toucher plusieurs parties du programme. Par exemple, changer la façon d’afficher la progression ne devrait pas vous forcer à réécrire le code qui conserve les tâches. Vous allez définir des frontières claires pour limiter ces effets.
Une responsabilité correspond à un rôle identifiable dans l’application : démarrer celle-ci, lire ou enregistrer les tâches, traduire une interaction en demande de changement, ou mettre à jour l’affichage. La séparation des responsabilités consiste à confier ces rôles à des parties distinctes. Ainsi, chaque changement a une zone principale où être réalisé, plutôt qu’un ensemble de fonctions dispersées dans un fichier central.
Attribuer un rôle à chaque fichier
Le contrat du projet fournit déjà les frontières à respecter. etat.js porte la définition des données de départ ; reducteur.js regroupe les règles qui les font évoluer ; persistance.js s’occupe de leur conservation dans le navigateur. Ces fichiers concernent les données et leur cycle de vie, mais chacun intervient à un niveau différent.
Les fichiers associés à l’interface ont d’autres rôles. dom.js centralise les interactions et les transforme en demandes compréhensibles par l’application ; rendu.js traduit les données disponibles en affichage. progression.js et clipboard.js isolent chacun une interaction avec une API du navigateur, tandis que statistiques.js regroupe les calculs destinés à l’affichage et rapport.js porte la fonctionnalité de rapport chargée à la demande dans une leçon ultérieure.
Enfin, main.js assemble les éléments et lance l’application. Il ne doit pas devenir l’endroit où l’on réécrit les règles de conservation, les décisions d’affichage et les interactions du navigateur. Pensez-y comme au point de coordination : il met les parties en relation, mais ne remplace pas leur travail propre.
Un exemple de répartition
Le tableau suivant sert de carte de responsabilités : il rend visible le rôle attendu de chaque partie avant d’écrire son contenu. Il ne crée pas de nouveaux fichiers et n’ajoute pas de classes ou de conventions à l’interface. Utilisez-le pour vérifier qu’une tâche concrète — par exemple afficher un résumé — a un emplacement principal et ne mélange pas plusieurs rôles sans raison.
| Fichier | Responsabilité principale | Exemple de modification |
|---|---|---|
| etat.js | Définir les données de départ | Faire évoluer leur forme selon le contrat de l’application |
| reducteur.js | Porter les règles de transition des données | Ajuster une règle de modification des tâches |
| persistance.js | Assurer la conservation dans le navigateur | Gérer la lecture ou l’écriture des données |
| dom.js | Centraliser les interactions de l’interface | Prendre en charge une nouvelle interaction utilisateur |
| rendu.js | Mettre à jour l’interface visible | Modifier la construction de la liste affichée |
| progression.js | Gérer l’observation de la progression | Adapter la réaction à sa visibilité |
| clipboard.js | Gérer la copie du résumé | Traiter le résultat de la demande de copie |
| statistiques.js | Fournir les calculs utiles à l’affichage | Ajuster un calcul de progression |
| rapport.js | Porter la fonctionnalité de rapport | Faire évoluer le contenu du rapport |
| main.js | Assembler et démarrer l’application | Coordonner la mise en place des parties |
Cohésion et couplage : deux vérifications pratiques
La cohésion décrit à quel point les éléments d’une partie servent un même rôle. Un fichier est cohérent si ses fonctions contribuent toutes à sa mission : par exemple, les opérations liées à la copie du résumé relèvent de clipboard.js. Si ce fichier commence aussi à construire toute la liste des tâches, sa cohésion diminue : il faut envisager de confier cette responsabilité à rendu.js.
Le couplage représente le niveau de dépendance entre des parties. Un couplage fort apparaît lorsqu’un changement interne dans un fichier oblige à modifier plusieurs autres fichiers qui connaissent trop de détails sur son fonctionnement. Dans ce projet, conservez la règle donnée par le contrat : les adaptateurs travaillent avec les données et le rendu, mais les données ne doivent pas dépendre des adaptateurs.
Vous n’avez pas besoin de créer immédiatement une abstraction supplémentaire pour chaque fonction. Une responsabilité doit être assez précise pour se comprendre, mais assez large pour regrouper les opérations qui changent pour la même raison. Le contrat fixe ici le nombre et le nom des fichiers : répartissez le travail à l’intérieur de ces frontières plutôt que d’inventer une nouvelle structure.
À retenir
- Attribuez à chaque fichier un rôle principal, conformément au contrat du projet.
- Visez une cohésion forte : les éléments d’un fichier doivent contribuer à la même responsabilité.
- Limitez le couplage : évitez qu’un changement local impose des modifications en cascade.
- Laissez à main.js la coordination et le démarrage, pas les règles propres aux autres parties.
Dans la prochaine leçon, vous verrez comment relier ces responsabilités au moyen des mécanismes des modules ES.