Existe-t-il des meilleures pratiques pour l'organisation des packages (Java)? [fermé]

201

Il y a quelque temps, j'ai vu une réponse à une question concernant l'organisation fine des packages java. Par exemple, my.project.util, my.project.factory, my.project.service, etc.

Je ne le trouve pas maintenant, je peux donc aussi bien poser la question.

Existe-t-il des meilleures pratiques en ce qui concerne l'organisation des packages en Java et que contiennent-ils?

Comment organisez-vous vos cours dans votre projet Java?

Par exemple, un projet sur lequel je travaille avec quelques personnes a un package appelé beans. Il a commencé par être un projet contenant des haricots simples, mais a fini par (par mauvaise expérience et manque de temps) contenir tout (presque). Je les ai nettoyés un peu, en mettant certaines classes d'usine dans un package d'usine (classes avec des méthodes statiques qui créent des beans) mais nous avons d'autres classes qui font de la logique métier et d'autres qui font un traitement simple (pas avec la logique métier) comme la récupération un message pour un code d'un fichier de propriétés.

Vos idées et commentaires sont appréciés.

Cyntech
la source
74
Je ne suis pas d'accord avec la clôture de cette question. Je ne suis pas en désaccord avec le fait que les questions de bonnes pratiques sont presque toujours basées sur l'expérience et l'opinion, cependant, je ne suis pas d'accord que ces questions devraient être fermées sur Stack Overflow. C'est le cœur d'une bonne programmation, en utilisant les meilleures pratiques et en trouvant la meilleure solution en utilisant ces opinions et expériences. Veuillez rouvrir cette question.
Cyntech
Je vous suggère de lire ceci: satisfice.com/blog/archives/5164 . TL; DR ... toute l'idée de "meilleures pratiques" est cassée. Au mieux, c'est un abus de langage flagrant, au pire, il est carrément nocif.
Stephen C

Réponses:

174

L'organisation ou la structuration d'un package est généralement une discussion animée. Voici quelques directives simples pour nommer et structurer les packages:

  • Suivez les conventions de dénomination des packages Java
  • Structurez vos packages en fonction de leur rôle fonctionnel ainsi que de leur rôle métier
    • Décomposez vos packages en fonction de leurs fonctionnalités ou modules. par exemple com.company.product.modulea
    • Une ventilation plus poussée pourrait être basée sur des couches dans votre logiciel. Mais n'allez pas trop loin si vous n'avez que quelques classes dans le package, alors il est logique d'avoir tout dans le package. par exemple com.company.product.module.webou com.company.product.module.utiletc.
    • Évitez d'aller trop loin avec la structuration, l'OMI évite les emballages séparés pour les exceptions, les usines, etc., sauf en cas de besoin urgent.
  • Si votre projet est petit, restez simple avec quelques packages. par exemple com.company.product.modelet com.company.product.util, etc.
  • Jetez un oeil à certains des projets open source populaires sur les projets Apache . Découvrez comment ils utilisent la structuration, pour des projets de différentes tailles.
  • Tenez également compte de la construction et de la distribution lors de la dénomination (vous permettant de distribuer votre api ou SDK dans un package différent, voir api servlet)

Après quelques expériences et essais, vous devriez pouvoir trouver une structure avec laquelle vous êtes à l'aise. Ne soyez pas obsédé par une seule convention, soyez ouvert aux changements.

naikus
la source
Merci pour votre réponse. C'est en grande partie ce que nous avons essayé d'englober, mais beaucoup de code non lié est entré dans notre package de beans, d'où ma question est venue.
Cyntech
2
Je suis d'accord que le package par fonctionnalité est le plus logique. J'ai entendu une grande analogie liée à la structure d'un bureau d'entreprise. Dans une approche en couches, chacun des individus par niveau dans une entreprise s'asseoirait les uns avec les autres, c'est-à-dire que les cadres, les gestionnaires, les administrateurs, les employés / travailleurs s'assoient tous dans des sections distinctes dans un bâtiment. Cette structure n'est probablement pas aussi efficace qu'une approche organisée par «caractéristiques». C'est-à-dire si le directeur des ventes siège avec le directeur des ventes qui siège avec les employés des ventes qui sont tous assis avec un administrateur des ventes. Cela permet une meilleure cohésion entre le département lorsqu'il est organisé de cette façon.
alex
Soyez d'accord avec vos points. Juste un point à souligner sur le nom de la société dans le package, parfois, la société obtient le produit acquis est vendu. La direction souhaite supprimer le nom de l'entreprise. Cela pourrait être des frais généraux.
Tushar D
183

J'organise les packages par fonctionnalité , pas par modèles ou rôles d'implémentation. Je pense que des packages comme:

  • beans
  • factories
  • collections

sont faux.

Je préfère, par exemple:

  • orders
  • store
  • reports

afin que je puisse masquer les détails d'implémentation grâce à la visibilité du package . L'usine de commandes doit être dans le orderspackage afin que les détails sur la création d'une commande soient masqués.

sur
la source
10
Ce message fait un bon point sur la visibilité des packages. Je n'ai jamais vu la portée du package Java utilisée, mais la bonne structure de package pourrait permettre aux développeurs de mieux en tirer parti.
Jpnh
23
C'est exactement ça, mais peu de développeurs le font. Les packages doivent être des collections cohérentes de classes, dont certaines ne sont visibles que dans le package. Cela minimiserait le couplage entre les classes qui ne devraient pas être couplées car elles se rapportent à des fonctionnalités différentes. L'approche package par couche ne tire pas parti des modificateurs de visibilité des packages, et les packages dans un tel projet ont une faible cohésion et un haut degré de couplage entre les packages.
Nate Reed
En avez-vous un exemple? J'utilise Spring-MVC, j'ai du mal à l'organiser par fonctionnalité / module car Spring utilise config xml.
Eric Huang
2
@onof J'organise également mon code par fonctionnalité, mais quelles sont les meilleures pratiques pour les classes de base partagées par toutes les fonctionnalités?
Marc
Je suivais le premier style. mais maintenant je dois passer d'un package à un autre lorsque je travaille avec des classes. ça fait vraiment une mauvaise expérience. Je passe maintenant au deuxième style parce que je pense qu'il sera plus facile de suivre les cours connexes ensemble.
M.kazem Akhgary
40

Réponse courte: Un package par module / fonctionnalité, éventuellement avec des sous-packages. Rassemblez des choses étroitement liées dans le même package. Évitez les dépendances circulaires entre les packages.

Réponse longue: je suis d'accord avec la plupart de cet article

Peter Tseng
la source
2
les sous-packages interrompent l'encapsulation. Un "sous-package" est vraiment un package complètement indépendant en lui
Ricardo Gamba
21

Je préfère la fonctionnalité avant les calques, mais je suppose que cela dépend de votre projet. Considérez vos forces:

  • Dépendances
    Essayez de minimiser les dépendances des packages, en particulier entre les fonctionnalités. Extrayez les API si nécessaire.
  • Organisation des équipes
    Dans certaines organisations, les équipes travaillent sur des fonctionnalités et dans d'autres sur des couches. Cela influence l'organisation du code, l'utilise pour formaliser les API ou encourager la coopération.
  • Déploiement et versionnage
    Mettre tout dans un module simplifie le déploiement et la versionnage, mais la correction des bogues est plus difficile. La division des éléments permet un meilleur contrôle, une évolutivité et une disponibilité accrues.
  • Répondre au changement Un
    code bien organisé est beaucoup plus simple à changer qu'une grosse boule de boue.
  • Taille (personnes et lignes de code)
    Plus elle est grande, plus elle doit être formalisée / standardisée.
  • Importance / qualité
    Certains codes sont plus importants que d'autres. Les API devraient être plus stables que l'implémentation. Il doit donc être clairement séparé.
  • Niveau d'abstraction et point d'entrée
    Il devrait être possible pour un étranger de savoir de quoi parle le code et où commencer la lecture en regardant l'arborescence des packages.

Exemple:

com/company/module
  + feature1/
    - MainClass          // The entry point for exploring
    + api/               // Public interface, used by other features
    + domain/
      - AggregateRoot
      + api/             // Internal API, complements the public, used by web
      + impl/ 
    + persistence/       
    + web/               // presentation layer 
    + services/          // Rest or other remote API 
    + support/            
  + feature2/
  + support/             // Any support or utils used by more than on feature
    + io
    + config
    + persistence
    + web

C'est juste un exemple. C'est assez formel. Par exemple, il définit 2 interfaces pour feature1 . Normalement, cela n'est pas obligatoire, mais pourrait être une bonne idée s'il est utilisé différemment par différentes personnes. Vous pouvez laisser l'API interne étendre le public.

Je n'aime pas les noms 'impl' ou 'support', mais ils aident à séparer les choses moins importantes des importantes (domaine et API). Quand il s'agit de nommer, j'aime être le plus concret possible. Si vous avez un paquet appelé 'utils' avec 20 classes, passez StringUtilsà support / string, HttpUtilà support / http et ainsi de suite.

ThomasGran
la source
13

Existe-t-il des meilleures pratiques en ce qui concerne l'organisation des packages en Java et que contiennent-ils?

Non, pas vraiment. Il y a beaucoup d'idées et beaucoup d'opinions, mais la vraie "meilleure pratique" est d'utiliser votre bon sens!

(Veuillez lire Pas de meilleures pratiques pour avoir une perspective sur les "meilleures pratiques" et les personnes qui les promeuvent.)

Cependant, il y a un principe qui est probablement largement accepté. La structure de votre package doit refléter la structure (informelle) du module de votre application, et vous devez viser à minimiser (ou idéalement éviter complètement) les dépendances cycliques entre les modules.

(Les dépendances cycliques entre les classes d'un package / module sont très bien, mais les cycles inter-packages ont tendance à compliquer la compréhension de l'architecture de votre application, et peuvent être un obstacle à la réutilisation du code. En particulier, si vous utilisez Maven, vous constaterez que cyclique Les dépendances inter-packages / inter-modules signifient que l'ensemble du désordre interconnecté doit être un artefact Maven.)

Je dois ajouter qu'il y a une meilleure pratique largement acceptée pour les noms de paquets. Et c'est que les noms de vos packages doivent commencer par le nom de domaine de votre organisation dans l'ordre inverse. Si vous suivez cette règle, vous réduisez la probabilité de problèmes causés par des conflits entre vos noms de classe (complets) et ceux d'autres personnes.

Stephen C
la source
9

J'ai vu certaines personnes promouvoir le «package par fonctionnalité» au lieu de «package par couche», mais j'ai utilisé pas mal d'approches au cours des années et j'ai trouvé «package par couche» beaucoup mieux que «package par fonctionnalité».

De plus, j'ai trouvé qu'une stratégie hybride: «package par module, couche puis fonctionnalité» fonctionne extrêmement bien dans la pratique car elle présente de nombreux avantages du «package par fonctionnalité»:

  • Favorise la création de frameworks réutilisables (bibliothèques avec à la fois le modèle et l'interface utilisateur)
  • Permet des implémentations de couches plug and play - pratiquement impossible avec «package par fonctionnalité» car il place les implémentations de couches dans le même package / répertoire que le code modèle.
  • Beaucoup plus...

J'explique en détail ici: Structure et organisation du nom du package Java, mais ma structure de package standard est:

revdomain.moduleType.moduleName.layer. [layerImpl] .feature.subfeatureN.subfeatureN + 1 ...

Où:

revdomain domaine inverse de la com.mycompany

moduleType [app * | framework | util]

moduleName par exemple myAppName si le type de module est une application ou «finance» si c'est un cadre comptable

couche [modèle | ui | persistance | sécurité etc.,]

layerImpl par ex., portillon, jsp, jpa, jdo, hibernate (Remarque: non utilisé si le calque est le modèle)

fonctionnalité, par exemple, finances

sous-fonctionN p. ex., comptabilité

sous-fonctionN + 1 par exemple, dépréciation

* Parfois, «app» est omis si moduleType est une application, mais la mettre dedans rend la structure du package cohérente sur tous les types de modules.

Volksman
la source
5

Je ne connais pas les pratiques standard pour l'organisation des packages. Je crée généralement des packages qui couvrent un spectre raisonnablement large, mais je peux faire la différence au sein d'un projet. Par exemple, un projet personnel sur lequel je travaille actuellement a un package dédié à mes contrôles d'interface utilisateur personnalisés (plein de classes sous-classes swing classes). J'ai un package dédié à ma gestion de base de données, j'ai un package pour un ensemble d'écouteurs / événements que j'ai créés, etc.

D'un autre côté, j'ai demandé à un collègue de créer un nouveau package pour presque tout ce qu'il a fait. Chaque MVC différent qu'il voulait avait son propre package, et il semblait qu'un ensemble MVC était le seul groupe de classes autorisé à être dans le même package. Je me souviens à un moment donné, il avait 5 packages différents qui avaient chacun une seule classe en eux. Je pense que sa méthode est un peu extrême (et l'équipe l'a forcé à réduire le nombre de packages alors que nous ne pouvions tout simplement pas le gérer), mais pour une application non triviale, il faudrait tout mettre dans le même package. C'est un point d'équilibre que vous et vos coéquipiers devez trouver par vous-même.

Une chose que vous pouvez faire est d'essayer de prendre du recul et de penser: si vous étiez un nouveau membre présenté au projet, ou si votre projet a été publié en open source ou en API, comment serait-il facile / difficile de trouver ce que vous voulez? Parce que pour moi, c'est ce que je veux vraiment des packages: l'organisation. Semblable à la façon dont je stocke les fichiers dans un dossier sur mon ordinateur, je m'attends à pouvoir les retrouver sans avoir à rechercher tout mon lecteur. J'espère pouvoir trouver la classe que je veux sans avoir à rechercher la liste de toutes les classes dans le package.

Brian S
la source