(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start' : new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f) ; })(window,document,'script','dataLayer','GTM-5LHNRP9') ; thecodest, Auteur de The Codest - Page 9 de 13

Application en tant que paquet

L'approche de la modularisation de notre application consiste à convertir l'ensemble de l'application en un paquet.

Créer la structure

Tout d'abord, nous devons créer app/packages dans lequel nous placerons tous nos paquets. Afin d'isoler nos paquets, nous devons séparer chaque Concept MVC dans un seul dossier. En prenant le CodeTriage projet à titre d'exemple, nous aurons quelque chose comme l'image suivante.

structure du paquet

Si nous essayons de lancer le serveur, il ne parviendra pas à trouver les constantes. C'est pourquoi nous devons ajouter une ligne de configuration à notre fichier application.rb

config.paths.add 'app/packages', glob : '*/{*,*/concerns}', eager_load:true

Maintenant, l'application fonctionne mais elle ne peut pas trouver les vues, nous devons donc ajouter une autre ligne de configuration à notre fichier application_controller.rb

append_view_path(Dir.glob(Rails.root.join('app/packages/*/views')))

Créer les paquets

Notre structure étant prête, nous pouvons maintenant commencer à créer les paquets. Pour ce faire, il nous suffit d'ajouter un élémentpackage.yml dans chaque dossier avec la configuration suivante :

enforce_privacy : false
enforce_dependencies : true

package.yml

appliquer_la_confidentialitédonne nous la possibilité d'isoler toutes les constantes du paquet et de travailler avec un paquet public. API. Afin d'exposer les constantes publiques, nous devons ajouter les constantes dans, par exemple paquets/utilisateurs/app/public.Pour l'instant, nous allons définir cette configuration comme suit faux.

enforce_dependencies va imposer la dépendance d'un paquet et vérifier toutes les références constantes. Si une dépendance n'est pas explicitement définie, il s'agira d'une violation de la frontière.

Validation du système de paquets

Packwerk a établi un critère que nous devons respecter pour avoir un système de paquets valide. Nous pouvons commencer à faire fonctionner packwerk valider dans notre console.

 Cette opération permet de vérifier la structure de nos dossiers, configuration du paquetet le cache de chemin autoload.

Pour l'instant, notre application n'est pas valide et nous devons corriger les chemins d'accès dans la sectionpackwerk.yml. Pour ce faire, il suffit d'ajouter les chemins manquants.

# packwerk.yml

load_paths :
.
.
.

# Utilisateurs
- app/packages/users/contrôleurs
- app/packages/users/models
- app/packages/users/package.yml
- app/packages/users/views

À ce stade, nous sommes prêts à vérifier les violations de limites dans notre application. Pour vérifier les violations, nous pouvons exécuterpackwerk update-deprecations Cette commande génère deprecated_references.yml pour chaque paquet. Dans chaque fichier, nous trouverons le nom du paquet, le type de violation et le chemin d'accès au fichier. Grâce à toutes ces informations, nous savons où se produit la violation et nous pouvons prendre une décision pour la résoudre.

deprecated_references.yml
# deprecated_references.yml

.
.
.

app/packages/repos :
  "::Repo" :
    violations :
    - dépendance
    fichiers :
    - app/packages/users/models/user.rb

En prenant l'exemple, nous allons décrire chaque partie de l'information générée.
par Packwerk.

- app/packages/repos  - où la violation de la constante est
trouvée.

- ::Repo  - chemin d'accès au fichier contenant la constante violée.

- dépendance  - un type de violation, soit de la dépendance, soit de la vie privée.

- app/packages/users/models/user.rb  - chemin d'accès au fichier contenant la constante violée.

Comme dernière étape de cette section, n'oubliez pas d'ajouter les nouveaux chemins d'accès aux fichiers générés dans le fichier packwerk.yml et relancer les validations.

Visualisation des dépendances

Avec toutes les informations contenues dans package.yml et deprecated_references.ymlnous pouvons alors
visualiser un graphe de dépendances. Pour ce faire, nous devons ajouter une autre gemme, dans ce cas nous utiliserons Pocky.

Râteau en marche pocky:générer nous générerons un fichier appelé packwerk.png où nous pouvons visualiser notre premier graphique de dépendances.

Une fois tous les paquets définis, notre graphique se présente comme suit.

graphe sans dépendances acceptées

existent déjà, mais cela ne signifie pas qu'elles sont acceptées par Packwerk. Jusqu'à
accepte une dépendance, nous devons ajouter la configuration des dépendances au fichier package.yml
dans chaque paquet. Nous nous concentrerons sur constructeurs_de_mails puisqu'il s'agit d'un paquet sans dépendance circulaire. Il convient de mentionner que Packwerk ne nous permet pas d'accepter des dépendances circulaires.

# app/packages/mail_builders/package.yml

``Ruby
enforce_privacy : false
enforce_dependencies : true
dépendances :
- app/packages/docs
- app/packages/issues
- app/packages/repos

Après avoir ajouté cette configuration, Pocky colorera en vert les dépendances acceptées.

graphe avec dépendances acceptées

Nous pouvons supprimer deprecated_references.yml de app/packages/mail_builders et exécuter
packwerk update-deprecations à nouveau. Le fichier ne sera pas généré à nouveau puisque tous les
ont été corrigées pour ce paquet. Il est important de mentionner que même si nous ne graphons pas avec des dépendances acceptées

Rubis modularisation sur Rails avec Packwerk accepte les dépendances, notre application fonctionnera toujours comme avant, mais nous avons maintenant plus de dépendances.
des informations pour prendre des décisions et remanier.

Supprimer les dépendances circulaires

Dans notre graphique précédent, nous avions beaucoup de dépendances circulaires qui devaient être résolues d'une manière ou d'une autre. Nous disposons de différentes stratégies pour y parvenir :

- Ne rien faire,

- Accepter les dépendances, fusionner les paquets,

- Déplacer code entre les paquets,

- Dupliquer une fonctionnalité, 

- Effectuer l'injection de dépendances ou l'injection de dépendances avec typage.

Le problème est que pour effectuer un refactoring correct, nous devons connaître la base de code. Je ne suis pas très familier avec le code de ce projet puisque je l'ai pris comme exemple, donc pour des raisons pratiques nous allons opter pour la première stratégie, ne rien faire. Même si nous éviterons la majeure partie du remaniement, nous voulons travailler sur les dépendances dans la section racine l'emballage.

Le paquet racine contient toutes les colles du programme Cadre RailsNous allons donc créer un nouveau paquetage appelé rails dans les étapes suivantes. Ainsi, afin de résoudre les dépendances circulaires, nous allons créer un nouveau paquetage appelé rails en suivant les étapes suivantes :

  1. Déplacer tous les fichiers et dossiers application_ de l'application vers app/packages/rails.
  2. Créer unpackage.yml pour le paquet avec la même configuration que les paquets précédents.
  3. Ajouter tous les nouveaux chemins d'accès aux fichiers dans packwerk.yml.
  4. Ajouter app/packages/rails en tant que dépendance du reste des paquets.

Une fois le paquet créé, nous commencerons à remarquer un grand nombre de fichiers qui peuvent être restructurés. Après avoir tout déplacé dans le paquet correspondant et accepté
nous aurons une nouvelle structure et un graphique plus propre.

Structure de l'emballage avec l'emballage des rails
Graphique sans dépendance circulaire de la racine

Supprimer les dépendances du paquet racine

Maintenant, notre graphique est beaucoup plus beau, ce serait bien si nous pouvions supprimer toutes les dépendances du paquet racine. Si nous vérifions deprecated_references.yml dans le paquet racine, nous remarquerons que la plupart d'entre elles proviennent de test , lib/tâches , db et config
. Afin de résoudre ces dépendances, nous allons créer un dossier de test dans chaque paquet. Avoir quelque chose comme app/packages/users/test. Ensuite, nous allons exclure lib/tâches , db et configparmi d'autres dossiers de Packwerk car ces dépendances ne sont pas vraiment importantes dans notre analyse et nous n'avons pas de moyen facile de les résoudre. Nous ajouterons ce qui suit à notre packwerk.yml.

exclude :
- "{bin,node_modules,script,tmp,vendor,lib,db,config,perf_scripts}/**/*"
- "lib/tasks/**/*.rake"

Après avoir déplacé tous les tests du paquet racine et exclu les dossiers de l'analyse, nous aurons un nouveau graphique sans les dépendances racine.

Graphique sans dépendances de la racine

Comme nous pouvons le constater, nous avons encore des dépendances circulaires dansutilisateurs , dépôts et documents . Bien que nous ne les ayons pas résolus, nous disposons d'informations importantes à transmettre maintenant. Nous savons que chaque équipe qui effectue des modifications dans l'un de ces paquets devra probablement effectuer des modifications dans les paquets ayant une dépendance circulaire. D'autre part, nous savons qu'une équipe peut travailler sur github_fetchers uniquement, savoir quels sont les paquets
se laisser influencer par les changements qui surviennent à chaque instant.

Vous pouvez trouver le résultat final du projet ici.

Prochaine étape

Dans une prochaine étape, vous pourriez imposer une confidentialité constante dans chaque paquet et n'exposer que l'API publique qui sera accessible à partir d'autres paquets. Vous pouvez facilement configurer l'emplacement de votre API dans la section package.yml.

enforce_privacy : true
enforce_dependencies : true
public_path : my/custom/path/

Conclusions

Packwerk nous donne beaucoup d'informations sur notre application et grâce à ces informations, nous pouvons prendre des décisions pour améliorer le flux de travail de nos équipes. Bien que le processus ait semblé long et qu'il ait nécessité de nombreuses configurations, il n'est pas nécessaire qu'il en soit toujours ainsi. Nous pouvons commencer à créer des paquets uniquement pour le nouveau code ajouté à notre application et ensuite modulariser progressivement. Nous pouvons maintenant commencer à parler de la modularisation progressive, un concept introduit par Stephan Hagemann. "Nous pouvons, pour la première fois, décider de commencer à modulariser une partie du code d'une manière ambitieuse... Cela nous permet de créer un système de soutien qui s'étend progressivement vers une meilleure structure d'application".

Sources d'information

  1. Modularisation progressive pour Ruby on Rails - Stephan Hagemann
  2. Renforcer la modularité dans les applications Rails avec Packwerk
  3. Packwerk Github
  4. Code source de l'article
Conseil en développement de produits numériques

Lire la suite

GraphQL Ruby. Qu'en est-il des performances ?

Rails et autres moyens de transport

Développement Rails avec TMUX, Vim, Fzf + Ripgrep

fr_FRFrench