web-dev-qa-db-fra.com

Quel est le meilleur moyen d'implémenter des constantes en Java?

J'ai vu des exemples comme celui-ci:

public class MaxSeconds {
   public static final int MAX_SECONDS = 25;
}

et supposé que je pouvais avoir une classe Constants pour envelopper les constantes, en les déclarant statiques final. Je ne connais pratiquement pas Java et je me demande si c'est le meilleur moyen de créer des constantes.

373
mk.

C'est parfaitement acceptable, probablement même la norme.

(public/private) static final TYPE NAME = VALUE;

TYPE est le type, NAME est le nom en majuscule avec des traits de soulignement pour les espaces et VALUE est la valeur constante.

Je recommande fortement de NE PAS mettre vos constantes dans leurs propres classes ou interfaces.

Remarque: les variables déclarées finales et modifiables peuvent toujours être modifiées. Cependant, la variable ne peut jamais pointer sur un autre objet.

Par exemple:

public static final Point Origin = new Point(0,0);

public static void main(String[] args){

    Origin.x = 3;

}

C’est légal et Origin serait alors un point à (3, 0).

403
jjnguy

Je déconseillerais fortement d'avoir une seule classe de constantes. Cela peut sembler une bonne idée à l’époque, mais lorsque les développeurs refusent de documenter les constantes et que la classe se développe pour englober plus de 500 constantes qui ne sont pas liées les unes aux autres (liées à des aspects totalement différents de l’application), se transforme généralement en fichier de constantes complètement illisible. Au lieu:

  • Si vous avez accès à Java 5+, utilisez des énumérations pour définir vos constantes spécifiques pour un domaine d'application. Toutes les parties du domaine d'application doivent faire référence à des énumérations, et non à des valeurs constantes, pour ces constantes. Vous pouvez déclarer une énumération similaire à la façon dont vous déclarez une classe. Les enums sont peut-être la fonctionnalité la plus utile (et, probablement, la seule) de Java 5+.
  • Si vous avez des constantes qui ne sont valides que pour une classe particulière ou l'une de ses sous-classes, déclarez-les comme protégées ou publiques et placez-les sur la première classe de la hiérarchie. De cette façon, les sous-classes peuvent accéder à ces valeurs constantes (et si d'autres classes y accèdent via public, les constantes ne sont pas valables pour une classe particulière ... ce qui signifie que les classes externes utilisant cette constante peuvent être trop étroitement couplées au classe contenant la constante)
  • Si vous avez une interface avec un comportement défini, mais que les valeurs renvoyées ou les valeurs d'argument doivent être particulières, il est parfaitement acceptable de définir des constantes sur cette interface afin que les autres implémenteurs y aient accès. Cependant, évitez de créer une interface uniquement pour contenir des constantes: cela peut devenir aussi grave qu'une classe créée uniquement pour contenir des constantes.
235
MetroidFan2002

C’est un BAD PRACTICE utiliser des interfaces uniquement pour contenir des constantes (nommé modèle d’interface constant de Josh Bloch). Voici ce que Josh conseille:

Si les constantes sont fortement liées à une classe ou une interface existante, vous devez les ajouter à la classe ou à l'interface. Par exemple, toutes les classes de primitives numériques encadrées, telles que Integer et Double, exportent les constantes MIN_VALUE et MAX_VALUE. Si les constantes sont mieux considérées en tant que membres d'un type énuméré, vous devez les exporter avec un type enum. Sinon, vous devez exporter les constantes avec une classe d'utilité non instable.

Exemple:

// Constant utility class
package com.effectivejava.science;
public class PhysicalConstants {
    private PhysicalConstants() { }  // Prevents instantiation

    public static final double AVOGADROS_NUMBER   = 6.02214199e23;
    public static final double BOLTZMANN_CONSTANT = 1.3806503e-23;
    public static final double ELECTRON_MASS      = 9.10938188e-31;
}

A propos de la convention de nommage:

Par convention, ces champs ont des noms composés de lettres majuscules, avec des mots séparés par des tirets bas. Il est essentiel que ces champs contiennent des valeurs primitives ou des références à des objets immuables.

120
Marcio Aguiar

Dans Effective Java (2e édition), il est recommandé d'utiliser des énumérations au lieu des entêtes statiques pour les constantes.

Il y a un bon article sur les énumérations dans Java ici: http://Java.Sun.com/j2se/1.5.0/docs/guide/language/enums.html

Notez qu'à la fin de cet article la question posée est:

Alors, quand devriez-vous utiliser des enums?

Avec une réponse de:

Chaque fois que vous avez besoin d'un ensemble fixe de constantes

36
shelfoo

Évitez simplement d'utiliser une interface:

public interface MyConstants {
    String CONSTANT_ONE = "foo";
}

public class NeddsConstant implements MyConstants {

}

