0.0.2-alpha.4

This commit is contained in:
2026-09-23 15:05:35 +02:00
parent 34ac3a9286
commit 70ff272b79
6 changed files with 600 additions and 3 deletions

View File

@@ -1,5 +1,5 @@
<!-- file: docs/rules/000-README.md -->
<!-- version: 8 -->
<!-- version: 9 -->
# Index des règles PGR
@@ -17,6 +17,7 @@ Les règles générales actuellement nécessaires restent dans `RULES.md`. La fa
- [`400-VALIDATION.md`](400-VALIDATION.md) — matrice de validation, preuves proportionnelles, tests/audits/diagnostics, doubles de test et autorité du gate opérateur.
- [`500-LANGUAGES.md`](500-LANGUAGES.md) — contrat commun des profils langage/écosystème et de leurs spécialisations de build.
- [`510-RUST_CARGO.md`](510-RUST_CARGO.md) — profil Rust/Cargo et règles réutilisables propres à cet écosystème.
- [`520-JAVA_MAVEN_GRADLE.md`](520-JAVA_MAVEN_GRADLE.md) — profil Java et spécialisations de build Maven/Gradle.
- [`600-PLATFORMS.md`](600-PLATFORMS.md) — contrat commun des profils plateforme.
Le modèle transversal d'ownership, d'applicabilité et de composition est décrit dans [`../architecture/003-RULE_PROFILE_MODEL.md`](../architecture/003-RULE_PROFILE_MODEL.md).

View File

