Format Source
Tout le code est strictement formaté en utilisant le formateur source (Java, JavaScript, JSON, JSP, Markdown, properties, shell, XML, YAML, et autres). Voici comment cela fonctionne :
Exécuter pour un module spécifique :
cd <module-root> && <gradlew> formatSource
Exécuter sur toute la base de code :
cd <repo-root>/portal-impl && ant format-source-current-branch
ant format-source-current-branch inspecte uniquement les fichiers validés, donc exécutez-le après avoir créé la validation, et fusionnez les modifications ou corrections du formateur dans cette validation.
Dans les deux cas, s'il y a des problèmes à corriger, le formateur les listera. Corrigez-les.
En plus du formateur automatique, il existe un ensemble de règles manuelles que le formateur ne détecte pas. Le flux de travail complet consiste à exécuter le formateur, appliquer les règles manuelles, puis réexécuter le formateur pour nettoyer les effets secondaires des modifications manuelles. Quand une règle manuelle entre en conflit avec le formateur automatique, le formateur l'emporte ; laissez le code formaté tel qu'il est.
Ignorez les fichiers générés. Le formateur automatique le fait déjà via BaseSourceProcessor.hasGeneratedTag ; appliquez la même règle aux modifications manuelles. Un fichier est généré quand il contient l'un de ces marqueurs non échappés :
-
@generated— Service Builder, REST Builder, générateur taglib (Java, de loin le plus courant ; ~18k fichiers) -
$ANTLR— lexeurs et analyseurs générés par ANTLR -
# This is a generated file.— scripts générés -
## Autogenerated— Markdown et config générés
Ces fichiers sont réécrits à la prochaine compilation, donc les modifications manuelles sont perdues et ne font que polluer le diff.
Rules
Rule 1: Chained Method Call Ordering
Why: L'ordre cohérent des méthodes dans les appels enchaînés facilite la recherche d'un appel spécifique et réduit la rétention quand de nouvelles méthodes sont ajoutées à la chaîne.
Examples:
Foo foo = builder.start(
arg
-).gamma(
- gammaArg
).alpha(
alphaArg
).beta(
betaArg
+).gamma(
+ gammaArg
).build();
Rule 2: Method Parameter Ordering
Why: L'ordre cohérent des paramètres rend les sites d'appel plus faciles à scanner et réduit la rétention quand de nouveaux paramètres sont ajoutés.
Examples:
private void process(
- String charlie, long alpha, String beta,
+ long alpha, String beta, String charlie,
Object delta) {
Rule 3: Sequential Assertion Ordering
Why: L'ordre cohérent des assertions rend les défaillances de test plus faciles à localiser et réduit la rétention quand de nouveaux cas sont ajoutés.
Examples:
Assert.assertEquals(1L, map.get("apple"));
-Assert.assertEquals(3L, map.get("cherry"));
Assert.assertEquals(2L, map.get("banana"));
+Assert.assertEquals(3L, map.get("cherry"));
Rule 4: Local Variable Declaration Ordering
Why: L'ordre cohérent des déclarations facilite la recherche d'une variable et réduit la rétention quand de nouvelles variables locales sont ajoutées.
Examples:
-Map<X, Y> beta = new HashMap<>();
-
boolean alpha = check();
+Map<X, Y> beta = new HashMap<>();
Rule 5: Variable Name Type Suffix
Why: Un suffixe de type rend le type de la variable lisible au site d'utilisation et empêche une locale générique de masquer une clé de chaîne, un champ ou un argument d'appel du même nom dans la portée.
Examples:
Les chaînes et autres types de référence comme Date, JSONObject obtiennent un suffixe de type.
-String foo = result.toString();
+String fooString = result.toString();
int, long, boolean gardent des noms descriptifs sans suffixe de type.
-int countInt = items.size();
-long timeLong = System.currentTimeMillis();
-boolean enabledBoolean = config.isEnabled();
+int count = items.size();
+long time = System.currentTimeMillis();
+boolean enabled = config.isEnabled();
Les listes préfèrent un nom au pluriel ; le suffixe List est acceptable quand aucun pluriel naturel n'existe.
-List<Item> itemList = repository.findAll();
+List<Item> items = repository.findAll();
Les maps préfèrent un nom descriptif ; le suffixe Map est acceptable quand aucun descripteur naturel n'existe.
-Map<String, Item> itemMap = loadIndex();
+Map<String, Item> itemsByKey = loadIndex();
Rule 6: Acronym Capitalization in Identifiers
Why: Traiter les acronymes comme des tokens entièrement en majuscules maintient les noms de méthodes, champs et variables visuellement cohérents avec l'API environnante et évite la dérive entre variantes camelCase et CamelCase pour le même concept.
Examples:
-public String getUrl() {
+public String getURL() {
return _url;
}
-foo.getHtmlContent();
-bar.parseXmlString();
+foo.getHTMLContent();
+bar.parseXMLString();
Rule 7: Quote Literal Tokens in Messages
Why: Envelopper les identifiants littéraux, les valeurs d'en-tête, les types de contenu et tokens similaires entre guillemets doubles à l'intérieur des messages de journal et d'exception sépare le littéral de la prose environnante, pour qu'un lecteur puisse dire d'un coup d'œil quels mots viennent des données et lesquels viennent de la phrase.
Examples:
throw new IllegalArgumentException(
- "Request body has no application/json content");
+ "Request body has no \"application/json\" content");
-_log.warn("Missing header X-Custom-Header for request");
+_log.warn("Missing header \"X-Custom-Header\" for request");
Utilisez des guillemets doubles échappés, pas de guillemets simples, pour envelopper le token.
-throw new IllegalArgumentException("Missing 'paths' object");
+throw new IllegalArgumentException("Missing \"paths\" object");
Rule 8: Generic Index Variable Name
Why: Quand une portée de méthode contient un seul index int retourné par indexOf ou similaire, le nommer simplement index est plus court qu'un nom qualifié et correspond à la convention dominante ; réutilisez le même slot index pour des recherches séquentielles dans la même portée plutôt que d'introduire des noms qualifiés parallèles.
Examples:
-int spaceIndex = endpoint.indexOf(' ');
+int index = endpoint.indexOf(' ');
-String prefix = endpoint.substring(0, spaceIndex);
-String suffix = endpoint.substring(spaceIndex + 1);
+String prefix = endpoint.substring(0, index);
+String suffix = endpoint.substring(index + 1);
Quand la valeur est réutilisée pour une deuxième recherche dans la même portée, réassignez index plutôt que d'introduire une nouvelle variable.
-int firstSlashIndex = path.indexOf('/', 1);
-int secondSlashIndex = path.indexOf('/', firstSlashIndex + 1);
+int index = path.indexOf('/', 1);
+index = path.indexOf('/', index + 1);
Rule 9: Map Entry Loop Naming
Why: Nommer la variable de boucle entry et les parties extraites d'après les données qu'elles contiennent (typiquement key/name et value) maintient chaque itération de map lisible dans la même forme, indépendamment du domaine environnant.
Examples:
-for (Map.Entry<String, Object> argumentEntry : arguments.entrySet()) {
- String paramName = argumentEntry.getKey();
- Object paramValue = argumentEntry.getValue();
+for (Map.Entry<String, Object> entry : arguments.entrySet()) {
+ String name = entry.getKey();
+ Object value = entry.getValue();
Rule 10: Test Method Predicate Phrasing
Why: Exprimer la clause de prédicat d'une méthode de test comme <property>Is<state> plutôt que <subject>Has<state><property> fait que une liste de méthodes triées se groupe par la propriété testée, et se lit comme une phrase sujet-verbe-complément complète.
Examples:
-public void testGetFooWhenBarHasNullBaz() throws Exception {
+public void testGetFooWhenBarBazIsNull() throws Exception {
-public void testGetFooWhenBarHasValidBaz() throws Exception {
+public void testGetFooWhenBarBazIsValid() throws Exception {
Rule 11: Drop Redundant Nonnull Assertion Before Specific Assertions
Why: Une assertion ultérieure qui appelle une méthode sur la même référence lèverait déjà une NullPointerException si la valeur était null, donc la vérification explicite nonnull ajoute du bruit sans ajouter de couverture.
Examples:
Foo foo = service.findFoo();
-Assert.assertNotNull(foo);
Assert.assertEquals("expected", foo.getName());
Assert.assertEquals(1L, foo.getId());
Rule 12: Inline Single-Use Local Variables
Why: Une locale qui est calculée une fois et immédiatement passée à un seul site d'appel ajoute un nom sans ajouter de sens, donc passer l'expression directement supprime un saut que le lecteur doit sinon suivre.
Examples:
-Foo foo = makeFoo(arg);
-
-bar.consume(foo);
+bar.consume(makeFoo(arg));
-FooSchema fooSchema = computeSchema(args, root);
-
return Bar.builder(
).name(
"x"
).inputSchema(
- fooSchema
+ computeSchema(args, root)
).build();
Les classes anonymes suivent la même règle.
-FooDelegate fooDelegate = new FooDelegate() {};
-
-method.invoke(fooDelegate);
+method.invoke(new FooDelegate() {});
Rule 13: Drop Narrative Assertion Messages
Why: Un message d'explication verbeux sur Assert.assertTrue ou Assert.assertFalse redéclare surtout ce que le prédicat montre déjà ; le supprimer laisse la ligne défaillante et la frame de pile porter le diagnostic, et raccourcit le test.
Examples:
-Assert.assertTrue(
- StringBundler.concat(
- "Lookup must use the entity's ", id,
- ". Actual filter was: ", filterString),
- filterString.contains("(id=" + id + ")"));
+Assert.assertTrue(filterString.contains("(id=" + id + ")"));
Rule 14: Declare Locals Next to First Use
Why: Déclarer une locale juste avant l'instruction qui la consomme maintient les lignes connexes ensemble et supprime le besoin de scanner en arrière vers un bloc en haut de la méthode pour se rappeler ce que chaque valeur signifie. La même logique s'applique à l'intérieur d'un bloc try : hoister une locale en dehors du try n'a de sens que quand le catch ou finally en a besoin ; sinon la portée plus large ajoute du bruit visuel et un lecteur doit confirmer que la locale n'est pas réutilisée plus tard.
Examples:
-long alpha = randomLong();
-String beta = "https://example.com";
-String gamma = randomString();
-
Foo foo = Mockito.mock(Foo.class);
+long alpha = randomLong();
+
Mockito.when(
foo.getAlpha()
).thenReturn(
alpha
);
+String beta = "https://example.com";
+
Mockito.when(
foo.getBeta()
).thenReturn(
beta
);
Une locale utilisée uniquement à l'intérieur d'un try appartient à l'intérieur du try :
-Foo foo = makeFoo();
-
-try {
- foo.consume();
-}
-catch (Exception exception) {
- _log.error("Failed", exception);
-}
+try {
+ Foo foo = makeFoo();
+
+ foo.consume();
+}
+catch (Exception exception) {
+ _log.error("Failed", exception);
+}
Rule 15: Avoid Unboxing in Assertion Comparisons
Why: Appeler .longValue(), .intValue(), ou similaire sur la valeur réelle force une chaîne sur la ligne en cours d'assertion ; matcher le type boxed du côté attendu maintient la comparaison lisible en un seul appel.
Examples:
-Assert.assertEquals(
- 0L,
- threadLocal.getValue(
- ).longValue());
+Assert.assertEquals(Long.valueOf(0), threadLocal.getValue());
Rule 16: Keep Default Override Adjacent to Declaration
Why: Quand une locale est déclarée et ensuite immédiatement corrigée si sa valeur initiale est null ou autrement inadéquate, maintenir le if directement après la déclaration traite la paire comme une étape logique « calculer alpha » et évite de la scinder entre un bloc de déclaration sans rapport.
Examples:
String alpha = source.getAlpha();
+
+if (alpha == null) {
+ alpha = fallback.getAlpha();
+}
+
String beta = null;
String gamma = null;
Date delta = source.getDelta();
-
-if (alpha == null) {
- alpha = fallback.getAlpha();
-}
Rule 17: Sort Sequential Setter Calls on Same Object
Why: Quand le même objet est configuré par un bloc contigu d'appels setters, commander les appels alphabétiquement par nom de méthode (et ensuite par argument) rend la configuration plus facile à scanner et correspond à la convention utilisée pour les assertions et déclarations.
Examples:
Foo foo = new Foo();
-foo.setGamma(gamma);
foo.setAlpha(alpha);
foo.setBeta(beta);
+foo.setGamma(gamma);
Exception: Quand le destinataire est une entité Service Builder (tout ce qui est soutenu par un *ModelImpl — FragmentEntryVersion, User, Group, etc.), le JavaServiceObjectCheck du formateur automatique réécrit le bloc setter en ordre de déclaration de champ de modèle, pas en ordre alphabétique. Laissez les blocs de setter d'entité tel que le formateur les produit ; l'alphabétisation manuelle sera révoquée à la prochaine exécution de formatSource.
Rule 18: Use Complete Sentences in User-Facing Messages
Why: Les chaînes de statut, erreur et notification qui omettent le verbe de liaison se lisent comme des fragments et se traduisent mal ; restaurer l'auxiliaire (is, are, was, were) transforme le message en une phrase complète et correspond à la formulation dominante déjà utilisée dans les fichiers de langue, les instructions de journal et les échos shell. Pour les messages d'échec, préférez la forme Unable to <verb> plutôt que Cannot <verb>, Failed to <verb>, ou Error <verb>ing.
Examples:
La règle s'applique aux valeurs de propriétés de langue.
-foo-not-allowed=Foo not allowed.
+foo-is-not-allowed=Foo is not allowed.
Elle s'applique aux messages de script shell.
-_log "Resource ${name} created successfully."
+_log "Resource ${name} was created successfully."
Elle s'applique au flux de travail et autres sorties de script YAML.
-echo "No entries found for ${id}."
+echo "No entries were found for ${id}."
Elle s'applique aux messages d'exception et de journal Java.
-throw new IllegalStateException("Foo not found for id " + id);
+throw new IllegalStateException("Foo was not found for id " + id);
-_log.warn("Cannot delete foo " + id);
+_log.warn("Unable to delete foo " + id);
Rule 19: Use "Delete" for Helpers That Delete Entities
Why: Les APIs de persistance de Liferay orthographient la destruction d'entité comme delete* (deleteUser, deleteEntry) ; nommer un helper privé _delete* quand son corps appelle un service delete* maintient le verbe du helper aligné avec l'opération qu'il effectue.
Examples:
-private void _removeStaleFoos(Map<Long, List<String>> deletedIdsMap)
+private void _deleteStaleFoos(Map<Long, List<String>> deletedIdsMap)
throws Exception {
...
_fooLocalService.deleteFoo(foo);
}
Mettez à jour les sites d'appel en même temps.
-_removeStaleFoos(deletedIdsMap);
+_deleteStaleFoos(deletedIdsMap);
Rule 20: Drop Unnecessary L Suffix on Long Literals
Why: Quand le slot récepteur est déjà typé long, le suffixe L sur un littéral entier ajoute du bruit visuel sans changer la valeur, car l'entier est élargi automatiquement.
Examples:
-public static final long TIMEOUT = 300000L;
+public static final long TIMEOUT = 300000;
Rule 21: Avoid iterator().next() for First-Element Access
Why: Une chaîne multiméthode pour accéder au premier élément cache l'intention derrière deux appels ; choisissez l'accesseur le plus direct que le type offre déjà pour que le site d'appel se lise comme une recherche unique.
Examples:
-Foo foo = page.getItems().iterator().next();
+Foo foo = page.getItems().get(0);
Rule 22: Prefer while Over do-while
Why: Une boucle while vérifie sa garde avant le corps, correspondant à la convention dominante dans la base de code ; do-while appartient uniquement aux cas où le corps doit véritablement s'exécuter avant la première vérification.
Examples:
-do {
- advance();
-}
-while (!done());
+while (!done()) {
+ advance();
+}
Rule 23: Blank Lines Delimit Logical Groups
Why: Les lignes vides marquent les frontières d'un groupe ; les instructions à l'intérieur d'un groupe se lisent comme une étape logique. Dans un groupe, l'ordre doit être déterministe (alphabétique, ordre d'argument, ordre d'appel) ; quand les instructions ne peuvent pas être ordonnées, scindez-les en groupes séparés avec une ligne vide pour que le lecteur sache que l'ordre est intentionnel plutôt qu'arbitraire. Les paires qui se lisent déjà comme une étape (setup parallèle, assertions parallèles, déclarations appairées) doivent être sur des lignes adjacentes sans ligne vide entre elles. Inversement, quand un bloc de setup logique se termine (configuration d'un objet contexte, mocking d'un service, construction d'une fixture), une simple ligne vide marque la frontière pour que le bloc suivant se lise comme un nouveau paragraphe.
Examples:
Déclarations appairées :
Foo first = create("first");
-
Foo second = create("second");
Assertions appairées sur des résultats parallèles :
Assert.assertEquals("alpha", alpha.getName());
-
Assert.assertEquals("beta", beta.getName());
Une ligne vide après un bloc de setup terminé le sépare du suivant :
themeDisplay.setSiteGroupId(siteGroupId);
themeDisplay.setUser(user);
+
ThemeRequest themeRequest = new ThemeRequest();
themeRequest.setLocale(locale);
Rule 24: Single Space After a Period in Prose
Why: Deux espaces après un point est une convention héritée de la machine à écrire ; la prose Liferay moderne dans les commentaires, JSPs, chaînes de langue et Markdown utilise une seule.
Examples:
-// Compute the score. Cache it for next time.
+// Compute the score. Cache it for next time.
Rule 25: Method-Name Plurality Matches Return-Type Plurality
Why: Une méthode qui retourne une collection doit signaler cela dans son nom, pour qu'un lecteur puisse prédire le type de retour sans vérifier la signature ; un nom au singulier sur un retour List force une deuxième lecture.
Examples:
-public List<Foo> getFooOverview() {
+public List<Foo> getFoos() {
return _fooLocalService.findAll();
}
Rule 26: Mirror Methods Share a Naming Suffix
Why: Quand deux méthodes sont appairées (fetch de données avec count, get avec getCount, par clé avec par clé count), elles doivent différer uniquement par le verbe de l'opération ; un suffixe non appairé cache la paire de git grep et du lecteur.
Examples:
public List<Foo> getFoosByGroupIds(long[] groupIds);
-public int getFoosCount(long[] groupIds);
+public int getFoosCountByGroupIds(long[] groupIds);
Rule 27: "Cleanup" Is a Noun, "Clean Up" Is a Verb
Why: Traiter cleanup et clean up comme interchangeables produit du bruit dans les symboles et la prose ; la forme nom nomme une chose (une méthode, une phase, un en-tête de section), la forme verbe décrit une action.
Examples:
La forme verbe appartient aux commentaires impératifs et noms de méthodes.
-// Cleanup the cache after the test runs
+// Clean up the cache after the test runs
La forme nom appartient aux identifiants et en-têtes de section.
-public void runCleanUp() {
+public void runCleanup() {
Rule 28: Order Declarations to Match Their Downstream Usage
Why: Quand un bloc de déclarations alimente directement une séquence d'appels en aval, les commander pour correspondre à cette séquence laisse l'œil matcher de gauche à droite et réduit la chance d'échanger deux valeurs du même type au site d'appel ; l'ordre alphabétique casse les égalités.
Examples:
Quand un bloc de locales alimente directement un appel à arguments multiples, déclarez-les dans l'ordre des arguments de l'appel.
-String beta = computeBeta();
-String alpha = computeAlpha();
-String gamma = computeGamma();
+String alpha = computeAlpha();
+String beta = computeBeta();
+String gamma = computeGamma();
invoke(alpha, beta, gamma);
Cela s'applique aussi aux déclarations de mock Mockito : ordonnez-les dans la séquence que le système testée exécute, avec l'alphabétique comme brise-égalité. Quand le système testée appelle _serviceA en premier et _serviceB en deuxième :
-Mockito.when(_serviceB.findFoo(id)).thenReturn(foo);
Mockito.when(_serviceA.exists(id)).thenReturn(true);
+Mockito.when(_serviceB.findFoo(id)).thenReturn(foo);
Rule 29: Descriptive Lambda Parameter Names
Why: Un paramètre lambda k, v, ou e simple force le lecteur à scroll en arrière pour connaître ce qu'il représente ; un nom de domaine se lit sur sa propre ligne.
Examples:
-fooMap.computeIfAbsent(name, k -> new HashSet<>());
+fooMap.computeIfAbsent(name, fooName -> new HashSet<>());
Rule 30: Use Guard Clauses Over Nested Positive Conditions
Why: Inverser la condition et quitter tôt aplatit l'indentation de la majeure partie de la méthode, pour que le lecteur suive une colonne droite plutôt qu'un nid en forme de flèche.
Examples:
for (Foo foo : foos) {
- if ((foo != null) && foo.isEnabled()) {
- // thirty lines of work
- }
+ if ((foo == null) || !foo.isEnabled()) {
+ continue;
+ }
+
+ // thirty lines of work
}
Rule 31: Prefer @Before and @After Over @BeforeClass and @AfterClass
Why: Le setup au niveau de l'instance donne à chaque test un état frais ; le setup au niveau de la classe crée un couplage caché entre les tests qui partagent la fixture statique, et le mode d'échec est silencieux quand un test la mute.
Examples:
-@BeforeClass
-public static void setUpClass() throws Exception {
+@Before
+public void setUp() throws Exception {
_fixture = createFixture();
}
Exception: Quand la fixture est chère à construire (par exemple, créer une nouvelle entreprise), @BeforeClass peut être le bon choix pour que la suite ne paie pas le coût par test.
Rule 32: Group Members by Category, Sort Within the Group
Why: Entrelacement de catégories éparpille les membres connexes dans la classe ; un bloc séparé par ligne vide par catégorie, alphabétique à l'intérieur, maintient chaque groupe scannable et rend les additions évidentes dans un diff. Le même principe gère les entrées must-be-first ou must-be-last (initialisation, défauts, « tous ») : les séparer du bloc trié avec une ligne vide pour que le lecteur sache que la position de début ou de fin est intentionnelle et que le reste de l'ordre n'a pas plus de sens.
Examples:
Grouper les constantes par catégorie :
private static final String _ALPHA_X = "ax";
-private static final String _GAMMA_X = "gx";
private static final String _ALPHA_Y = "ay";
+
+private static final String _GAMMA_X = "gx";
private static final String _GAMMA_Y = "gy";
Séparer les éléments must-be-first ou must-be-last du bloc trié :
public enum FooStep {
INIT,
+
ALPHA,
BETA,
GAMMA;
}
Rule 33: Variable Name Matches the Expression Assigned to It
Why: Quand le nom d'une locale ne correspond pas au côté droit, le lecteur doit vérifier quel nom est le véridique à chaque utilisation ; choisissez le nom de l'expression pour que les deux restent synchronisés.
Examples:
-long[] currentAndAncestorGroupIds = getReferencedGroupIds();
+long[] referencedGroupIds = getReferencedGroupIds();
Rule 34: Add @Override on Every Overriding Method
Why: @Override rend le override explicite, laisse le compilateur attraper la dérive de signature dans le supertype, et correspond à chaque autre override dans la base de code.
Examples:
+@Override
public void doSomething() {
super.doSomething();
}
Rule 35: No ASCII-Art Separators in CSS Comments
Why: Les règles ASCII-art dupliquent ce que l'indentation et les lignes vides conveyent déjà ; correspondre au style de commentaire terse environnant maintient le fichier scannable et cohérent.
Examples:
-/* ---------- Hide the column when narrow ---------- */
+/* Hide the column when narrow */
.foo .col {
display: none;
}
Rule 36: Combine Consecutive StringBundler.append of Literal Strings
Why: Deux appels append de littéraux seulement collapsent en un sans changer le comportement, et la forme fusionnée laisse le lecteur voir le littéral complet en une seule ligne.
Examples:
-sb.append("<?xml version=\"1.0\"?>");
-sb.append("<foo><bar>");
+sb.append("<?xml version=\"1.0\"?><foo><bar>");
Rule 37: Drop the Fully-Qualified Class Name When the Class Is Imported
Why: Une fois qu'une classe est dans le bloc d'import, la forme entièrement qualifiée au site d'utilisation ajoute du bruit et force un retour à la ligne ; le nom simple est ce que chaque autre référence dans le fichier utilise déjà.
Examples:
import com.example.foo.FooResource;
// ...
-com.example.foo.FooResource fooResource = factory.create();
+FooResource fooResource = factory.create();
Rule 38: Bash Scripts Exit on First Failure
Why: Sans une directive fail-fast explicite, une commande défaillante passe silencieusement à la suivante ; le bloc set -o errexit / set -o nounset / set -o pipefail en haut du script rend les défaillances, les variables non définies et les étapes de pipeline cassées surfaces immédiatement.
Examples:
-#!/bin/bash
+#!/usr/bin/env bash
+
+set -o errexit
+set -o nounset
+set -o pipefail
_execute "step-1"
_execute "step-2"
Rule 39: Class-Level Constants Live at the Top of the Class, Sorted
Why: Les constantes éparpillées entre les méthodes forcent le lecteur à scanner la classe entière pour confirmer ce qui est et n'est pas une constante ; un bloc trié unique en haut, après les champs, est le lieu canonique pour chercher.
Examples:
public class Foo {
+ private static final String _ALPHA = "alpha";
+
+ private static final String _BAR = "bar";
+
public void doFirst() {
- }
-
- private static final String _BAR = "bar";
-
- public void doSecond() {
}
- private static final String _ALPHA = "alpha";
+ public void doSecond() {
+ }
}
Rule 40: Methods Used Only Inside the Class Must Be private
Why: Visibilité par défaut ou public sur une méthode interne à la classe surestime le contrat ; un lecteur ne peut pas dire de la signature seule si des appelants externes existent, et les outils ne peuvent pas élaguer la méthode quand ses appelants disparaissent.
Examples:
-void _doInternal() {
+private void _doInternal() {
// ...
}
Rule 41: Method Names Start With a Verb
Why: Une méthode représente une action, donc son nom doit commencer par une (get, set, is, make, attach, verify, …) ; un nom nom-seulement se lit comme un champ, pas un appel.
Examples:
-private boolean _osgiAware() {
+private boolean _isOsgiAware() {
return _bundleContext != null;
}
Rule 42: Constant Names Lead With Their Group Prefix
Why: Quand les noms de constantes commencent par leur catégorie (<PREFIX>_<KIND>_<VALUE>), un tri alphabétique place chaque membre du groupe ensemble ; le début avec la valeur éparpille le groupe dans le fichier.
Examples:
-private static final String _DXP_ONLY_BUNDLE_NAME = "...";
-private static final String _ENTERPRISE_APP_BUNDLE_NAME = "...";
+private static final String _BUNDLE_NAME_DXP_ONLY = "...";
+private static final String _BUNDLE_NAME_ENTERPRISE_APP = "...";
Rule 43: Blank Line Between Dependent Resources in try-With-Resources
Why: Quand un try à plusieurs ressources mélange des ressources indépendantes avec une qui les consomme, une ligne vide entre le groupe indépendant et le consommateur rend la dépendance visible au niveau de la déclaration de ressource au lieu de forcer le lecteur à la tracer dans le corps.
Examples:
try (
PreparedStatement preparedStatement1 = connection.prepareStatement(selectSQL);
PreparedStatement preparedStatement2 = connection.prepareStatement(updateSQL);
+
ResultSet resultSet = preparedStatement1.executeQuery()) {
Rule 44: Do Not Wrap and Rethrow a Checked Exception
Why: Envelopper une exception attrapée dans une exception runtime générique (ou un équivalent spécifique au framework) cache à la fois le type original et la frame de pile originale ; le premier choix est de laisser l'original se propager en le déclarant sur la méthode.
Examples:
-try {
- parser.read(input);
-}
-catch (IOException ioException) {
- throw new PortalException(ioException);
-}
+parser.read(input);
Exception: Quand la signature de la méthode ne peut pas être changée (un override d'interface, un callback dont le contrat interdit le type vérifié), envelopper est l'échappatoire nécessaire. Utilisez un utilitaire connu (ReflectionUtil.throwException, _log.error plus un type runtime spécifique au domaine) et gardez l'original comme cause pour que la frame de pile survive.
Rule 45: Drop Defensive Math.ceil on Whole-Unit Division
Why: Quand convertir une valeur unité entière (millisecondes en secondes, octets en kilooctets) pour une entrée dont les valeurs réalistes sont déjà des multiples du diviseur, Math.ceil ajoute une promotion double et un cast primitif qui tous s'effondrent pour toute entrée réelle ; la division entière fait le même travail.
Examples:
-long seconds = (long)Math.ceil(milliseconds / 1000.0);
+long seconds = milliseconds / 1000;
Rule 46: Burrito — Declarations Before Configuration, Outer Before Inner
Why: Grouper toutes les déclarations ensemble et toutes les configurations ensemble — avec l'objet le plus externe/sortie d'abord — rend le but d'un bloc visible en avant et élimine le code « spaghetti » où les étapes create-et-configure sont entrelacées quand vous descendez la chaîne de dépendance.
Examples:
Sortie/accumulateur déclaré en premier. Quand un bloc construit une collection et la retourne ou la passe, déclarez la variable de sortie en haut — avant les variables d'entrée et source — même si elle est peuplée plus tard dans la boucle. Comme Brian Chan l'a dit : « l'indice est que vous retournez X, donc nous voulons envelopper les vars autour de ceci. »
+List<OutputType> results = new ArrayList<>();
+
InputType input = fetchInput(arg);
List<SourceType> sources = service.getSources(input.getId());
-List<OutputType> results = new ArrayList<>();
-
for (SourceType source : sources) {
results.add(transform(source));
}
return results;
Cela s'applique aussi aux accumulateurs Map, Set, et JSONObject — ce qui est construit et retourné va en haut.
Objets externes déclarés d'abord, puis configurés de l'intérieur vers l'extérieur. Quand mettre en place une hiérarchie de conteneur (A enveloppe B enveloppe C), déclarez tous les objets en avant dans l'ordre externe-à-interne, puis configurez-les de l'intérieur vers l'extérieur. N'entrelacez pas déclaration et configuration quand vous traversez la chaîne.
+ContainerA containerA = new ContainerA();
+ContainerB containerB = new ContainerB();
+
ContainerC containerC = new ContainerC();
containerC.setContent(content);
-ContainerB containerB = new ContainerB();
-
containerB.setContainerC(containerC);
-ContainerA containerA = new ContainerA();
-
containerA.setContainerB(containerB);
Dans les tests basés sur Mockito la même règle s'applique : déclarez tous les mocks d'abord dans l'ordre externe-à-interne (le mock qui enveloppe ou reçoit des autres vient en premier), puis écrivez les stubs Mockito.when() de l'intérieur vers l'extérieur.
+OuterMock outerMock = Mockito.mock(OuterMock.class);
+
InnerMock innerMock = Mockito.mock(InnerMock.class);
Mockito.when(
innerMock.getValue()
).thenReturn(
value
);
-OuterMock outerMock = Mockito.mock(OuterMock.class);
-
Mockito.when(
outerMock.getInner()
).thenReturn(
innerMock
);
C'est le complément de Rule 14 : les variables d'entrée intermédiaires se déplacent vers le bas (à côté de la première utilisation), tandis que les variables de sortie et d'enveloppe se déplacent vers le haut (déclarées avant le code qui les alimente).
Rule 47: Parameter-Aligned Variable Naming
Why: Quand une variable locale porte une valeur directement dans un appel de méthode, la nommer après le paramètre de la méthode rend le site d'appel auto-documenté et élimine la surcharge de traduction pour le lecteur qui doit sinon réconcilier un synonyme avec la signature de la méthode.
Examples:
Quand une locale est passée comme un paramètre spécifique nommé, adoptez le nom du paramètre plutôt qu'une description alternative de la même valeur.
-boolean httpsEnabled = _isHttpsEnabled();
+boolean secure = _isSecure();
String baseURL = _portal.getPortalURL(
company.getVirtualHostname(),
- _portal.getPortalServerPort(httpsEnabled), httpsEnabled);
+ _portal.getPortalServerPort(secure), secure);
Cela s'applique aussi quand renommer une méthode ou son paramètre pour correspondre au vocabulaire de l'API qu'elle délègue.
private Map<Locale, String> _getLocalizedMap(
- String value, Map<String, String> i18nMap) {
+ String defaultValue, Map<String, String> i18nMap) {
Map<Locale, String> localizedMap = LocalizedMapUtil.getLocalizedMap(
- contextAcceptLanguage.getPreferredLocale(), value, i18nMap);
+ contextAcceptLanguage.getPreferredLocale(), defaultValue, i18nMap);
Les variables Page<T> utilisent la forme plurielle de la méthode qui les a retournées. Si la méthode est getItemsPage(...), nommez la variable itemsPage, pas itemPage.
-Page<OrderItem> orderItemPage =
+Page<OrderItem> orderItemsPage =
service.getOrderIdOrderItemsPage(orderId, pagination);
-for (OrderItem orderItem : orderItemPage.getItems()) {
+for (OrderItem orderItem : orderItemsPage.getItems()) {
Quand vous renommez une locale, propagez le nouveau nom à chaque site d'appel, chaque paramètre qui la passe, et chaque helper privé qui la reçoit.
Rule 48: Chicago Title Case for Titles in Language Properties
Why: Les titres dans Language.properties — labels, headings, texte de bouton, options de dropdown, valeurs de filtre — suivent le Chicago Manual of Style : capitaliser le premier mot, le dernier mot, et chaque mot majeur (noms, verbes, adjectifs, adverbes, pronoms), et garder les articles, conjonctions de coordination et prépositions en minuscules. Les phrases et phrases inline restent en sentence case ; les phrases complètes tombent sous Rule 18.
Examples:
-some-key=Alpha of the bravo
+some-key=Alpha of the Bravo