C'est tentant, mais viole l'encapsulation et brouille la distinction entre les définitions de classe.

21
stimpy

J'utilise l'approche suivante:

public final class Constants {
  public final class File {
    public static final int MIN_ROWS = 1;
    public static final int MAX_ROWS = 1000;

    private File() {}
  }

  public final class DB {
    public static final String name = "oups";

    public final class Connection {
      public static final String URL = "jdbc:tra-ta-ta";
      public static final String USER = "testUser";
      public static final String PASSWORD = "testPassword";

      private Connection() {}
    }

    private DB() {}
  }

  private Constants() {}
}

Par exemple, j’utilise Constants.DB.Connection.URL pour obtenir une constante. Il me semble plus "orienté objet".

19
albus.ua

La création de constantes finales statiques dans une classe séparée peut vous poser des problèmes. Le compilateur Java l'optimise et place la valeur réelle de la constante dans toute classe qui la référence.

Si par la suite vous changez la classe 'Constants' et vous ne recompilez pas durement sur d'autres classes référençant cette classe, vous obtiendrez une combinaison d'anciennes et de nouvelles valeurs.

Au lieu de les considérer comme des constantes, considérez-les comme des paramètres de configuration et créez une classe pour les gérer. Les valeurs doivent être non finales et même envisager d’utiliser des accesseurs. À l'avenir, si vous déterminez que certains de ces paramètres doivent en réalité être configurables par l'utilisateur ou l'administrateur, ce sera beaucoup plus facile à faire.

17
Kevin Day

L'erreur numéro un que vous pouvez commettre est de créer une classe accessible globalement, appelée avec un nom générique, telle que Constants. Cela est simplement jonché de déchets et vous perdez toute possibilité de déterminer quelle partie de votre système utilise ces constantes.

Au lieu de cela, les constantes doivent aller dans la classe qui les "possède". Avez-vous une constante appelée TIMEOUT? Il devrait probablement aller dans votre classe Communications () ou Connection (). MAX_BAD_LOGINS_PER_HOUR? Va dans l'utilisateur (). Et ainsi de suite.

L'autre utilisation possible est les fichiers Java .properties lorsque des "constantes" peuvent être définies au moment de l'exécution, mais ne sont pas facilement modifiables par l'utilisateur. Vous pouvez les empaqueter dans vos fichiers .jars et les référencer avec le class resourceLoader.

13
Yann Ramin

C'est la bonne façon de faire.

Généralement, les constantes sont pas conservées dans des classes "Constantes" distinctes car elles ne sont pas découvrables. Si la constante est pertinente pour la classe actuelle, leur maintien aide le développeur suivant.

6
Jason Cohen

Je conviens que l'utilisation d'une interface n'est pas la solution. Éviter ce motif a même son propre élément (# 18) dans Bloch's Effective Java .

Un argument que Bloch avance contre le modèle d'interface constant est que l'utilisation de constantes est un détail d'implémentation, mais l'implémentation d'une interface pour les utiliser expose ces détails d'implémentation dans votre API exportée.

Le modèle public|private static final TYPE NAME = VALUE; est un bon moyen de déclarer une constante. Personnellement, je pense qu'il est préférable d'éviter de faire une classe séparée pour héberger toutes vos constantes, mais je n'ai jamais vu de raison de ne pas le faire, autre que les préférences personnelles et le style.

Si vos constantes peuvent être bien modélisées comme une énumération, considérez la structure enum disponible dans la version 1.5 ou ultérieure.

