#### Angular Guidelines * [Les principes directeurs](#principles) + [Stack driven](#stackDriven) + [KISS principle](#KISS) + [Single Responsability](#SRP) + [Try to be DRY](#T-DRY) + [Component-Driven Development](#CDD) + [Smart and dumb pattern](#smartAndDumb) * [La structure de projet](#projectStructure) + [La structure LIFT](#projectStructureLIFT) + [L'arborescence des fichiers](#projectStructureTree) * [Règles d'architecture](#architecture) + [Structure & Organisation](#structureConventions) + [Routing & Navigation](#routingConventions) + [Les formulaires](#forms) + [Styling & CSS](#stylingConventions) + [Gestion de l'État (Signals & Ressources)](#stateManagement) + [Gestion des Erreurs](#errorHandling) [Back to top](#top) ## Préface Le but de ce document est d'établir des guidelines pour améliorer l'efficacité, la maintenabilité et la cohérence du code. Pour atteindre ce but, ce document définit des principles directeurs, une organisation de fichiers, et des règles d'architecture. Pour voir les bonnes pratiques et les conventions à utiliser, veuillez consulter le document suivant : [Angular Standard](/AngularStandard.html) ## Principes directeurs ### Stack Driven **Adoptez une approche drivée par la stack** pour garantir une base solide et un code durable. Pour appliquer le principe "Stack Driven" dans un projet Angular, voici deux points clés à développer : * **Maitrisez la stack (HTML, CSS, JS, TS)** La stack, c'est la base ! En effet, le HTML, le CSS, le JavaScript et TypeScript constituent les fondations de votre application Angular. Il est crucial de maîtriser ces technologies pour assurer une intégration fluide et efficace avec le framework. * **Standardiser l'utilisation du framework Angular** En alignant l'équipe avec les standards et les meilleures pratiques d’Angular, vous assurez la création d’un code robuste et maintenable. De plus, la standardisation facilite la collaboration entre les développeurs et assure une uniformité dans la codebase. Il est également possible de normaliser l'utilisation des features d'Angular pour produire un code durable aligné avec l'écosystème. Voici quelques conseils : + **Utilisez les inputs et outputs :** pour communiquer entre les composants parents/enfants. + **Utilisez des pipes :** pour transformer les données à afficher (ex. dates, nombres). + **Utilisez des directives :** pour partager des comportements liés aux éléments HTML. + **Utilisez des guards :** pour contrôler l'accès aux routes/zones de votre application. + **Utilisez des interceptors :** pour centraliser la logique des requêtes HTTP. + **Utilisez des resolvers uniquement :** pour charger des données avant l'affichage. Si vous souhaitez gérer le chargement (spinner, skeleton), alors utilisez un service. Documentation : [Angular Architecture Guide](https://angular.io/guide/architecture) ### KISS On pourrait résumer ce principe en 1 phrase: **Les solutions les plus simples sont souvent les meilleures**. Le principle KISS peut être traduit de plusieurs manières: 'Keep it Short and Simple', 'Keep it Simple and Straightforward', 'Keep It Simple and Stupid', ... D'un point de vue programmation, un code simple se matérialise par un code clean. Pour appliquer le principe KISS dans un projet Angular, voici quelques conseils : * **Évitez l'abstraction prématurée du code**. En d'autres mots, évitez de prédire les besoins futurs et limitez exclusivement l'abstraction aux parties réutilisables du code clairement identifiées. * **Adoptez une approche déclarative**. Préférez une approche déclarative et non impérative, ce qui rend le code plus lisible et plus facile à maintenir. * **Préférez les solutions natives** avant d'utiliser une dépendance tierce. En évitant les dépendances tierces, vous réduisez la complexité de votre application et limitez la dette technique. Documentation: [Keep It Simple, Stupid (KISS)](https://www.interaction-design.org/literature/topics/keep-it-simple-stupid) ### Single Responsability Principle Le principe de responsabilité unique peut être résumé en une phrase: **Un composant, une classe, une fonction ne devrait avoir qu'une seule raison de changer**. C'est un principe fondamental de l'ingénierie logicielle qui vise à réduire la complexité du code en le divisant en unités plus petites et plus simples. Application du principe SRP dans une application Angular : * **Au niveau composant**: + Factorisez vos composants en unités autonomes (voir [CDD](#CDD)). + Suivez le pattern smart/dumb component. + Définissez uniquement la logique de présentation dans le composant. * **Au niveau service**: + Utilisez des services pour déléguer la logique métier. + Utilisez des services pour manager la gestion de données partagées. + Créez des services pour centraliser les appels HTTP aux apis. ### Try to be DRY **Privilégiez la réutilisabilité** du code sans sacrifier la clarté/lisibilité. **Évitez d'avoir un code générique avec des conditions mutuellement exclusives**. Cela rend le code complexe, difficile à tester et à modifier. Si vous vous trouvez dans cette situation, refactorisez en plusieurs éléments distincts. Même s'il y a une duplication partielle, cela est souvent préférable à un code trop générique. Documentation: [T-DRY (Try to be DRY)](https://angular.io/guide/styleguide#t-dry-try-to-be-dry) ### Component-Driven Development Le développement piloté par composants (CDD) est une méthodologie qui se concentre sur la création et l'assemblage de composants réutilisables pour bâtir l'application. Cette approche encourage la création de petits composants autonomes pouvant être facilement réutilisés et combinés. Documentation: [Component Driven User Interfaces](https://www.componentdriven.org/) [An overview of component driven development and atomic design principles](https://blog.ankitsanghvi.in/cdd-and-atomic-design/) [Why Component driven development?](https://www.technbuzz.com/2022/06/06/why-component-driven-development/) [Component-Driven Development](https://www.chromatic.com/blog/component-driven-development/) [A Guide to Component Driven Development (CDD)](https://itnext.io/a-guide-to-component-driven-development-cdd-1516f65d8b55) ### Smart/Dumb components Le pattern smart/dumb components dans un projet Angular contribue à un code organisé en séparant la gestion du state et le code de présentation. Les composants dumb se concentrent uniquement sur la présentation et le rendu de l'UI. Ils reçoivent leurs données via les `inputs` et émettent des événements via les `outputs`. Les composants smart gèrent le state et sont par nature plus spécifiques à l'application, jouant souvent le rôle de contrôleur (accès aux services, fetching de données, etc.). Les pages de l'application sont ainsi souvent des composants smart. Documentation: [Smart Components vs Presentational Components](https://blog.angular-university.io/angular-2-smart-components-vs-presentation-components-whats-the-difference-when-to-use-each-and-why/) ## La structure du projet #### La structure LIFT La structure proposée s'appuie sur la recommandation officielle [LIFT](https://angular.io/guide/styleguide#lift). > Do structure the application such that you can Locate code quickly, Identify the code at a glance, > keep the Flattest structure you can, and Try to be DRY. * **L**ocate: Organisez le code pour que la localisation des éléments soit intuitive, simple et rapide. * **I**dentify: Nommez le fichier pour identifier instantanément ce qu'il représente et ce qu'il contient. Pour ce faire, le nom du fichier doit être descriptif. Évitez les fichiers mélangeant plusieurs composants ou services. * **F**lat: Conservez la structure la plus à plat aussi longtemps que possible. Envisagez de créer des sous-dossiers lorsqu'un dossier atteint sept fichiers ou plus. * **T**-DRY (Try to be DRY): Respectez le principe DRY. Évitez toutefois de sacrifier la lisibilité juste pour suivre à la lettre le principe DRY. #### L'arborescence des fichiers * api + models - entity-a.api.model.ts - entity-b.api.model.ts + services - domain-a.api.service - domain-b.api.service * app + components - ui * shared-button + shared-button.component.html|scss|ts + constants - constant-a.ts - constant-b.ts + directives - shared-directive.ts + enums - enum-a.ts - enum-b.ts + features - feature-a * components + scoped-component-a - scoped-component-a.component.html|scss|ts + scoped-component-b - scoped-component-b.component.html|scss|ts * models + scoped-model-a.model.ts + scoped-model-b.model.ts * pages + page-a - page-a.page.html|scss|ts + page-b - page-b.page.html|scss|ts * services + scoped-service-a.service.ts + scoped-service-b.service.ts * feature-a.component.html|scss|ts * feature-a.routes.ts + guards - auth.guard.ts - module-import.guard.ts - no-auth.guard.ts + helpers - helper-a.ts - helper-b.ts + interceptors - token.interceptor.ts - error.interceptor.ts + models - model-a.ts - model-b.ts + services - service-a.service.ts - service-b.service.ts + pages - page-not-found * page-not-found.page.html|scss|ts + pipes - shared-pipe.ts + app.component.html|scss|ts + app.routes.ts * assets + i18n - en.json - fr.json - nl.json + documents - file-a.pdf - file-b.pdf + icons - custom-icon-a.svg - custom-icon-b.svg + images - image-a.svg - image-b.svg * favicon.icon * index.html * maint.ts * styles.scss Tous vos composants, vos services, directives, ... doivent être déclarés en tant que **standalone**. Suivez l'approche **CDD (Component-Driven Development) pour organiser vos composants**. Adoptez le **on push change detection strategy** pour améliorer les performances de votre application. Utilisez la nouvelle syntaxe offert par le **control-flow** pour simplifier et booster la lisibilité de votre code. **Organisez votre code par feature**. Cela permet de regrouper les composants, services, modèles et autres par domaine. **Alignez vos features sur vos routes.** Cela permet de faciliter la navigation dans votre application. **Séparez le code propre de vos apis** dans un dossier distinct de votre application. **Regroupez vos composants de base partagés** dans un sous-dossier **`ui`**. Si vous avez des pages de CRUD, **créez des pages distinctes pour la création, l'édition et le détail**. Cela permet de séparer les responsabilités et de rendre le code plus facile à maintenir. Note: Créez un composant de formulaire réutilisable partagé entre la création et l'édition. Exemple concret Si vous avez les routes suivantes dans votre application : ``` - /dashboard - /users - /users/list - /users/detail/:id - /users/create - /users/edit/:id ``` Alors organisez votre application comme ceci : ``` src/ |-- app/ | |-- features/ | | |-- dashboard/ # Feature module for the /dashboard route | | | |-- pages/ # Folder for page components in the dashboard feature | | | |-- components/ # Folder for reusable components specific to the dashboard feature | | | |-- services/ # Folder for services specific to the dashboard feature | | |-- users/ # Feature module for the /users route | | | |-- pages/ # Folder for page components in the users feature | | | | |-- create/ # Page used to create a new user | | | | |-- edit/ # Page used to edit an existing user | | | | |-- list/ # Page used to list all users | | | | |-- detail/ # Page used to display the details of a user | | | |-- components/ # Folder for reusable components specific to the users feature | | | |-- services/ # Folder for services specific to the users feature |-- ... ``` Documentation: [Angular File Structure and Best Practices](https://medium.com/%40shijin_nath/angular-right-file-structure-and-best-practices-that-help-to-scale-2020-52ce8d967df5) [Tips for Structuring Your Angular Project](https://www.telerik.com/blogs/angular-basics-tips-structuring-angular-project) [How to define a highly scalable folder structure for your Angular project](https://itnext.io/choosing-a-highly-scalable-folder-structure-in-angular-d987de65ec7) [Angular schematics extension VS Code](https://marketplace.visualstudio.com/items?itemName=cyrilletuzi.angular-schematics) [Github: Angular Folder Structure](https://github.com/adnan-halilovic/angular-folder-structure) [Angular App Architecture: Don’t get Lost in Structure](https://youtu.be/FVYJ6D4dnbU?t=2129) [How to structure your Angular apps like a Googler](https://www.youtube.com/watch?v=7SDpTOLeqHE) [Angular.io: Workspace and project file structure](https://angular.io/guide/file-structure) [Angular.io Styleguide: Application structure and NgModules](https://angular.io/guide/styleguide#lift) [Angular project structure best practice](https://stackoverflow.com/a/52933684/1152632) ## Règles d'Architecture ### Routing & Navigation Le **nommage des dossiers features doit refléter les routes** et leurs structures. Utilisez `WithComponentInputBinding` pour lier les paramètres de route en tant qu’inputs. Utilisez le lazy loading pour toutes les routes sauf la route par défaut. N'hésitez pas à créer un niveau de route pour gérer des zones de votre application (admin, user, ...). ### Les formulaires Les reactives forms et les template-driven forms sont deux approches valides. Toutefois, le mieux est de choisir une approche et de s'y tenir. En conséquence, utilisez toujours les **les template-driven forms**. Ils sont déclaratifs, simple et sont facilement compatibles avec les signals. Documentation [Prefer Template-Driven Forms | Ward Bell | ng-conf 2021](https://www.youtube.com/watch?v=L7rGogdfe2Q) [in code](https://stackblitz.com/edit/angular-kkatri?file=src%2Fapp%2Fapp.component.ts) Documentation [How To Use Reactive Forms in Angular](https://www.digitalocean.com/community/tutorials/angular-reactive-forms-introduction) Documentation [make your Angular Reactive Forms more... \*Reactive\*](https://www.youtube.com/watch?v=4WBV-7PJ0jM) Documentation [Template-Driven Form Validation Example](https://jasonwatmore.com/post/2022/12/19/angular-14-template-driven-form-validation-example) Documentation [Reactive Forms Validation Example](https://jasonwatmore.com/post/2022/11/18/angular-14-reactive-forms-validation-example) Documentation [How To Use Custom Form Validation in Angular](https://www.digitalocean.com/community/tutorials/angular-custom-validation) Documentation [Form Validation Done Right | Ward Bell | ng-conf 2022](https://www.youtube.com/watch?v=EMUAtQlh9Ko) Documentation [Vest - Declarative validations framework](https://github.com/ealush/vest) [[Angular: sandbox]](https://codesandbox.io/s/vest-angular-dht77?file=/src/app/app.component.ts:104-109) [Ngc validate: the glue for Vest and Angular](https://github.com/wardbell/ngc-validate) ### Styling & CSS Utilisez Tailwind CSS pour un style utility-first. Avec cette approche, vous ne devez pas écrire de CSS personnalisé. Si nécessaire, vous pouvez ajouter des classes de style partagées réutilisant les utilitaires de tailwind via le fichier tailwind.config.js. Note: Le tri des classes Tailwind dans le template peut être géré via un plugin VS Code `prettier-plugin-tailwindcss`. ### Gestion des états partagés N’utilisez pas de librairies de store externes. **Utilisez des services partagés**. **Utilisez des signaux** pour gérer les states en exposant uniquement des signaux en read-only pour la lecture des states et des méthodes publiques pour les actions sur les states. ### Gestion des Erreurs Rendez les erreurs compréhensibles pour l’utilisateur final. Utilisez un gestionnaire d’erreurs global pour les exceptions non interceptées. Gérez les erreurs des appels HTTP dans les ApiServices. Transformez-les pour qu’elles soient compréhensibles et utiles, puis retournez des données cohérentes.