Aller au contenu

L'architecture Angular parfaite ?

“Architecture” ici fait rĂ©fĂ©rence Ă  la structure de fichiers, Ă  la façon dont vous la dĂ©coupez en diffĂ©rents composants, services, modules etc et de l’endroit oĂč vous les placez. Aussi, ce qui va suivre est basĂ© sur mon expĂ©rience personnelle, et doit ĂȘtre considĂ©rĂ© comme une boĂźte Ă  outils qui, comme toute approche, prĂ©sente des avantages et des inconvĂ©nients.

Chaque fois que je crée ou modifie une architecture Angular, je me pose 3 questions :

  1. Est-ce que les devs’ trouveront mon architecture agrĂ©able Ă  utiliser au quotidien ?
  2. Est-ce qu’elle pourra encaisser les Ă©volutions Ă  venir ?
  3. Est-ce que mon architecture reflÚte mon besoin métier au mieux ?

Chacun de mes choix est confronté à ces 3 questions.

Si les rĂ©ponses sont “oui”, alors je sais que mon architecture est parfaite, ou plutĂŽt qu’elle est parfaitement adaptĂ©e Ă  mon contexte mĂ©tier actuel.

Car oui, la rĂ©ponse Ă  ces 3 questions dĂ©pendent du logiciel que l’on doit crĂ©er et de l’équipe en charge. Ce que je veux dire par lĂ  c’est qu’une certaine architecture pourrait trĂšs bien fonctionner dans une situation mais pas une autre car le contexte mĂ©tier (qu’on appelle la complexitĂ© inhĂ©rente) est diffĂ©rent. Ainsi, deux architectures dans deux contextes diffĂ©rents peuvent varier drastiquement et il n’existe pas d’architecture qui couvre 100% des cas.

Cependant, les 3 questions que j’ai Ă©noncĂ© plus haut ainsi que des principes Ă©prouvĂ©es vont nous permettre d’atteindre notre objectif : concevoir l’architecture Angular parfaite pour votre besoin.

Dans cette article, nous allons tenter de comprendre pourquoi ces questions sont importantes et surtout comment y répondre !


Est-ce que mon architecture est agréable ?

L’agrĂ©abilitĂ© ressentie par les devs est primordiale dans vos architectures et doit ĂȘtre au cƓur de chacune de vos dĂ©cisions. Cela fait partie d’un principe qu’on appelle la Developer eXperience (DX). C’est Ă  dire l’aisance qu’ont les devs Ă  faire leur mĂ©tier.

Pour moi, la DX est la top prio. Nous vivons dans un milieu oĂč les technologies et les besoins mĂ©tiers Ă©voluent constamment, l’impact de ça c’est que vous allez rĂ©guliĂšrement mettre votre code Ă  jour car l’API d’une librairie ou la version de votre framework ont changĂ©. Egalement, d’un point de vue business, vos PO/PM vous demanderont d’ajouter des fonctionnalitĂ©s ou d’en modifier trĂšs rĂ©guliĂšrement. Bref, on passe nos journĂ©es Ă  modifier notre code et notre architecture de maniĂšre micro ou macro.

Et changer les choses dans une codebase c’est le dĂ©but des embrouilles :

  • introduction de bugs dus Ă  des effets de bords
  • lassitude, agacement ou inquiĂ©tudes des devs qui doivent replonger dans un code obscur

Une mauvaise architecture entraĂźne une mauvaise DX qui entraĂźne une Ă©quipe anxieuse et peu efficace. On aura peur de modifier les choses par incomprĂ©hension de la codebase et/ou on aura la flemme de “faire propre” car les patterns sont lourds : c’est le dĂ©but de la dette technique.

Ainsi, l’importance d’avoir une architecture agrĂ©able Ă  utiliser est primordiale pour la santĂ© mentale des devs et donc la pĂ©rennitĂ© du business.

Si l’équipe de dĂ©veloppement trouve la structure de fichiers cohĂ©rentes et facile Ă  naviguer alors elle pourra ajouter, modifier ou supprimer des Ă©lĂ©ments plus rapidement et sans crainte d’effet de bord.

Ce qui participe Ă©galement Ă  l’agrĂ©abilitĂ© de navigation dans une architecture c’est de garder le nombre de fichiers et dossiers bas tout en respectant la separation of concerns. La multiplication de fichiers peut tout Ă  fait rĂ©pondre Ă  un besoin, mais elle peut Ă©galement ĂȘtre vecteur d’erreurs. On doit trouver des noms adĂ©quats, on doit faire attention Ă  ne pas mĂ©langer les responsabilitĂ©s des fichiers, et au-delĂ  de ça cela apporte de la lourdeur Ă  la navigation entre fichiers.