@@ -0,0 +1,314 @@
<!-- file: docs/rules/520-JAVA_MAVEN_GRADLE.md -->
<!-- version: 1 -->
# Profil Java / Maven / Gradle
## Rôle
Ce document possède les règles réutilisables propres au langage Java et à ses deux spécialisations de build principales retenues ici : Maven et Gradle.
Il complète [`500-LANGUAGES.md`](500-LANGUAGES.md). Les règles de gouvernance, documentation et validation restent possédées par leurs familles générales.
Android n'est pas défini ici. Une contrainte AGP, SDK Android, `minSdk`, `targetSdk`, `versionCode`, signing ou packaging APK/AAB appartient au profil plateforme Android et peut surcharger localement les règles Gradle ou JDK de ce document.
## Politique JDK et compatibilité Java
Pour un projet Java général suivant le profil PGR :
- le JDK de développement SHOULD être une version LTS ;
- la dernière LTS compatible disponible dans l'environnement SHOULD être utilisée par défaut ;
- une LTS plus ancienne MAY être sélectionnée lorsqu'un outil, framework, serveur, CI ou environnement d'exécution l'exige ;
- une version Java non-LTS SHOULD NOT être introduite sans besoin technique explicite.
PGR MUST distinguer :
```text
JDK utilisé pour construire
≠
niveau Java du code source
≠
niveau de bytecode/runtime minimal supporté
```
Le niveau Java ciblé MUST être déclaré explicitement par le build lorsqu'il affecte la compatibilité. Il ne doit pas dépendre implicitement du JDK actif sur la machine.
Une hausse de la version Java minimale supportée constitue un changement de compatibilité et MUST être justifiée comme telle.
PGR MUST NOT imposer une version exacte de JDK uniquement parce qu'un corpus historique ou un autre projet utilise cette version.
## Structure source Java
Un module Java classique SHOULD conserver la structure reconnue par l'écosystème :
```text
src/
├── main/
│ ├── java/
│ └── resources/
└── test/
├── java/
└── resources/
```
PGR SHOULD NOT remplacer cette convention par une arborescence propriétaire telle que `sources/`, `java-code/` ou `tests-java/` sans contrainte réelle.
Lorsqu'un projet distingue des tests d'intégration, environnementaux ou live, il SHOULD utiliser un source set ou un module explicitement déclaré par le build plutôt que détourner `src/test/`.
## Packages et ownership
Un package Java représente une responsabilité architecturale, pas seulement un dossier.
La racine de package SHOULD être stable et appartenir au projet ou à l'organisation. Les sous-packages SHOULD refléter des responsabilités telles que `config`, `transport`, `store`, `logging` ou `protocol`.
Les packages génériques tels que `misc`, `stuff`, `helpers`, `common` ou `util` SHOULD NOT devenir des dépotoirs. Lorsqu'un élément est partagé, son propriétaire architectural doit d'abord être identifié.
Un package utilitaire petit et cohérent MAY exister lorsque sa responsabilité est claire.
## Nommage des modules
Lorsqu'un dépôt multi-langage ou multi-module utilise déjà une nomenclature de rôles commune, les modules Java SHOULD conserver les mêmes suffixes conceptuels afin de rester lisibles à l'échelle du dépôt.
Exemples usuels :
```text
foo-api
foo-lib
foo-app
foo-cli
foo-server
foo-service
foo-worker
foo-tool
foo-demo
foo-smoke
foo-poc
```
Ce vocabulaire est une convention de rôle et non une obligation de créer artificiellement des modules séparés.
## Imports
Les imports wildcard SHOULD NOT être utilisés :
```java
import foo.*;
import static foo.Bar.*;
```
Les imports explicites sont préférés afin de conserver l'origine des symboles visible.
Les imports statiques SHOULD être évités par défaut dans le code produit lorsqu'une forme qualifiée reste lisible. Une règle de test ou de framework plus spécifique MAY autoriser une convention différente lorsqu'elle est réellement idiomatique et bornée.
## Visibilité et API
La visibilité minimale appropriée est la règle par défaut :
```text
private
→ package-private
→ protected
→ public
```
Une méthode ou un type MUST NOT devenir `public` uniquement pour faciliter un test.
Une interface Java SHOULD exister lorsqu'elle représente une vraie frontière : plusieurs implémentations, contrat consommé indépendamment, adaptation de plateforme, API publique ou autre séparation architecturale réelle.
PGR SHOULD NOT généraliser le pattern `Foo` / `FooImpl` lorsqu'une seule implémentation existe sans frontière utile.
## Annotations et génération implicite
PGR n'interdit pas les annotations en tant que mécanisme Java.
Les annotations fonctionnelles faisant partie du contrat officiel d'un framework ou d'une API sont légitimes, par exemple pour la persistance, la validation, l'injection, le routage ou d'autres mécanismes officiellement documentés.
En revanche, Lombok et les outils équivalents de convenience/codegen implicite SHOULD NOT être utilisés par défaut lorsqu'ils servent principalement à masquer du boilerplate, générer des constructeurs/getters/setters ou modifier implicitement l'API visible dans la source.
Une exception exige une justification explicite et reste attachée au projet ou framework concerné.
## Nullabilité
`null` SHOULD apparaître uniquement lorsqu'il appartient explicitement au contrat.
Une API ne devrait pas laisser le caller deviner si l'absence est possible. Selon le cas, le contrat peut employer :
- `Optional<T>` ;
- une collection vide ;
- une exception appropriée ;
- un type résultat plus explicite ;
- une annotation de nullabilité reconnue par le projet.
PGR MUST NOT imposer `Optional` partout. L'objectif est l'explicitation du contrat, pas une cérémonie syntaxique.
## Exceptions
Java possède un mécanisme natif d'exceptions ; PGR ne recrée pas automatiquement un modèle `Result` autour de toutes les opérations.
La distinction checked/unchecked appartient au contrat de la couche concernée.
Un `catch` SHOULD exister uniquement lorsque la couche sait réellement traiter, traduire ou enrichir l'erreur. Les captures silencieuses de `Exception` ou `Throwable` sont interdites hors mécanisme de frontière explicitement spécialisé.
Lorsqu'une erreur est traduite, sa cause SHOULD être préservée lorsque cette information reste pertinente.
Une couche SHOULD exposer ses propres erreurs de contrat plutôt que propager sans contrôle les détails techniques d'une dépendance interne.
## Tests Java
Les tests comportementaux et structurels gardent des responsabilités distinctes.
Les tests unitaires résident normalement sous `src/test/java/`. Les tests d'intégration, environnementaux ou live SHOULD être séparés par source set, module ou tâche lorsque leur exécution possède des préconditions différentes.
Les tests MUST NOT :
- rendre publique une API uniquement pour l'atteindre ;
- rechercher des chaînes dans les sources pour simuler un audit d'architecture ;
- vérifier une prerelease en codant en dur la version courante ;
- ouvrir `VERSION`, `pom.xml` ou `build.gradle` uniquement pour confirmer leur synchronisation.
Les contraintes structurelles appartiennent au build system, au compilateur, à un linter adapté ou à un audit read-only.
## Maven — ownership du build
Dans un projet Maven multi-module, le POM parent/root SHOULD centraliser ce qui est réellement commun :
- version du projet lorsqu'elle doit être reflétée par Maven ;
- niveau Java cible ;
- `dependencyManagement` ;
- `pluginManagement` ;
- configuration commune de compilation et de tests.
Les modules SHOULD hériter de cette politique lorsque Maven le permet et ne pas recopier les mêmes versions/configurations sans nécessité.
Le fichier PGR `VERSION` reste la version canonique de l'unité de release. Le `pom.xml` racine porte un miroir technique lorsque Maven exige cette valeur. Les enfants SHOULD hériter de la version parent afin d'éviter les modifications mécaniques répétées de nombreux POM.
`dependencyManagement` centralise les contraintes de version communes ; il ne signifie pas qu'une dépendance doit être effectivement ajoutée à tous les modules. Chaque module déclare uniquement ce qu'il utilise.
## Maven Wrapper
Deux politiques sont légitimes :
```text
Maven système
→ environnement contrôlé
→ contrainte de version documentée
Maven Wrapper
→ distribution / CI / onboarding reproductible
→ wrapper versionné
```
PGR MUST NOT ajouter un Maven Wrapper uniquement par cérémonie.
Lorsqu'un wrapper est retenu, ses fichiers requis sont versionnés et constituent une exception explicite à la politique générale qui ignore les outputs générés.
## Validation Maven
Le développement SHOULD privilégier les gates ciblées avant le reactor complet.
Exemple avec wrapper :
```bash
./mvnw -pl <module> -am test
```
Exemple avec Maven système :
```bash
mvn -pl <module> -am test
```
Les gates globales telles que le reactor complet, `verify` ou le packaging de tous les modules SHOULD être réservées aux changements transverses et aux phases où elles fournissent une preuve supplémentaire réelle.
`clean` est une opération de maintenance et MUST NOT précéder automatiquement chaque validation.
## Gradle — ownership du build
Un projet Gradle SHOULD centraliser la configuration commune au niveau root lorsqu'elle est réellement partagée.
Selon le DSL retenu, les propriétaires typiques sont :
```text
settings.gradle / settings.gradle.kts
build.gradle / build.gradle.kts
gradle.properties
```
Les sous-projets SHOULD NOT recopier sans nécessité :
- la compatibilité Java ;
- les repositories ;
- les versions de plugins ;
- les contraintes de dépendances ;
- les configurations de tests communes.
Un version catalog tel que `gradle/libs.versions.toml` MAY être utilisé lorsque la taille du projet le justifie. PGR MUST NOT l'imposer pour un projet qui n'en tire aucun bénéfice réel.
## Gradle Wrapper et version de Gradle
La contrainte Gradle doit refléter la matrice réellement supportée par le projet :
```text
minimum seulement
range min..max
version exacte/pinnée
latest compatible
```
Le projet MUST choisir la forme la moins restrictive qui prouve réellement sa compatibilité.
Un Gradle Wrapper SHOULD être versionné lorsqu'il apporte une reproductibilité utile pour la distribution, la CI ou l'onboarding. Un projet contrôlé MAY utiliser un Gradle système si sa contrainte de compatibilité est explicitement vérifiée.
Une plateforme ou un framework plus spécifique MAY imposer une contrainte plus étroite. Cette contrainte ne se propage jamais implicitement aux autres projets Gradle.
## DSL Gradle
PGR ne transforme pas une préférence de langage applicatif en interdiction du DSL de build.
Groovy DSL et Kotlin DSL sont tous deux reconnus. Un projet SHOULD retenir un DSL canonique et éviter de les mélanger arbitrairement.
Le code applicatif Java reste Java par défaut lorsque rien n'impose Kotlin/Groovy. Les scripts Gradle SHOULD rester aussi déclaratifs et courts que raisonnablement possible.
Une logique de build devenue importante SHOULD être déplacée vers une abstraction ou un plugin clairement possédé plutôt que grossir indéfiniment les scripts root.
## Validation Gradle
Les tâches ciblées sont préférées pendant le développement :
```bash
./gradlew :<module>:test
```
ou, lorsqu'un Gradle système est explicitement retenu :
```bash
gradle :<module>:test
```
Les tâches globales `check`, `build`, `assemble` ou de packaging complet SHOULD être sélectionnées lorsqu'elles correspondent réellement au scope, typiquement lors d'un changement transverse ou dans les phases de stabilisation/release.
`gradle clean` est une opération de maintenance et MUST NOT être utilisé comme précondition automatique à chaque build.
## Outputs, état local et Git
Les sorties de build et caches usuels ne sont pas versionnés :
```text
Maven: target/
Gradle: .gradle/, build/
```
Les métadonnées IDE spécifiques à une machine restent ignorées sauf exception explicitement partagée selon les règles générales du projet.
Les wrappers retenus sont une exception volontaire : ils peuvent être générés par l'outil, mais leurs fichiers nécessaires au bootstrap reproductible sont versionnés.
Les fichiers de configuration locale contenant chemins machine, credentials ou overrides développeur restent hors Git. Un template est ajouté uniquement lorsqu'un utilisateur doit réellement préparer une valeur non régénérée automatiquement.
## Validation et futurs audits PGR
Les catégories et l'autorité du gate restent possédées par [`400-VALIDATION.md`](400-VALIDATION.md).
Ce profil définit des commandes et politiques Java/Maven/Gradle, mais PGR lui-même ne possède actuellement aucun projet Java, Maven ou Gradle à compiler. Aucune commande Maven/Gradle n'est donc ajoutée à la gate documentaire de cette tranche.
De même, aucun audit Java/Maven/Gradle n'est créé uniquement pour matérialiser un outil.
Lorsqu'un skeleton ou projet réel fournira un sujet stable, des audits monotâches MAY vérifier séparément des propriétés objectivement structurelles, par exemple la cohérence `VERSION`/POM, l'héritage d'une politique Maven ou la contrainte Gradle déclarée. Ils resteront read-only et ne lanceront jamais Maven ou Gradle à la place de leurs gates propres.