Si vous utilisez une version antérieure à 1.5, vous pouvez toujours extraire des énumérations dactylographiées en utilisant les classes normales Java. (Voir ce site pour plus d'informations).

5
Rob Dickerson

Qu'en est-il d'une énumération?

5
Sébastien D.

Je préfère utiliser des accesseurs plutôt que des constantes. Ces accesseurs peuvent renvoyer des valeurs constantes, par exemple public int getMaxConnections() {return 10;}, mais tout ce qui a besoin de la constante passera par un getter.

Un des avantages est que si votre programme dépasse la constante - vous trouvez qu’il doit être configurable - vous pouvez simplement changer la façon dont le getter renvoie la constante.

L’autre avantage est que, pour modifier la constante, il n’est pas nécessaire de recompiler tout ce qui l’utilise. Lorsque vous référencez un champ final statique, la valeur de cette constante est compilée dans tout bytecode qui la référence.

5
big_peanut_horse

Sur la base des commentaires ci-dessus, je pense que c'est une bonne approche pour changer la classe constante globale à l'ancienne (ayant des variables finales statiques publiques) en son équivalent enum de la manière suivante:

public class Constants {

    private Constants() {
        throw new AssertionError();
    }

    public interface ConstantType {}

    public enum StringConstant implements ConstantType {
        DB_Host("localhost");
        // other String constants come here

        private String value;
        private StringConstant(String value) {
            this.value = value;
        }
        public String value() {
            return value;
        }
    }

    public enum IntConstant implements ConstantType {
        DB_PORT(3128), 
        MAX_PAGE_SIZE(100);
        // other int constants come here

        private int value;
        private IntConstant(int value) {
            this.value = value;
        }
        public int value() {
            return value;
        }
    }

    public enum SimpleConstant implements ConstantType {
        STATE_INIT,
        STATE_START,
        STATE_END;
    }

}

Alors je peux les renvoyer comme:

Constants.StringConstant.DB_Host
4
Lorand Bendig

Une bonne conception orientée objet ne devrait pas nécessiter beaucoup de constantes disponibles publiquement. La plupart des constantes doivent être encapsulées dans la classe qui en a besoin pour faire son travail.

3
Bradley Harris

Il y a un certain nombre d'opinions pour répondre à cela. Pour commencer, les constantes dans Java sont généralement déclarées publiques, statiques et finales. En voici les raisons:

public, so that they are accessible from everywhere
static, so that they can be accessed without any instance. Since they are constants it
  makes little sense to duplicate them for every object.
final, since they should not be allowed to change

Je n'utiliserais jamais une interface pour un accesseur/objet CONSTANTS simplement parce que les interfaces doivent généralement être implémentées. Est-ce que ça n'a pas l'air drôle?

String myConstant = IMyInterface.CONSTANTX;

Au lieu de cela, je choisirais entre plusieurs manières différentes, en fonction de petits compromis, et cela dépend donc de ce dont vous avez besoin:

1.  Use a regular enum with a default/private constructor. Most people would define 
     constants this way, IMHO.
  - drawback: cannot effectively Javadoc each constant member
  - advantage: var members are implicitly public, static, and final
  - advantage: type-safe
  - provides "a limited constructor" in a special way that only takes args which match
     predefined 'public static final' keys, thus limiting what you can pass to the
     constructor

2.  Use a altered enum WITHOUT a constructor, having all variables defined with 
     prefixed 'public static final' .
  - looks funny just having a floating semi-colon in the code
  - advantage: you can JavaDoc each variable with an explanation
  - drawback: you still have to put explicit 'public static final' before each variable
  - drawback: not type-safe
  - no 'limited constructor'

3.  Use a Class with a private constructor:
  - advantage: you can JavaDoc each variable with an explanation
  - drawback: you have to put explicit 'public static final' before each variable
  - you have the option of having a constructor to create an instance
     of the class if you want to provide additional functions related
     to your constants 
     (or just keep the constructor private)
  - drawback: not type-safe

4. Using interface:
  - advantage: you can JavaDoc each variable with an explanation
  - advantage: var members are implicitly 'public static final'
  - you are able to define default interface methods if you want to provide additional
     functions related to your constants (only if you implement the interface)
  - drawback: not type-safe
2
djangofan

Quel est le meilleur moyen d'implémenter des constantes en Java?

Une approche à éviter : utiliser des interfaces pour définir des constantes.

Créer une interface spécifiquement pour déclarer des constantes est vraiment la pire des choses: il élimine la raison pour laquelle les interfaces ont été conçues: définir le (s) contrat (s) de méthode (s).

Même si une interface existe déjà pour répondre à un besoin spécifique, déclarer les constantes qu'elles contiennent n'a pas vraiment de sens, car les constantes ne doivent pas faire partie de l'API et du contrat fourni aux classes clientes.


Pour simplifier, nous avons en gros 4 approches valables .

Avec le champ _static final String/Integer_:

  • 1) en utilisant une classe qui déclare des constantes à l'intérieur mais pas seulement.
  • 1 variante) créer une classe dédiée à ne déclarer que des constantes.

Avec _Java 5 enum_:

  • 2) déclarer l'énumération dans une classe d'objet connexe (en tant que classe imbriquée).
  • 2 variante) créant l'énumération en tant que classe autonome (ainsi définie dans son propre fichier de classe).

TLDR: Quel est le meilleur moyen et où localiser les constantes?

Dans la plupart des cas, le chemin enum est probablement plus fin que le chemin _static final String/Integer_ et personnellement, je pense que le chemin _static final String/Integer_ devrait être utilisé que si nous avons de bonnes raisons de ne pas utiliser d’énums.
Et pour savoir où nous devrions déclarer les valeurs constantes, , l’idée est de rechercher s’il existe une seule classe existante possédant une cohésion fonctionnelle spécifique et forte avec des valeurs constantes. Si nous trouvons une telle classe, nous devrions l’utiliser comme détenteur des constantes . Sinon, la constante ne devrait être associée à aucune classe en particulier.


static final String_/_static final Integer_ VERSUS enum

L'utilisation d'énums est vraiment un moyen de prendre en compte fortement.
Les énumérations ont un grand avantage sur le champ constant String ou Integer.
Ils fixent une contrainte de compilation plus forte. Si vous définissez une méthode qui prend enum en paramètre, vous pouvez uniquement transmettre une valeur enum définie dans la classe enum (ou null).
Avec String et Integer, vous pouvez les remplacer par n’importe quelle valeur de type compatible. La compilation se déroulera sans problème même si la valeur n’est pas une constante définie dans les champs _static final String_/_static final Integer_.

Par exemple, ci-dessous deux constantes définies dans une classe sous la forme de champs _static final String_:

_public class MyClass{

   public static final String ONE_CONSTANT = "value";
   public static final String ANOTHER_CONSTANT = "other value";
   . . .
}
_

Voici une méthode qui s'attend à avoir l'une de ces constantes en paramètre:

_public void process(String constantExpected){
    ...    
}
_

Vous pouvez l'invoquer de cette manière:

_process(MyClass.ONE_CONSTANT);
_

ou

_process(MyClass.ANOTHER_CONSTANT);
_

Mais aucune contrainte de compilation ne vous empêche de l'invoquer de cette manière:

_process("a not defined constant value");
_

L'erreur ne se produit qu'au moment de l'exécution et uniquement si vous vérifiez simultanément la valeur transmise.

Avec enum, les vérifications ne sont pas obligatoires car le client ne pouvait transmettre qu'une valeur enum dans un paramètre enum.

Par exemple, voici deux valeurs définies dans une classe enum (donc constantes):

_public enum MyEnum {

    ONE_CONSTANT("value"), ANOTHER_CONSTANT(" another value");

    private String value;

    MyEnum(String value) {
       this.value = value;
    }
         ...
}
_

Voici une méthode qui s'attend à avoir l'une de ces valeurs enum en paramètre:

_public void process(MyEnum myEnum){
    ...    
}
_

Vous pouvez l'invoquer de cette manière:

_process(MyEnum.ONE_CONSTANT);
_

ou

_process(MyEnum.ANOTHER_CONSTANT);
_

Mais la compilation ne vous permettra jamais de l'invoquer de cette façon:

_process("a not defined constant value");
_

Où devons-nous déclarer les constantes?

Si votre application contient une seule classe existante qui possède une cohésion fonctionnelle spécifique et forte avec les valeurs constantes, les valeurs 1) et 2) apparaissent plus intuitives.
Généralement, cela facilite l’utilisation des constantes si elles sont déclarées dans la classe principale qui les manipule ou dont le nom est très naturel de deviner qu’elles seront trouvées à l’intérieur.

Par exemple, dans la bibliothèque JDK, les valeurs exponentielles et constantes pi sont déclarées dans une classe qui ne déclare pas uniquement les déclarations constantes (_Java.lang.Math_).

_   public final class Math {
          ...
       public static final double E = 2.7182818284590452354;
       public static final double PI = 3.14159265358979323846;
         ...
   }
_

Les clients utilisant des fonctions mathématiques ont souvent recours à la classe Math. Ainsi, ils peuvent trouver les constantes assez facilement et peuvent également se souvenir où E et PI sont définis de manière très naturelle.

Si votre application ne contient pas de classe existante ayant une cohésion fonctionnelle très spécifique et forte avec les valeurs constantes, les variantes 1) et 2) apparaissent plus intuitives.
En règle générale, l’utilisation des constantes n’est pas facilitée si elles sont déclarées dans une classe qui les manipule, alors que nous avons également 3 ou 4 autres classes qui les manipulent autant que si aucune de ces classes ne semble être plus naturel que d’autres d’héberger des valeurs constantes.
Ici, définir une classe personnalisée pour ne conserver que des valeurs constantes a du sens.
Par exemple, dans la bibliothèque JDK, l'enumération _Java.util.concurrent.TimeUnit_ n'est pas déclarée dans une classe spécifique car il n'y a pas vraiment une seule et unique classe spécifique JDK qui apparaît comme la plus intuitive pour la contenir:

_public enum TimeUnit {
    NANOSECONDS {
      .....
    },
    MICROSECONDS {
      .....
    },
    MILLISECONDS {
      .....
    },
    SECONDS {
      .....
    },
      .....
}      
_

De nombreuses classes déclarées dans _Java.util.concurrent_ les utilisent: BlockingQueue, _ArrayBlockingQueue<E>_, CompletableFuture, ExecutorService, ... et aucune d'entre elles ne semble plus appropriée pour tenir l'énum.

2
davidxxx

FWIW, une valeur de délai d'expiration en secondes devrait probablement être un paramètre de configuration (lu à partir d'un fichier de propriétés ou par injection, comme dans Spring), et non une constante.

1
Tim Howland

Quelle est la différence

1.

