Une nouvelle façon d'architecturer son application

Certaines parts d'ombre subsistent

a marqué ce sujet comme résolu.

Bonsoir,

Cela fait quelques temps que j'essaye de me pencher sur le Javascript en profondeur notamment sur les framework / librairies telles que AngularJS (dans sa version 1), React ou encore Vue. Récemment je suis tombé sur une vidéo de chez Facebook qui introduit une nouvelle façon d'architecturer son application : le modèle Flux qui vient s'opposer au modèle MVC.

Je comprends les différents éléments nécessaires à ce type d'architecture (dispatcher / store / actions) cependant ce que j'ai du mal à comprendre c'est en quoi c'est si différent de ce que l'on fait actuellement. Flux veut que le state d'une application ne puisse être modifié que dans des stores via des events qui sont déclenchées depuis la vue puis relayés par le dispatcher jusqu'au store. Jusque là ça va. Cependant ce système de centralisation de "mutation" de l'état d'une application, et bien on l'a aussi sur le modèle MVC non ?

Par exemple on peut très bien mimer ce comportement sur Angular : on aurait un service (= store) qui aurait des méthodes pour mettre à jour le state. Ces méthodes ne seront appelées que par le controller (+/- actions) eux même appelés par la vue.

En ce qui concerne le pourquoi de Flux vs MVC pour moi je vois deux choses :

  • Eviter le two-way binding.
  • Garder les mutations du state au même endroit = en cas de bug moins de temps à savoir d'où sa vient et on sait quel event a été appelé et donc quelle méthode est incriminée.

Je n'ai pas vraiment de question toute faite c'est plus une demande d'éclaircissement en général sur le réel + d'une architecture telle Flux. J'ai beau lire les tutos, la docs officiel la seule chose pour l'instant qui n'est pas clair c'est en quoi ce que l'on fait avec Flux n'est pas possible de faire avec un framework MVC du style AngularJS.

Je vous remercie :)

Eviter le two-way binding.

Oui, c'est le plus gros point fort de flux à l'usage. On ne s'en rend pas bien compte au début (je venais d'Angular 1 moi aussi), on a l'impression que c'est chiant et tout, mais ça évite un plat de spaghetti indémerdable. Quand une app Angular grossit, il est très très difficile de comprendre (tracker) d'où proviennent les données. Avec flux tu as un seul point d'interception pour le comprendre : ton reducer. C'est lui et lui seul qui va mettre à jour le state.

Ensuite pour la question générale, je pense que c'est possible avec Angular, mais en esquivant des fonctionnalités d'Angular (notamment le 2-way binding). Donc tu as des vues qui ne font que lire des données et les afficher, et dispatcher des actions. Dans ce cas là, tu vas te retrouver avec une vue très simple bannissant les ng-bind. Et par contre, ton contrôleur va grossir avec un ensemble de méthodes de dispatch (en fait il va appeler des primitives directement sur le service).

Ca me paraît jouable mais ça impose plein de trucs :

  • faire attention, dans la vue, à ne faire que "lire" des données, pas de binding
  • dans le contrôleur, ne conserver strictement aucun état, et avoir uniquement des dispatch-like (en gros service.setData())
  • dans le service, écrire des méthodes d'extraction des données : "les personnes dont le nom commence par 'A'" (ou alors dans le contrôleur ? on voit que ça commence à être merdique déjà).

Donc ça implique de s'imposer beaucoup de contraintes, et pour peu que tu bosses à plusieurs, c'est mort.

Aussi, si tu as besoin de mettre à jour les données de ton service depuis plusieurs points d'accès (une API, une websocket, une action utilisateur) ça va vite être le bordel.

L'idée de Flux c'est de vraiment bien séparer les responsabilités. Ta vue ne fait qu'afficher des données et dispatcher des actions, ton reducer vient mettre à jour le state en fonction des actions reçues, ton "sélecteur" extrait les informations du state pour les passer à la vue. Afin d'être certain que si des portions du state dont tu te fous changent, ta vue n'est pas impactée.