AprĂšs tout, si Angular et NgRx s’évertuent Ă  rĂ©duire le boilerplate de leurs produits, c’est parce qu’ils ont bien compris l’importance d’avoir un workspace lĂ©ger.

Ne vous mĂ©prenez pas sur ce que je dis, je ne vous incite pas Ă  avoir un seul gros composant, service ou store avec tout dedans. Je vous incite Ă  dĂ©couper les choses quand il y a rĂ©ellement une raison de le faire. Lorsque vous vous apprĂȘtez Ă  dĂ©couper un fichier en plusieurs , posez vous la question du gain et utilisez votre bon sens. Gardez la separation of concerns comme indicateur.

Ne sous-estimez pas l’importance de la DX. C’est le nerf de la guerre. Posez vous la question de savoir si une nouvelle personne qui intĂšgre l’équipe arriverait Ă  comprendre l’architecture frontend en quelques minutes.

Est-ce que mon architecture est Ă©volutive ?

Je le disais en introduction, les besoins mĂ©tier Ă©voluent en permanence. Une feature en plus, une autre utilisĂ©e Ă  plusieurs endroits qui devient un peu diffĂ©rente selon lĂ  oĂč elle est consommĂ©e.

Le problĂšme c’est que ni les devs ni les PO/PM ne voient dans le futur, donc oubliez tout de suite l’idĂ©e que vous ferez une architecture qui encaissera tous les changements futurs. Ca n’arrivera pas.

Alors on pourrait se dire que de sortir l’artillerie lourde dĂšs le dĂ©part est une bonne idĂ©e. Partons sur une architecture hexagonale en monorepo et full microfrontends. Au moins on aura quelque chose d’évolutif.

C’est peut-ĂȘtre le cas, mais cela implique que l’équipe, incluant vous-mĂȘme, soit hautement qualifiĂ©s pour entretenir ce genre d’architecture. Et, spoiler alert, ça n’arrive pas non plus ou dans de trop rares cas.

Une architecture Ă©volutive est avant tout quelque chose de facilement incrĂ©mentale et dont on a la maĂźtrise. C’est Ă  dire quelque chose qui diminue les contraintes : si on veut poser une nouvelle brique par dessus de maniĂšre isolĂ©e ou non, on peut le faire.

Si je devais donner un choix stratĂ©gique offrant beaucoup de valeurs sans demander une maturitĂ© technique dĂ©mesurĂ©e, c’est l’utilisation d’un monorepo.

Un monorepo, c’est le fait d’avoir un seul repository git avec plusieurs apps et libs. Cela permet notamment de faciliter le partage et la rĂ©utilisation de code entre vos diffĂ©rentes briques techniques et de profiter d’un Ă©cosystĂšme trĂšs Ă©volutif. Ma solution prĂ©fĂ©rĂ©e est NX.

NX est un Ă©cosystĂšme facilitant la mise en place et le maintient d’architecture web. Vous profiterez de ses outils qui permettent d’intĂ©grer facilement les outils et patterns populaires du web (Angular, React, Jest, Cypress, Storybook
). NX est surtout utilisĂ© dans les architectures monorepo mais vous pouvez tout Ă  fait utiliser NX pour une simple application.

Personnellement je l’utilise beaucoup dans mon quotidien et contrairement Ă  ce qu’il se dit ce n’est pas uniquement adaptĂ© aux gros projets. Mais ce n’est pas trivial non plus, cela nĂ©cessite une bonne coordination entre les membres de l’équipe.

Je prévois un article dédié sur le sujet ! Stay tuned!

A part ça, une erreur que je vois souvent et qui impacte nĂ©gativement l’évolutivitĂ©, c’est la mauvaise comprĂ©hension du principe DRY (Don’t Repeat Yourself).

J’ai travaillĂ© pour une sociĂ©tĂ© qui fabriquait des logiciels en marque blanche. En gros, on avait plusieurs clients, chacun dĂ©sirant une application dĂ©diĂ©e avec certaines fonctionnalitĂ©s. Ces fonctionnalitĂ©s Ă©taient parfois les mĂȘmes entre les diffĂ©rentes apps (donc pour les diffĂ©rents clients), parfois non, ou parfois c’était les mĂȘmes mais avec quelques diffĂ©rences subtiles. Donc les apps avaient quelques bases communes entre elles mais aussi beaucoup de spĂ©cificitĂ©s.

Le choix (qui avait Ă©tĂ© fait bien avant mon arrivĂ©) a Ă©tĂ© de concevoir une seul app Angular avec toutes les fonctionnalitĂ©s Ă  l’intĂ©rieur, chaque client partageait les mĂȘmes pages oĂč un tas de if se trouvaient et un fichier de configs par client qui pilotait l’activation des fonctionnalitĂ©s Ă  coup de shouldActivateThisFeature: true.

RĂ©sultat : on s’est retrouvĂ©s avec une app gigantesque avec des fichiers de 3k lignes qui contenaient les diffĂ©rentes logiques des diffĂ©rents clients. C’était impossible Ă  tester, trĂšs difficile Ă  isoler et l’évolution Ă©tait trĂšs limitĂ©e.

Comment on en est arrivĂ© lĂ  ? Parce qu’il y a une incomprĂ©hension sur la dĂ©finition de DRY.

Ce n’est pas parce que quelque chose Ă  le mĂȘme nom que c’est la mĂȘme chose.

Ici, les applications avaient le mĂȘme nom, les pages et fonctionnalitĂ©s aussi, donc on a considĂ©rĂ© que c’était la mĂȘme chose. On a donc tout mis dans une seule et mĂȘme app.

Une solution viable aurait Ă©tĂ© de faire une app distincte par client oĂč chacune d’entre elle dĂ©clarait son propre routing avec ses propres pages et de considĂ©rer chaque fonctionnalitĂ© comme une librairie consommable par les apps.

Pensez toujours Ă  respecter une separation of concerns dans vos applications. Si deux features semblent trĂšs similaires mais divergent en quelques points, c’est souvent le signal que ce sont en rĂ©alitĂ© deux features diffĂ©rentes.

Est-ce que mon architecture reflÚte mon besoin métier ?

Ce point lĂ  est la rĂ©sultante des deux prĂ©cĂ©dents. En fait, une architecture qui reflĂšte le besoin mĂ©tier est la porte d’entrĂ©e vers une architecture agrĂ©able et Ă©volutive.

Ceci est l’un des principes du DDD (Domain Driven Design) : concevoir une application en suivant le contexte mĂ©tier. Cela veut dire que mon architecture est le reflet de mon business, si bien qu’un PO/PM devrait pouvoir se balader dans mon repository et comprendre son architecture (j’exagĂšre un peu mais pas tant).

Il y a une phrase d’Arnaud Lemaire que j’aime beaucoup et qui rĂ©sume une architecture DDD rĂ©ussie : des petits changements mĂ©tiers doivent entraĂźner des petits changements dans la codebase et des grands changements mĂ©tiers doivent entraĂźner des grands changements dans la codebase.

Bon, ceci Ă©tant dit, je ne ferai pas une explication exhaustive du DDD, dĂ©jĂ  parce que ça pourrait tenir dans un bouquin, mais aussi parce que je ne prĂ©tends pas pouvoir le faire. En revanche, je peux vous expliquer comment appliquer certains de ses principes Ă  la crĂ©ation d’architecture !

Il y a notamment deux voies pour mettre en place une architecture qui suit la logique métier :

  1. un découpage de dossiers qui suit la navigation utilisateur
  2. de la colocation de code

Le premier point consiste Ă  avoir un folder routes avec les diffĂ©rentes routes de votre applications (vos pages). Et dans chacune des routes on a potentiellement des sous routes. En somme, le code de la page domain.com/products-list sera contenu dans routes/products-list. Certains frameworks disposent de ce principe de maniĂšre naturelle, par exemple NextJS ou AnalogJS. C’est ce qu’on appelle le file base routing. C’est trĂšs intĂ©ressant car ainsi la logique de notre structure de fichiers est liĂ©e et pilotĂ©e par le mĂ©tier, l’évolution de notre codebase sera donc toujours fait au mĂȘme rythme que le mĂ©tier tout en ayant quelque chose de facilement comprĂ©hensible. L’avantage est que si vous avez un ticket de bug sur une page, vous saurez immĂ©diatement oĂč intervenir.

Le second point concerne la colocation de code. Cela fait rĂ©fĂ©rence au fait de regrouper le code et les fichiers traitant du mĂȘme domaine mĂ©tier au mĂȘme niveau dans votre arborescence de fichiers Cela assure une comprĂ©hension claire des dĂ©pendances des diffĂ©rentes parties de votre code et des potentielles effets de bords.