public interface MyGlobalConstants {
    public static final int TIMEOUT_IN_SECS = 25;
}

2.

public class MyGlobalConstants {
    private MyGlobalConstants () {} // Prevents instantiation
    public static final int TIMEOUT_IN_SECS = 25;
}

et en utilisant MyGlobalConstants.TIMEOUT_IN_SECS partout où nous avons besoin de cette constante. Je pense que les deux sont identiques.

1
chandrayya

Une seule classe de constantes génériques est une mauvaise idée. Les constantes doivent être regroupées avec la classe à laquelle elles sont le plus logiquement associées.

Plutôt que d'utiliser des variables de tout type (en particulier des énumérations), je vous suggérerais d'utiliser des méthodes. Créez une méthode avec le même nom que la variable et demandez-lui de renvoyer la valeur que vous avez affectée à la variable. Supprimez maintenant la variable et remplacez toutes ses références par des appels à la méthode que vous venez de créer. Si vous estimez que la constante est suffisamment générique pour que vous n'ayez pas à créer une instance de la classe uniquement pour l'utiliser, faites de la méthode constante une méthode de classe.

1
ab

Une constante, de tout type, peut être déclarée en créant une propriété immuable qui appartient à une classe (c'est-à-dire une variable membre avec le modificateur final.). Les modificateurs static et public sont également fournis.

public class OfficePrinter {
    public static final String STATE = "Ready";  
}

Il existe de nombreuses applications dans lesquelles la valeur d'une constante indique une sélection parmi un n-Tuple (par exemple, énumération). Dans notre exemple, nous pouvons choisir de définir un type énuméré qui limitera les valeurs attribuées possibles (c'est-à-dire amélioré sécurité de type):

public class OfficePrinter {
    public enum PrinterState { Ready, PCLoadLetter, OutOfToner, Offline };
    public static final PrinterState STATE = PrinterState.Ready;
}
1
Ryan Delucchi

Je n'appellerais pas la classe la même chose (à part la casse) que la constante ... J'aurais au moins une classe de "Paramètres", ou "Valeurs", ou "Constantes", où vivraient toutes les constantes. Si j'en ai un grand nombre, je les regrouperais en classes de constantes logiques (UserSettings, AppSettings, etc.).

0
Joel Martinez

static final est ma préférence, j'utiliserais un enum si l'élément était effectivement énumérable.

0
wulfgarpro

Il est MAUVAISE habitude et terriblement annulant la pratique de citer Joshua Bloch sans comprendre le fondamentalisme de base zéro.