L'avantage, c'est qu'une grande partie de tout ça peut s'écrire sous forme de pures fonctions : une même entrée => une même sortie. Je pense notamment aux vues (et aux sélecteurs). Ce qui rend ton code beaucoup plus simple à débugger et à tester unitairement. Et ça permet aussi de bénéficier gratuitement de mémoisation (cf. reselect par exemple) entre autres choses.

Le seul truc qui m'ennuie dans Flux, c'est que comme il existe différentes implémentations, on n'est pas vraiment guidé au début, et on a vite tendance à faire des conneries. Contrairement à Angular, Meteor, Ember, etc. qui te mettent sur des rails.

En réponse à ce problème, si jamais il t'ennuie également, il existe Elm. Le langage intègre lui-même ("nativement" si je puis dire) ce système Flux de CQRS. Si tu regardes ici on retrouve le triplet model, view, update :

1
StartApp.start { model = 0, view = view, update = update }

Avec la vue qui décrit uniquement la sortie en fonction du model et qui envoie des actions :

1
2
3
4
5
6
view address model =
  div []
    [ button [ onClick address Decrement ] [ text "-" ]
    , div [] [ text (toString model) ]
    , button [ onClick address Increment ] [ text "+" ]
    ]

Et la mise à jour du modèle en fonction des actions :

1
2
3
4
5
6
type Action = Increment | Decrement

update action model =
  case action of
    Increment -> model + 1
    Decrement -> model - 1

C'est un langage compilé, avec un compilateur extrêmement sympathique qui lorsque tu rencontres une erreur, t'explique ce qu'il essaie de faire, et pourquoi il n'y arrive pas, en Anglais dans le texte.

C'est un langage fortement typé, ce qui est très appréciable lorsqu'on sait utiliser les types à bon escient (c'est loin d'être évident, mais franchement c'est une excellente gymnastique quand on vient d'autres langages).

Et c'est un langage fonctionnel, qui permet notamment de composer des fonctions, etc. Ce dont tu auras nécessairement besoin dans une architecture flux (la fonction de sélection de tous les utilisateurs qui ont plus de 20 ans et dont le nom commence par 'A', ça peut s'écrire comme la composition de 2 fonctions).

Franchement ça vaut le coup d’œil. C'est dur à prendre en main quand on vient du JS, Java, Ruby ou autre, mais je trouve que c'est du très beau boulot.

J'espère que j'ai répondu à tes questions :)

+1 -0

Salut Javier

Merci pour ta réponse ultra complète c'est très appréciable !

OK pour Flux du coup je vois maintenant son utilité comparé à ce que l'on fait actuellement et je me rends compte à quel point ça aurait pu nous faciliter la tâche sur le projet Angular (1) sur lequel on bosse à mon taf. J'ai l'impression que c'est la voie qui est suivie par les nouvelles versions des Framework / librairies ce qui est plutôt bien. Grâce à tes explications maintenant dans ma tête c'est plutôt ça :D

Image utilisateur

Elm a l'air très intéressant même si vraiment déconcertant au premier abord, mais je vais essayer de m'y pencher.

Le seul truc qui m'ennuie dans Flux, c'est que comme il existe différentes implémentations, on n'est pas vraiment guidé au début, et on a vite tendance à faire des conneries

T'aurais des implémentations à recommander du modèle Flux ? Pour des personnes comme moi qui commence à s'y intéresser quand tu vois les nombreux choix dispo sur Github c'est pas super simple de voir l'avantage de l'une sur l'autre. Celle qui semble se dégager pour l'instant d'après ce que j'ai lu c'est Redux.

Petite aparté : toi qui vient d'Angular 1 considère tu une upgrade de ton/tes applications existantes vers Angular 2 via ngUpgrade ou une réécriture complète ? Pour prendre comme exemple l'application sur laquelle je travaille actuellement au taf je me pose la question à chaque fois que je dois implémenter de nouvelles fonctionnalités : mieux vaut-il pas dire stop et migrer sur Angular 2 (même si en beta actuellement mais l'API ne devrait plus trop bouger si je ne m'abuse) ou continuer la même route et au fil du temps rendre l'application de moins en moins maintenable.

Merci pour tes explications :)

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte