Organisation des classes Java
Introduction
Dans un projet Java, les classes sont regroupées dans des répertoires appelés packages. Ces packages permettent d'organiser votre code et de former l'architecture logicielle de votre application. Un développeur doit comprendre à la simple vue des packages l'intention de l’architecture logicielle.
Notion de racine
Tout projet Java se doit d'organiser ses packages sous forme d'arborescence logique. Pour ce faire on détermine une racine. Le ou les packages racines ont pour but de données une réelle identité à vos classes, c'est de là que part toute l'architecture.
On applique pour cela la convention de nommage dit du reserve DNS (ou nom de domaine inversé).
Exemple :
- Pour Google, le package racine est le suivant :
com.google
. - Pour la Fondation Apache :
org.apache
. - Pour la Fondation Eclipse :
org.eclipse
. - etc...
Note Vous l'avez compris le package racine se construit sur ce motif :
<Nom de domaine inversé>.<Nom du projet>
.
Notion de cohésion
Définition :
- Une classe est en dépendance avec une autre classe si :
- Cette dernière est déclarée dans ses imports.
- Une classe est en cohésion avec une autre classe si :
- Elle est en relation avec cette autre classe.
- Elle n'est pas déclarée dans ses imports.
- Une classe n'est pas en cohésion avec d'autres classes si :
- Elle n'est pas en relation avec les classes de son package.
Note En Java les classes d'un même package n'ont pas besoin de s'importer mutuellement.
Pour vérifier la cohésion d'une classe il suffit de regarder ses imports. Plus une classe possède d'import de classe du même projet, plus sa cohésion est faible. Une classe possédant trop d'import indique également que la classe à trop de responsabilité, et donc qu'elle pourrait être découpée en de plus petites classes.
Organisation par couche
L'organisation par couche est la plus rependue auprès des développeurs, elle est également simple à mettre en place. En revanche les classes manquent de cohésion entre elles.
Dans un projet Jakarta EE voici un exemple d'organisation :
Partie EJB :
+ fr.zelmoacademy.example
+ model
- data
- entity
- mapper
- repository
- service
- security
- util
Partie WAR :
+ fr.zelmoacademy.example.client
- controller
+ model
- data
- form
- mapper
- security
- view
- util
Légende :
- model : Regroupe les classes représentants les données ainsi que les classes qui les transforment.
- data : Regroupe les classes de type DTO (Data Transfer Object).
- entity : Regroupe les classes de type entité métier.
- mapper : Regroupe les classes qui transforment les DTO en d'autres types de DTO ou d'entité et réciproquement.
- repository : Regroupe les classes de type DAO (Data Access Object).
- service : Regroupe les classes de traitement (comme les cas d'utilisation).
- util : Regroupe les classes utilitaires.
- controller : Regroupe les classes de type Contrôleur qui permettent d'interroger l'application depuis l’extérieur.
- form : Regroupe les classes de type Formulaire, ce sont des DTO mais pour des pages de formulaire web.
- security : Regroupe les classes dédiées à la mise en œuvre de la sécurité.
- view : Regroupe les classes dédiées spécifiquement à la vue.
Note Bien entendu, vous pouvez décliner cette organisation en fonction du projet. Ou encore privilégier d'autre nom pour vos packages (exemple: dao au lieu de repository, dto au lieu de data ...).
Organisation par fonctionnalités
L'organisation par fonctionnalité permet d'augmenter la cohésion entre les classes en les regroupant par traitement. Chaque fonctionnalité doit être indépendante des autres, ce qui limite grandement les effets de bord. Mais elle nécessite une découpe métier beaucoup plus rigoureux.
Partie EJB :
+ fr.zelmoacademy.example
- common
- feature1
- feature2
- feature3
- security
- util
Partie WAR:
+ fr.zelmoacademy.example.client
- common
- feature1
- feature2
- feature3
- security
- util
Légende :
- feature : A renommer par le nom de la fonctionnalité réelle. Ce package est spécifique, il ne dépend que de common et util.
- common : Regroupe les classes communes entre les fonctionnalités.
A présent, dans la partie EJB chaque package de fonctionnalité regroupe : les entités métiers, les DTO, les DAO, le ou les services ... La partie WAR reprend ce principe également mais pour les contrôleurs, formulaires, DTO...
Organisation par technologie
Cette organisation est un découpage avancé par technologie. Il isole le métier codé en pure Java afin de pouvoir décider de la technologie à utiliser le plus tardivement possible. Ou de pouvoir changer de technologie en réduisant le coût technique.
Note Cette organisation relève d'une architecture nommée : Clean Architecture ou Architecture Hexagonale. Elle est plus complexe à mettre en œuvre et nécessite plus de code. A privilégier uniquement pour des gros projets avec des règles métiers et des enjeux techniques.
Partie JAR en pure Java, pas de dépendances externes:
+ fr.zelmoacademy.example.core
+ model
- data
- gateway
- business
- util
OU
+ fr.zelmoacademy.example.core
- common
- feature1
- feature2
- feature3
- util
Partie EJB:
+ fr.zelmoacademy.example
+ persistence
- entity
- mapper
- repository
- service
- security
- util
Partie WAR:
+ fr.zelmoacademy.example.client
+ controller
+ model
- data
- form
- mapper
- security
- view
- util
Légende :
- core : Ce package contient tout le cœur métier de l'application en pure Java, sans dépendances externes.
- gateway : Pour passerelle, c'est un terme très générique pour englober la notion d'entrepôt (repository), de service web, d'annuaire ou tout ce qui consiste à la lecture/écrire d'objet en dehors de l'application.
- business : Contient les classes réalisant les traitements métiers (cas d'utilisation).
- persistence : Ce package est dédié à l'emploi de la technologie de persistance, en Jakarta EE il s'agit de JPA. Le package mapper permet la conversion entre les entités persistantes et les objets du cœur métier.
- service : Ce package est dédié à l'emploi de la technologie de traitement, en Jakarta EE il s'agit d'EJB.