Je n'ai rien lu Joshua Bloch, donc soit

  • il est un programmeur terrible
  • ou les personnes que je trouve à ce jour le citant (Joshua est le nom d'un garçon, je présume) utilisent simplement son matériel comme script religieux pour justifier leurs logiciels d'indulgences religieuses.

Comme dans le fondamentalisme biblique, toutes les lois bibliques peuvent être résumées par

  • Aime l'identité fondamentale de tout ton cœur et de tout ton esprit
  • Aime ton prochain comme toi-même

et de la même façon, le fondamentalisme de génie logiciel peut être résumé par

  • consacrez-vous aux principes fondamentaux du sol zéro avec toute votre puissance de programmation et de l'esprit
  • et consacrez-vous à l’excellence de vos collègues programmeurs comme vous le feriez pour vous-même.

En outre, parmi les milieux fondamentalistes bibliques, un corollaire fort et raisonnable est tiré

  • D'abord aime toi. Parce que si vous ne vous aimez pas beaucoup, le concept "aimez votre prochain comme vous-même" n'a pas beaucoup de poids, puisque "combien tu t'aimes" est la ligne de référence au-dessus de laquelle tu aimerais les autres.

De même, si vous ne vous respectez pas en tant que programmeur et acceptez simplement les déclarations et les prophéties de certains programmeurs guru-nath SANS remettre en question les principes fondamentaux, vos citations et votre confiance en Joshua Bloch (et autres) n'auront aucun sens. Et par conséquent, vous n’auriez aucun respect pour vos collègues programmeurs.

Les lois fondamentales de la programmation logicielle

  • la paresse est la vertu d'un bon programmeur
  • vous devez rendre votre vie de programmation aussi facile, paresseuse et donc aussi efficace que possible
  • vous devez rendre les conséquences et les entrailles de votre programmation aussi faciles, paresseuses et donc aussi efficaces que possible pour vos voisins programmeurs qui travaillent avec vous et récupèrent vos entrailles de programmation.

Les constantes de motif d'interface sont une mauvaise habitude ???

Sous quelles lois de programmation fondamentalement efficace et responsable s'inscrit cet édit religieux?

Il suffit de lire l’article de Wikipédia sur les constantes de modèle d’interface ( https://en.wikipedia.org/wiki/Constant_interface ), et les excuses idiotes qu’il énonce à l’égard des constantes de modèle d’interface.

  • Whatif-No IDE? Qui sur la terre en tant que programmeur de logiciel ne serait pas utiliser un IDE? La plupart d’entre nous sont des programmeurs qui préfèrent ne pas avoir à prouver qu’ils ont recours à un système de survie aescétique et macho en évitant l’utilisation d’un IDE.

    • De plus, attendez un deuxième partisan de la programmation micro-fonctionnelle afin de ne pas avoir besoin d'un IDE. Attendez de lire mon explication sur la normalisation des modèles de données.
  • Pollue l'espace de noms avec des variables non utilisées dans la portée actuelle? Ce pourrait être les partisans de cet avis

    • ne sont pas conscients de la nécessité de normaliser les modèles de données et de leur nécessité
  • L'utilisation d'interfaces pour appliquer des constantes constitue un abus des interfaces. Les partisans de tels ont une mauvaise habitude de

    • ne voyant pas que les "constantes" doivent être traitées comme des contrats. Et les interfaces sont utilisées pour imposer ou projeter la conformité à un contrat.
  • Il est difficile, voire impossible, de convertir les interfaces en classes implémentées à l'avenir. Hah… hmmm… ???

    • Pourquoi voudriez-vous vous engager dans une telle structure de programmation que votre gagne-pain persistant? IOW, pourquoi se consacrer à une telle habitude de programmation si ambivalente et si mauvaise?

Quelles que soient les excuses, il n’ya pas d’excuse valable en matière de génie logiciel fondamentalement efficace pour délégitimer ou généralement décourager l’utilisation de constantes d’interface.

Peu importent les intentions et les états mentaux d'origine des pères fondateurs qui ont rédigé la Constitution des États-Unis. Nous pourrions débattre des intentions originales des pères fondateurs mais tout ce qui m'importe, ce sont les déclarations écrites de la Constitution américaine. Et chaque citoyen américain a la responsabilité d'exploiter le fondamentalisme littéraire écrit, et non les intentions fondatrices non écrites, de la Constitution américaine.

De même, je me fiche de ce que les intentions "originales" des fondateurs de la plate-forme Java et du langage de programmation avaient pour l'interface. Ce qui m'importe, ce sont les fonctionnalités efficaces fournies par la spécification Java, et je compte exploiter ces fonctionnalités au maximum pour m'aider à respecter les lois fondamentales de la programmation logicielle responsable. Je ne me soucie pas si je suis perçu pour "violer l'intention d'interfaces". Je me fiche de ce que Gosling ou de quelqu'un de Bloch dit à propos de la "bonne façon d'utiliser Java", à moins que ce qu'ils disent ne viole pas mon besoin de réaliser efficacement les fondamentaux.

L'essentiel est la normalisation du modèle de données

Peu importe la manière dont votre modèle de données est hébergé ou transmis. Que vous utilisiez des interfaces ou des énumérations ou des noms virtuels, relationnels ou non-SQL, si vous ne comprenez pas la nécessité et le processus de la normalisation des modèles de données.

Nous devons d’abord définir et normaliser le modèle de données d’un ensemble de processus. Et lorsque nous avons un modèle de données cohérent, nous ne pouvons UNIQUEMENT qu'utiliser le flux de processus de ses composants pour définir le comportement fonctionnel et bloquer en bloc un champ ou un domaine d'applications. Et alors seulement, nous pouvons définir l’API de chaque processus fonctionnel.

Même les aspects de la normalisation des données proposés par EF Codd sont maintenant sérieusement contestés et gravement contestés. par exemple. sa déclaration sur 1NF a été critiquée pour son ambiguïté, son désalignement et sa simplification excessive, comme le reste de ses déclarations, en particulier avec l'avènement des services de données modernes, de la technologie repo et de la transmission. OMI, les déclarations EF Codd doivent être complètement abandonnées et un nouvel ensemble d’énoncés plus mathématiquement plausibles doit être conçu.

Un défaut flagrant d'EF Codd et la cause de son décalage par rapport à une compréhension humaine effective est sa conviction que des données multidimensionnelles, humainement perceptibles, de dimension mutable peuvent être efficacement perçues grâce à un ensemble de mappages bidimensionnels fragmentés.

Les bases de la normalisation des données

Ce qu'EF Codd n'a pas pu exprimer.

Au sein de chaque modèle de données cohérent, il s'agit de l'ordre séquentiel séquentiel de cohérence à appliquer au modèle de données.

  1. L'unité et l'identité des instances de données.
    • concevoir la granularité de chaque composant de données, leur granularité se situant à un niveau où chaque instance d'un composant peut être identifiée et récupérée de manière unique.
    • absence d'instance aliasing. c'est-à-dire qu'il n'existe aucun moyen par lequel une identification produit plus d'une instance d'un composant.
  2. Absence de diaphonie d'instance. Il n’existe pas la nécessité d’utiliser une ou plusieurs autres instances d’un composant pour contribuer à l’identification d’une instance d’un composant.
  3. L'unité et l'identité des composants/dimensions des données.
    • Présence de dé-aliasing de composant. Il doit exister une définition unique permettant d'identifier un composant/dimension. Quelle est la définition primaire d'un composant?
    • où la définition principale n'entraînera pas l'exposition de sous-dimensions ou de composants de membre qui ne font pas partie d'un composant prévu;
  4. Un moyen unique de désiasing des composants. Il doit exister une, et une seule, définition de ce type qui supprime le repliement d'un composant.
  5. Il existe une, et une seule, interface de définition ou contrat permettant d'identifier un composant parent dans une relation hiérarchique de composants.
  6. Absence de diaphonie des composants. Il n’existe pas la nécessité d’utiliser un membre d’un autre composant pour contribuer à l’identification définitive d’un composant.
    • Dans une telle relation parent-enfant, la définition identificatrice d'un parent ne doit pas dépendre d'une partie de l'ensemble des composants membres d'un enfant. Un élément membre de l'identité d'un parent doit être l'identité complète de l'enfant sans avoir recours à la référence à aucun ou à tous les enfants d'un enfant.
  7. Préempter les apparences bimodales ou multimodales d'un modèle de données.
    • Lorsqu'il existe deux définitions possibles d'un composant, il est évident que deux modèles de données différents sont mélangés en un seul. Cela signifie qu'il y a une incohérence au niveau du modèle de données ou au niveau du champ.
    • Un domaine d'applications doit utiliser un et un seul modèle de données, de manière cohérente.
  8. Détecter et identifier la mutation du composant. À moins que vous n'ayez effectué une analyse statistique par composant de données volumineuses, vous ne voyez probablement pas ou ne voyez pas la nécessité de traiter une mutation du composant.
    • Un modèle de données peut avoir certaines de ses composantes muter de manière cyclique ou progressive.
    • Le mode peut être rotation d'élément ou rotation de transposition.
    • Une mutation de rotation de membre pourrait être un échange distinct de composants enfants entre composants. Ou alors, il faudrait définir de nouveaux composants.
    • Une mutation transpositive se manifesterait sous la forme d'un membre dimensionnel en mutation dans un attribut, et inversement.
    • Chaque cycle de mutation doit être identifié comme un modal de données distinct.
  9. Versionaliser chaque mutation. Telle que vous pouvez extraire une version précédente du modèle de données, lorsque peut-être la nécessité de traiter une mutation de 8 ans du modèle de données.

Dans un champ ou une grille d'applications-composants inter-services, il doit exister un et un seul modèle de données cohérent ou un moyen permettant à un modèle/version de données de s'identifier.

Demandons-nous toujours si nous pourrions utiliser les constantes d'interface? Vraiment ?

Des problèmes de normalisation des données sont plus en jeu que cette question banale. Si vous ne résolvez pas ces problèmes, la confusion que vous pensez des constantes d’interface est relativement nulle. Rien.

À partir de la normalisation du modèle de données, vous déterminez ensuite les composants en tant que variables, propriétés et constantes d'interface de contrat.

Vous déterminez ensuite ce qui entre dans l’injection de valeur, la mise en place de configuration de propriété, les interfaces, les chaînes finales, etc.

Si vous devez utiliser l'excuse de la nécessité de localiser un composant plus facile à dicter contre les constantes d'interface, cela signifie que vous avez la mauvaise habitude de ne pas pratiquer la normalisation de modèle de données.

Peut-être souhaitez-vous compiler le modèle de données dans une version de vcs. Que vous puissiez extraire une version distinctement identifiable d'un modèle de données.

Les valeurs définies dans les interfaces sont complètement assurées d'être non mutables. Et partageable. Pourquoi charger un ensemble de chaînes finales dans votre classe à partir d’une autre classe alors que vous n’avez besoin que de cet ensemble de constantes ??

Alors pourquoi ne pas publier un contrat de modèle de données? Je veux dire, si vous pouvez le gérer et le normaliser de manière cohérente, pourquoi pas? ...

public interface CustomerService {
  public interface Label{
    char AssignmentCharacter = ':';
    public interface Address{
      String Street = "Street";
      String Unit= "Unit/Suite";
      String Municipal = "City";
      String County = "County";
      String Provincial = "State";
      String PostalCode = "Zip"
    }

    public interface Person {
      public interface NameParts{
        String Given = "First/Given name"
        String Auxiliary = "Middle initial"
        String Family = "Last name"
      }
    }
  }
}

Maintenant, je peux référencer les étiquettes sous contrat de mes applications d'une manière telle que

CustomerService.Label.Address.Street
CustomerService.Label.Person.NameParts.Family

Cela confond le contenu du fichier jar? En tant que Java programmeur, je ne me soucie pas de la structure du pot.

Cela présente une complexité pour l’échange d’exécution à motivation osgi? Osgi est un moyen extrêmement efficace de permettre aux programmeurs de conserver leurs mauvaises habitudes. Il y a de meilleures alternatives que osgi.

Ou pourquoi pas ça? Il n’ya pas de fuite de constantes privées dans le contrat publié. Toutes les constantes privées doivent être regroupées dans une interface privée appelée "Constantes", car je ne souhaite pas rechercher de constantes et je suis trop paresseux pour taper à plusieurs reprises "chaîne privée finale".

public class PurchaseRequest {
  private interface Constants{
    String INTERESTINGName = "Interesting Name";
    String OFFICIALLanguage = "Official Language"
    int MAXNames = 9;
  }
}

Peut-être même ceci:

public interface PurchaseOrderConstants {
  public interface Properties{
    default String InterestingName(){
       return something();
    }
    String OFFICIALLanguage = "Official Language"
    int MAXNames = 9;
  }
}

Le seul problème avec les constantes d'interface qui mérite d'être considéré est celui de la mise en œuvre de l'interface.

Ce n'est pas "l'intention originale" des interfaces? Comme si je me souciais de "l'intention initiale" des pères fondateurs dans la rédaction de la constitution américaine, plutôt que de la façon dont la Cour suprême interpréterait les lettres de la constitution américaine ???

Après tout, je vis au pays du libre, du sauvage et du foyer des braves. Soyez courageux, soyez libre, soyez sauvage - utilisez l'interface. Si mes collègues programmeurs refusent d'utiliser des méthodes de programmation efficaces et paresseuses, la règle d'or m'oblige-t-il à réduire l'efficacité de ma programmation pour qu'elle s'aligne sur la leur? Peut-être que je devrais, mais ce n'est pas une situation idéale.

0
Blessed Geek

Pour aller plus loin, vous pouvez placer des constantes utilisées globalement dans une interface afin qu'elles puissent être utilisées à l'échelle du système. Par exemple.

public interface MyGlobalConstants {
    public static final int TIMEOUT_IN_SECS = 25;
}

Mais ne l'implémentez pas alors. Il suffit de s'y référer directement dans le code via le nom de classe complet.

0
Andrew Harmel-Law

J'utilise static final pour déclarer des constantes et utiliser la notation de nommage ALL_CAPS. J'ai vu pas mal de cas réels où toutes les constantes sont regroupées dans une interface. Quelques articles ont qualifié à juste titre de mauvaise pratique, principalement parce que ce n'est pas à quoi sert une interface. Une interface doit imposer un contrat et ne doit pas être un lieu où insérer des constantes non liées. Le regrouper dans une classe qui ne peut pas être instanciée (par un constructeur privé) est également acceptable si la sémantique des constantes n'appartient pas à une classe spécifique ( es). Je mets toujours une constante dans la classe à laquelle elle est le plus liée, car cela a du sens et est facilement maintenable.

Les énumérations sont un bon choix pour représenter une plage de valeurs, mais si vous stockez des constantes autonomes en mettant l'accent sur la valeur absolue (par exemple, TIMEOUT = 100 ms), vous pouvez simplement opter pour l'approche static final.

0
bincob

Pour les constantes, Enum est un meilleur choix à mon humble avis. Voici un exemple

classe publique myClass {

public enum myEnum {
    Option1("String1", 2), 
    Option2("String2", 2) 
    ;
    String str;
            int i;

            myEnum(String str1, int i1) { this.str = str1 ; this.i1 = i }


}
0
mmansoor

Je suis d’accord avec ce que la plupart des gens disent, il est préférable d’utiliser des énumérations pour traiter d’un ensemble de constantes. Cependant, si vous programmez sous Android, il existe une meilleure solution: IntDef Annotation .

@Retention(SOURCE)
@IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST,NAVIGATION_MODE_TABS})
public @interface NavigationMode {}
public static final int NAVIGATION_MODE_STANDARD = 0;
public static final int NAVIGATION_MODE_LIST = 1;
public static final int NAVIGATION_MODE_TABS = 2;
...
public abstract void setNavigationMode(@NavigationMode int mode);
@NavigationMode
public abstract int getNavigationMode();

L’annotation IntDef est supérieure aux énumérations d’une manière simple, elle prend beaucoup moins de place car c’est simplement un marqueur de compilation. Ce n'est pas une classe, il n'a pas non plus la propriété de conversion de chaîne automatique.

0
Quinn Turner

Je le fais en créant une classe 'Global' avec les valeurs constantes et en effectuant une importation statique dans les classes nécessitant un accès à la constante.

0
Javamann