Nous allons voir dans la section suivante des exemples d’architectures qui mettent en pratique tous les principes Ă©numĂ©rĂ©es jusqu’ici.

La mise en pratique

Je vous parlais de file base routing, voici comment faire l’équivalent dans Angular en partant d’une application en version 16 :

src/
    app/
        routes/
            login/
                login.route.ts
            my-account/
                profile/
                    profile.route.ts
                purchase-history/
                    purchase-history.route.ts
                my-account.route.ts
                my-account.routing.ts
            product/
                product.route.ts
            product-list/
                product-list.route.ts
        app.config.ts
        app.component.ts
        app.routing.ts
    index.html
    main.ts
 angular.json
 package.json

Ici, la structure de mes fichiers suit parfaitement la navigation de l’utilisateur dans l’application. Si je suis sur la page domain.com/product alors je sais immĂ©diatement oĂč se trouve le code impliquĂ©. Et Ă  l’intĂ©rieur de chaque folder on retrouve la route en question avec leurs sous routes Ă©ventuelles (c’est le cas pour my-account). C’est le fichier app.routing.ts qui pilote le routing de premier niveau et celui de second niveau est gĂ©rĂ© par des fichiers comme my-account.routing.ts par exemple.

C’est trĂšs pratique pour l’agrĂ©abilitĂ© comme je le disais plus haut, si vous avez un bug sur une page alors vous pourrez identifier en un clin d’Ɠil oĂč intervenir. Vous avez sans doute remarquĂ© quelque chose : je ne suis pas la convention Angular et je nomme mes routes en xxx.route.ts. Cela me permet d’identifier rapidement ce qu’est ce fichier plutĂŽt que de nommer tous mes composants xxx.component.ts. Je vous invite Ă  faire de mĂȘme !

Maintenant, imaginez que vous avez un header et footer prĂ©sents sur toutes vos pages et que vous voulez en faire deux composants. Ces composants vont ĂȘtre utilisĂ©s dans le AppComponent. Mais oĂč allez vous les placer dans votre architecture ?

La rĂ©ponse est : au plus proche de lĂ  oĂč ils sont utilisĂ©s. C’est le principe de colocation de code !

src/
    app/
        routes/
        app.config.ts
        app.component.ts
        app.routing.ts
        footer.component.ts
        header.component.ts
    index.html
    main.ts
 angular.json
 package.json

👆 Les composants sont au mĂȘme niveau de leur endroit d’utilisation

Ainsi, des xxx.component.ts vivant Ă  cĂŽtĂ© d’un xxx.route.ts signifient qu’ils sont utilisĂ© dedans. Tout simplement ! Pas besoin d’utiliser de dossier shared ou core dans ce cas-lĂ . Cela ne ferait que rajouter du bruit inutile.

Je suis cette mĂȘme logique pour toutes les routes et pas uniquement pour les composants :

src/
    app/
        routes/
            login/
            my-account/
                profile/
                purchase-history/
                my-account.route.ts
                my-account.routing.ts
                sidebar.component.ts
            product/
            product-list/
                product-list.route.ts
                product-list.service.ts
                product-list.store.ts
        app.config.ts
        app.component.ts
        app.routing.ts
        footer.component.ts
        header.component.ts
        initializer.service.ts
        jwt.interceptor.ts
    index.html
    main.ts
angular.json
package.json

Et oui ! Je parie que vous n’aviez jamais vu ce genre d’approche avant. Et bien je peux vous assurer qu’aprĂšs avoir essayĂ© des tas d’approche, celle-ci apporte la meilleure DX au quotidien et sur le long terme. Ici donc, tout est aplati, on minimise les dossiers et on suit une rĂšgle simple : les fichiers qui sont utilisĂ©s ensemble sont cĂŽte Ă  cĂŽte. Par exemple, j’ai besoin de crĂ©er un interceptor pour ajouter mon token JWT Ă  chaque requĂȘte HTTP. Cet interceptor est utilisĂ© dans mon app.config.ts donc je le place Ă  son niveau ! Il en va de mĂȘme pour les guards, les services etc.

C’est de la colocation de code. Le but est de comprendre en un clin d’Ɠil les responsabilitĂ©s et dĂ©pendances de mes fichiers.

Vous allez peut-ĂȘtre vous dire qu’on va potentiellement avoir des dossiers avec 15 fichiers Ă  l’intĂ©rieur, voire plus. En effet, et devinez quoi : c’est vraiment pas grave, au contraire ! Croyez moi, les devs comprendront bien plus vite ce dĂ©coupage lĂ  que d’obscurs dossiers core ou autres qui entraĂźnent des rĂ©flexions supplĂ©mentaires et donc de potentielles erreurs et c’est lĂ  que la dette technique s’accumule.

Prenez ces conseils comme des indications, si votre Ă©quipe se sent plus Ă  l’aise avec un dossier par-ci par-lĂ  alors faites le, mais gardez toujours en tĂȘte la DX et de rĂ©duire les chances d’augmenter la dette technique.

Bon, on garde les fichiers en commun ensemble au mĂȘme endroit, trĂšs bien, mais qu’en est-il des Ă©lĂ©ments partagĂ©s ?

Typiquement :

  • des composants UI
  • des features
  • des utilitaires

Une solution est un dossier shared au mĂȘme niveau que routes qui contient les Ă©lĂ©ments partagĂ©s de l’application.

src/
    app/
        routes/
        shared/
            components/
            features/
            utils/
        app.config.ts
        app.component.ts
        app.routing.ts
        footer.component.ts
        header.component.ts
        initializer.service.ts
        jwt.interceptor.ts
    index.html
    main.ts
angular.json
package.json

Ainsi en tant que dev, si un élément est réutilisé à plusieurs endroits alors je le mettrais ici.

Par exemples les composants :

src/
    app/
        routes/
        shared/
            components/
                buttons/
                cards/
                form/
                    input/
                    textarea/
                table/
            features/
            utils/
        app.config.ts
        app.component.ts
        app.routing.ts
        footer.component.ts
        header.component.ts
        initializer.service.ts
        jwt.interceptor.ts
    index.html
    main.ts
angular.json
package.json

Ces composants représentent des éléments qui ne sont pas attachés à la logique métier exactement comme les composants de Angular Material par exemple.

Il existe des solutions encore plus puissantes comme les design system. Un design system gĂšre l’ensemble de l’apparence de votre mĂ©tier, on y trouve les composants, les styles et les rĂšgles UI. Une mĂ©thodologie Ă©prouvĂ©e pour la crĂ©ation de design system est l’Atomic Design. Je n’en parlerai pas ici car ce n’est pas le sujet mais je vous invite Ă  faire vos propres recherches !

Pour les utilitaires, rien de bien compliqué, on a des folders qui correspondent à nos besoins utilitaires :

src/
    app/
        routes/
        shared/
            components/
            features/
            utils/
                converting/
                formatting/
                testing/
        app.config.ts
        app.component.ts
        app.routing.ts
        footer.component.ts
        header.component.ts
        initializer.service.ts
        jwt.interceptor.ts
    index.html
    main.ts
angular.json
package.json

Pour les features, c’est la mĂȘme idĂ©e. Une feature est un regroupement d’élĂ©ments mĂ©tiers rĂ©utilisables. Cela peut ĂȘtre des stores, des services, de la UI ou mĂȘme une combinaison de tout cela.

src/
    app/
        routes/
        shared/
            components/
            features/
                payment/
                    cart.component.ts
                    cart.store.ts
                    index.ts
                    payment.service.ts
                user/
                    has-role.guard.ts
                    index.ts
                    has-logged-in.guard.ts
                    user.store.ts
            utils/
        app.config.ts
        app.component.ts
        app.routing.ts
        footer.component.ts
        header.component.ts
        initializer.service.ts
        jwt.interceptor.ts
    index.html
    main.ts
angular.json
package.json

Dans cette exemple nous avons deux features, payment et user. Chacun ayant un index.ts pour exposer l’API aux consommateurs. On peut facilement imaginer que dans mon application j’ai besoin des informations du user Ă  plusieurs endroits, ainsi j’importe ce dont j’ai besoin depuis la feature user. Il en va de mĂȘme pour payment, le service pourrait exposer des mĂ©thodes de paiement dĂ©clenchable Ă  plusieurs endroits de mon application, et on peut imaginer que le cart soit affichable Ă  plusieurs endroits Ă©galement.

Important : entendons nous bien, je possĂšde un folder shared mais pas de SharedModule ou que sais-je encore. Le folder shared apporte l’indication que les Ă©lĂ©ments Ă  l’intĂ©rieur sont rĂ©utilisĂ©s Ă  plusieurs endroits, mais pas qu’ils sont tous packagĂ©s ensemble ! Ils ont tous leurs propres responsabilitĂ©s et ne communique pas ensemble, comme les Ă©lĂ©ments dans routes par exemple.

Bref, chaque feature est un sous-ensemble de mon domaine d’application et contient des Ă©lĂ©ments rĂ©utilisables. Dans l’idĂ©e si une fonctionnalitĂ© Ă©merge pour une seule page de l’application alors elle ne devrait pas ĂȘtre dans shared/features/xxx. Par exemple si un administrateur Ă  la possibilitĂ© de supprimer un user en faisant un http.delete sur un endpoint user/${id} via une page admin/delete-users alors en thĂ©orie cette logique devrait ĂȘtre contenue dans routes/admin/delete-users/delete-users.service.ts. Donc pas dans la feature user car cette fonctionnalitĂ© n’est pas partagĂ©e.

Je dis bien “en thĂ©orie” car c’est typiquement sur ce genre de choix oĂč on va adapter son architecture selon le mĂ©tier et les prĂ©fĂ©rences de l’équipe, on pourrait prĂ©fĂ©rer mettre cette logiquement Ă©galement dans la feature user pour certaines raisons. Et en poussant l’idĂ©e un peu plus loin, on pourrait mĂȘme avoir ceci :

src/
    app/
        design-system/
            components/
                buttons/
                cards/
                form/
                table/
            styles/
        features/
            payment/
            user/
        routes/
            login/
            my-account/
            product/
            product-list/
        utils/
            converting/
            formatting/
            testing/
        app.config.ts
        app.component.ts
        app.routing.ts
        footer.component.ts
        header.component.ts
        initializer.service.ts
        jwt.interceptor.ts
    index.html
    main.ts
angular.json
package.json

Ici, j’ai carrĂ©ment fait sauter la notion de shared. Les composants sont dĂ©placĂ©s dans un design-system, utils est directement Ă  la racine ainsi que features signifiant qu’ils pourraient ĂȘtre partagĂ©s ou non.

C’est, Ă  mon sens, une architecture trĂšs solide (hormis monorepo) si l’équipe Ă  un haut niveau de maturitĂ©. Le risque rĂ©side dans le fait de perturber l’agrĂ©abilitĂ© au quotidien, j’imagine facilement qu’une feature devienne mal isolĂ©e et qu’on y introduise des notions qui ne devraient pas y ĂȘtre. PrĂ©fĂ©rez la colocation de code tant que c’est possible.

Pour aller plus loin

Il y a beaucoup de mĂ©thodologies dont je n’ai pas parlĂ© :

  • microfrontends
  • clean architecture
  • architecture hexagonale

Ce sont des sujets poussĂ©s et qui nĂ©cessite un haut niveau de maturitĂ© technique mais qui peuvent apporter beaucoup Ă  la pĂ©rennitĂ© de vos projets. Assurez vous de maĂźtriser les points prĂ©cĂ©dents avant pour comprendre l’essence d’une bonne architecture avant de vous lancer dans ces recherches.

Résumé

  • Pensez toujours Ă  vos collĂšgues qui rĂ©cupĂšreront votre code en priorisant la DX
  • Si je reçois un ticket qui me dit “il y a un bug sur cette feature”, je dois trouver oĂč intervenir en quelques secondes
  • Si une nouvelle personne intĂšgre l’équipe (et quelque soit son niveau de sĂ©nioritĂ© Ă  peu de chose prĂšs) alors elle doit comprendre l’architecture en quelques minutes
  • L’organisation de vos fichiers doit ĂȘtre logique et consistant
  • MĂ©fiez vous du DRY qui est parfois trompeur
  • Mettez un folder routes qui suivra la navigation de l’utilisateur
  • Aplatissez vos fichiers et utilisez de la colocation de code au maximum tant que cela respecte la separation of concerns
  • Utilisez un dossier shared pour y mettre des sous dossiers components, utils, features etc contenant vos Ă©lĂ©ments partagĂ©s
  • Alternativement, vous pouvez mettre ces sous dossiers directement Ă  la racine au mĂȘme niveau que routes
  • ConsidĂ©rez sĂ©rieusement l’approche monorepo avec NX

Conclusion

Une architecture parfaite pour votre business mettra du temps Ă  ĂȘtre mise en place. Il faudra faire, dĂ©faire et refaire rĂ©guliĂšrement. Mais si vous suivez ces conseils et que vous priorisez la DX alors tout ce passera pour le mieux et vos collĂšgues et clients/responsables vous remercieront !