Dossier par type ou Dossier par fonction

59

Je me sers d’un guide de style AngularJS. Dans ce guide, il existe un style appelé folder-by-feature, au lieu de folder-by-type, et je suis curieux de savoir quelle est la meilleure approche (dans cet exemple pour Java)

Supposons que je dispose d'une application permettant de récupérer des utilisateurs et des animaux domestiques à l'aide de services, de contrôleurs, de référentiels et d'objets de domaine ofcourse.

En prenant les styles de dossier par., Nous avons deux options pour notre structure de packaging:

1. Dossier par type

com.example
├── domain
│    ├── User.java
│    └── Pet.java
├── controllers
│    ├── UserController.java
│    └── PetController.java
├── repositories
│    ├── UserRepository.java
│    └── PetRepository.java
├── services
│    ├── UserService.java
│    └── PetService.java
│   // and everything else in the project
└── MyApplication.java

2. Dossier par fonctionnalité

com.example
├── pet
│    ├── Pet.java
│    ├── PetController.java
│    ├── PetRepository.java
│    └── PetService.java
├── user
│    ├── User.java
│    ├── UserController.java
│    ├── UserRepository.java
│    └── UserService.java
│   // and everything else in the project
└── MyApplication.java

Quelle serait une bonne approche et quels sont les arguments pour le faire?

Jelle
la source
1
Je ne sais pas @ Laiv. Le langage / cadre affecte-t-il vraiment la réponse? Quoi qu'il en soit, l'autre question est certainement pertinente.
RubberDuck
1
Ensuite, je dois modifier ma réponse. Et oui, c'est un doublon possible
Laiv
2
Je n'ai jamais compris les avantages du type de dossier. Si je travaille sur un ticket relatif à la fonctionnalité Pet, je bénéficierais probablement de la localité de Pet, du contrôleur, du référentiel et du service. Dans quelle situation aurais-je besoin de tous les contrôleurs, mais pas des vues, des pensions ou des services?
Alexander
2
Personne ne semble avoir mentionné que les paquets en Java ne sont pas que des dossiers; ils affectent également l'accès pour les classes contenues. Pour cette raison, le type de paquet par couche peut réellement fournir une valeur sémantique en Java.
Angus Goldsmith

Réponses:

69

Dossier par type ne fonctionne que sur des projets de petite taille. Dossier par fonctionnalité est supérieur dans la majorité des cas.

Dossier par type est acceptable lorsque vous ne disposez que d'un petit nombre de fichiers (moins de 10 par type, par exemple). Dès que vous obtenez plusieurs composants dans votre projet, tous avec plusieurs fichiers du même type, il devient très difficile de trouver le fichier que vous recherchez.

Par conséquent, dossier par fonctionnalité est préférable en raison de son évolutivité. Cependant, si vous parcourez chaque fonction, vous perdez des informations sur le type de composant représenté par un fichier (car son contenu ne figure plus dans un controllerdossier), ce qui crée de la confusion. Il existe 2 solutions simples pour cela.

Premièrement, vous pouvez respecter les conventions de dénomination communes qui impliquent une typicité dans le nom du fichier. Par exemple, le populaire guide de style AngularJS de John Papa contient les éléments suivants:

Directives de dénomination

  • Utilisez des noms cohérents pour tous les composants en suivant un modèle décrivant la fonctionnalité du composant, puis (facultativement) son type. Mon
    modèle recommandé est feature.type.js. Il y a 2 noms pour la plupart des
    actifs:

    • le nom du fichier (avengers.controller.js)
    • le nom du composant enregistré avec Angular (AvengersController)

Deuxièmement, vous pouvez combiner les styles de dossier par type et de dossier par fonction en un dossier par fonction:

com.example
├── pet
|   ├── Controllers
│   |   ├── PetController1.java
|   |   └── PetController2.java
|   └── Services
│       ├── PetService1.java
│       └── PetService2.java
├── user
|   ├── Controllers
│   |   ├── UserController1.java
│   |   └── UserController2.java
|   └── Services
│       ├── UserService1.java
│       └── UserService2.java
Rétablir Monica
la source
1
Le guide de style de johnpapa était exactement celui sur lequel je plaisantais :-)
Jelle
1
Quelques fois (plus souvent que nous le pensons), nous ajoutons trop de complexité à des choses supposées être faciles. La dénomination et l'emballage sont certaines de ces choses. Le meilleur conseil est de garder les choses simples. Le mélange des deux présente les avantages et les inconvénients des deux approches.
Laiv
1
@ Laiv Dans l'exemple que j'ai donné, je suis d'accord pour dire que c'est exagéré, mais dans la plupart de mes cas réels, où chaque dossier de type peut facilement contenir 10 à 20 fichiers, je pense que c'est très utile car le dossier de fonctionnalité global aurait de l'ordre de 50 fichiers autrement.
Rétablir Monica
6
fakking, merci iPhone corrige automatiquement! Je voulais dire "parler".
Jelle
2
@Chaotic Cet exemple est trop trivial pour commencer à parler de détails, mais dans les cas où des éléments sont utilisés dans plusieurs composants, il devrait probablement s'agir d'un composant propre dont dépendent les autres composants.
Rétablir Monica
26

Cela n’a vraiment rien à voir avec la technologie en question, à moins que vous n’utilisiez un cadre qui impose le dossier par type dans le cadre d’une approche de configuration par-dessus la configuration.

Personnellement, je suis fermement convaincu que ce type de dossier est de loin supérieur et qu’il devrait être utilisé autant que possible partout. Il regroupe des classes qui fonctionnent réellement ensemble, alors que type de dossier par type ne fait que dupliquer quelque chose qui est généralement déjà présent dans le nom de la classe.

Michael Borgwardt
la source
10
J'ajouterais que dans folder-by-feature, il est plus facile de jouer avec les étendues de classes et de méthodes (protected, package, ...).
Laiv
Pour les projets plus petits, vous ne pouvez avoir qu'une seule fonctionnalité. Il est beaucoup plus facile d'organiser par type dans ce scénario.
aaaaaa
Par exemple, Grails force le type de dossier par type pour vos domaines, contrôleurs, services, etc.
tylerwal le
17

Travailler avec des packages par fonctionnalités se distingue par une modularité et une cohésion élevées . Cela nous permet de jouer avec la portée des composants. Par exemple, nous pouvons utiliser les modificateurs d'accès pour appliquer le LoD et l' inversion de dépendance pour les intégrations et / et les extensions.

Les autres raisons sont:

  • Navigation de code plus facile
  • Un niveau d'abstraction supérieur
  • Réduire les portées (contextes limitatifs)
  • Modularisation verticale

Dossier par couche met trop l'accent sur les détails de l'implémentation (comme l'a mentionné @David), ce qui n'en dit pas beaucoup sur l'application sur laquelle nous travaillons. Contrairement au paquet par fonction , le paquet par couche encourage la modularisation horizontale. Ce type de modularisation rend le travail avec des composants transversaux difficile et fastidieux.

Enfin, il y a une 3ème option. " Paquet par composant " qui, selon les mots de l'oncle Bob, semble mieux aligné sur les principes de son paquet . Si l'avis de l'oncle concernant Bob est important ou non, je vous laisse le soin de décider. Je trouve cela intéressant puisque cette convention est alignée sur sa Clean Architecture, que j'aime bien.

Laiv
la source