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

StackOverflow https://stackoverflow.com/questions/66066

  •  09-06-2019
  •  | 
  •  

Question

J'ai vu des exemples comme celui-ci:

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

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

Était-ce utile?

La solution

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

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

TYPE est le type, NAME le nom en majuscules avec des traits de soulignement pour les espaces et VALUE 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 mutables peuvent toujours être modifiées. cependant, la variable ne peut jamais pointer sur un objet différent.

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).

Autres conseils

Je vous déconseille vivement de choisir 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 de cela:

  • 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 peut-être 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 valides 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 développeurs y aient accès. Cependant, évitez de créer une interface contenant uniquement des constantes: cela peut devenir aussi grave qu'une classe créée uniquement pour contenir des constantes.

C’est une mauvaise pratique d’utiliser des interfaces uniquement pour conserver des constantes (nommé modèle d’interface constant par Josh Bloch). Voici ce que Josh conseille:

  

Si les constantes sont fortement liées à   une classe ou une interface existante, vous   devrait les ajouter à la classe ou   interface. Par exemple, tous les   classes primitives numériques encadrées,   tels que Integer et Double, exportez   Constantes MIN_VALUE et MAX_VALUE. Si   les constantes sont mieux vues comme   membres d'un type énuméré, vous   devrait les exporter avec un enum   type. Sinon, vous devriez exporter le   des constantes avec un non instable   classe utilitaire.

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;
}

À propos de la convention de dénomination:

  

Par convention, ces champs ont des noms   composé de lettres majuscules, avec   mots séparés par des traits de soulignement. Il est   critique que ces champs contiennent   soit des valeurs primitives ou des références   aux objets immuables.

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 enums en 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 la suivante:

  

Alors, quand devriez-vous utiliser des enums?

Avec une réponse de:

  

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

Évitez 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.

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 semble plus & «Objet oriently &»; quant à moi.

La création de constantes finales statiques dans une classe séparée peut vous causer des problèmes. Le compilateur Java l’optimisera réellement et placera 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 être configurables par l'utilisateur ou par l'administrateur, ce sera beaucoup plus facile à faire.

La première erreur que vous pouvez faire 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 dont & "possède" & "; leur. 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 .properties Java lorsque " constantes " peut être défini au moment de l'exécution, mais pas facilement modifiable par l'utilisateur. Vous pouvez les regrouper dans vos fichiers .jars et les référencer avec le class resourceLoader.

C'est la bonne façon de faire.

En général, les constantes ne sont pas conservées dans des "ient constantes " classes parce qu'ils ne sont pas découvrables. Si la constante est pertinente pour la classe actuelle, le fait de les conserver aide le développeur suivant.

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

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.

L’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.

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

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 créer un cours séparé pour regrouper toutes vos constantes, mais je n'ai jamais vu de raison de ne pas le faire, si ce n'est la préférence et le style personnels.

Si vos constantes peuvent être bien modélisées comme une énumération, considérez le fichier enum disponible à partir de la version 1.5.

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

D'après les commentaires ci-dessus, je pense que c'est une bonne approche pour changer la classe constante globale ancienne (ayant des variables finales statiques publiques) en son équivalent enum, comme suit:

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

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.

Il existe un certain nombre d'opinions pour répondre à cette question. Pour commencer, les constantes en 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 cela n’aurait pas l’air drôle?

String myConstant = IMyInterface.CONSTANTX;

Au lieu de cela, je choisirais différentes méthodes, en fonction de quelques compromis, et cela dépend donc de vos besoins:

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
  

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écialement pour déclarer des constantes est la pire des choses: il élimine la raison pour laquelle les interfaces ont été conçues: définition du ou des contrat (s).

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

Pour simplifier, nous avons globalement 4 approches valides .

Avec static final String/Integer champ:

  • 1) en utilisant une classe qui déclare des constantes à l'intérieur mais pas seulement.
  • 1 variante) création d'une classe dédiée à la déclaration de constantes uniquement.

Avec Java 5 enum:

  • 2) déclarer l’énumération dans une classe d’objets apparentés (donc une classe imbriquée).
  • variante 2) 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, la méthode enum est probablement plus fine que la static final String et personnellement, je pense que cette méthode ne devrait être utilisée 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 Integer / enum contre String

L'utilisation de Enums est vraiment un moyen d'être fortement envisagé.
Les énumérations ont un grand avantage sur les champs Integer ou java.lang.Math constants.
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 Math / E.

Par exemple, ci-dessous deux constantes définies dans une classe en tant que PI champs:

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");

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

Avec enum, les contrôles ne sont pas obligatoires car le client ne peut transmettre qu'une valeur enum dans un paramètre enum.

Par exemple, voici deux valeurs définies dans une classe enum (donc prêtes à l'emploi):

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 manière:

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

Où devons-nous déclarer les constantes?

Si votre application contient une seule classe existante possédant une cohésion fonctionnelle spécifique et forte avec les valeurs constantes, les valeurs 1) et 2) apparaissent plus intuitives.
Généralement, il est plus facile d’utiliser les 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 retrouvées à l’intérieur.

Par exemple, dans la bibliothèque JDK, les valeurs constantes exponentielle et pi sont déclarées dans une classe qui ne déclare pas uniquement les déclarations constantes (java.util.concurrent.TimeUnit).

public enum TimeUnit {
    NANOSECONDS {
      .....
    },
    MICROSECONDS {
      .....
    },
    MILLISECONDS {
      .....
    },
    SECONDS {
      .....
    },
      .....
}      

Les clients utilisant des fonctions mathématiques font souvent appel à la classe java.util.concurrent. Ainsi, ils peuvent trouver les constantes assez facilement et peuvent également se rappeler où BlockingQueue et ArrayBlockingQueue<E> sont définis de manière très naturelle.voie orale.

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, tandis que nous avons également 3 ou 4 autres classes qui les manipulent autant et qu'aucune de ces classes ne semble plus naturelle que d’autres. valeurs d'accueil constantes.
Ici, définir une classe personnalisée ne contenant que des valeurs constantes est logique.
Par exemple, dans la bibliothèque JDK, l'énumération CompletableFuture n'est pas déclarée dans une classe spécifique car il n'y a pas vraiment une et une seule classe spécifique JDK qui apparaît comme la plus intuitive pour la contenir:

<*>

De nombreuses classes déclarées dans ExecutorService les utilisent: <=>, <=>, <=>, <=>, ... et aucun d’entre eux ne semble plus approprié que l’enum..

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.-à-d. Amélioré sécurité de type ):

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

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 lié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 pour l’utiliser, faites de la méthode constante une méthode de classe.

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

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.

Je n'appellerais pas la classe la même chose (à l'exception du boîtier) 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 grouperais en classes de constantes logiques (UserSettings, AppSettings, etc.)

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. Ex.

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.

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 }


}

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.

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

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 constante 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 <=>.

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

@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.

It is BAD habit and terribly ANNOYING practice to quote Joshua Bloch without understanding the basic ground-zero fundamentalism.

I have not read anything Joshua Bloch, so either

  • he is a terrible programmer
  • or the people so far whom I find quoting him (Joshua is the name of a boy I presume) are simply using his material as religious scripts to justify their software religious indulgences.

As in Bible fundamentalism all the biblical laws can be summed up by

  • Love the Fundamental Identity with all your heart and all your mind
  • Love your neighbour as yourself

and so similarly software engineering fundamentalism can be summed up by

  • devote yourself to the ground-zero fundamentals with all your programming might and mind
  • and devote towards the excellence of your fellow-programmers as you would for yourself.

Also, among biblical fundamentalist circles a strong and reasonable corollary is drawn

  • First love yourself. Because if you don't love yourself much, then the concept "love your neighbour as yourself" doesn't carry much weight, since "how much you love yourself" is the datum line above which you would love others.

Similarly, if you do not respect yourself as a programmer and just accept the pronouncements and prophecies of some programming guru-nath WITHOUT questioning the fundamentals, your quotations and reliance on Joshua Bloch (and the like) is meaningless. And therefore, you would actually have no respect for your fellow-programmers.

The fundamental laws of software programming

  • laziness is the virtue of a good programmer
  • you are to make your programming life as easy, as lazy and therefore as effective as possible
  • you are to make the consequences and entrails of your programming as easy, as lazy and therefore as effective as possible for your neigbour-programmers who work with you and pick up your programming entrails.

Interface-pattern constants is a bad habit ???

Under what laws of fundamentally effective and responsible programming does this religious edict fall into ?

Just read the wikipedia article on interface-pattern constants (https://en.wikipedia.org/wiki/Constant_interface), and the silly excuses it states against interface-pattern constants.

  • Whatif-No IDE? Who on earth as a software programmer would not use an IDE? Most of us are programmers who prefer not to have to prove having macho aescetic survivalisticism thro avoiding the use of an IDE.

    • Also - wait a second proponents of micro-functional programming as a means of not needing an IDE. Wait till you read my explanation on data-model normalization.
  • Pollutes the namespace with variables not used within the current scope? It could be proponents of this opinion

    • are not aware of, and the need for, data-model normalization
  • Using interfaces for enforcing constants is an abuse of interfaces. Proponents of such have a bad habit of

    • not seeing that "constants" must be treated as contract. And interfaces are used for enforcing or projecting compliance to a contract.
  • It is difficult if not impossible to convert interfaces into implemented classes in the future. Hah .... hmmm ... ???

    • Why would you want to engage in such pattern of programming as your persistent livelihood? IOW, why devote yourself to such an AMBIVALENT and bad programming habit ?

Whatever the excuses, there is NO VALID EXCUSE when it comes to FUNDAMENTALLY EFFECTIVE software engineering to delegitimize or generally discourage the use of interface constants.

It doesn't matter what the original intents and mental states of the founding fathers who crafted the United States Constitution were. We could debate the original intents of the founding fathers but all I care is the written statements of the US Constitution. And it is the responsibility of every US citizen to exploit the written literary-fundamentalism, not the unwritten founding-intents, of the US Constitution.

Similarly, I do not care what the "original" intents of the founders of the Java platform and programming language had for the interface. What I care are the effective features the Java specification provides, and I intend to exploit those features to the fullest to help me fulfill the fundamental laws of responsible software programming. I don't care if I am perceived to "violate the intention for interfaces". I don't care what Gosling or someone Bloch says about the "proper way to use Java", unless what they say does not violate my need to EFFECTIVE fulfilling fundamentals.

The Fundamental is Data-Model Normalization

It doesn't matter how your data-model is hosted or transmitted. Whether you use interfaces or enums or whatevernots, relational or no-SQL, if you don't understand the need and process of data-model normalization.

We must first define and normalize the data-model of a set of processes. And when we have a coherent data-model, ONLY then can we use the process flow of its components to define the functional behaviour and process blocks a field or realm of applications. And only then can we define the API of each functional process.

Even the facets of data normalization as proposed by EF Codd is now severely challenged and severely-challenged. e.g. his statement on 1NF has been criticized as ambiguous, misaligned and over-simplified, as is the rest of his statements especially in the advent of modern data services, repo-technology and transmission. IMO, the EF Codd statements should be completely ditched and new set of more mathematically plausible statements be designed.

A glaring flaw of EF Codd's and the cause of its misalignment to effective human comprehension is his belief that humanly perceivable multi-dimensional, mutable-dimension data can be efficiently perceived thro a set of piecemeal 2-dimensional mappings.

The Fundamentals of Data Normalization

What EF Codd failed to express.

Within each coherent data-model, these are the sequential graduated order of data-model coherence to achieve.

  1. The Unity and Identity of data instances.
    • design the granularity of each data component, whereby their granularity is at a level where each instance of a component can be uniquely identified and retrieved.
    • absence of instance aliasing. i.e., no means exist whereby an identification produces more than one instance of a component.
  2. Absence of instance crosstalk. There does not exist the necessity to use one or more other instances of a component to contribute to identifying an instance of a component.
  3. The unity and identity of data components/dimensions.
    • Presence of component de-aliasing. There must exist one definition whereby a component/dimension can be uniquely identified. Which is the primary definition of a component;
    • where the primary definition will not result in exposing sub-dimensions or member-components that are not part of an intended component;
  4. Unique means of component dealiasing. There must exist one, and only one, such component de-aliasing definition for a component.
  5. There exists one, and only one, definition interface or contract to identify a parent component in a hierarchical relationship of components.
  6. Absence of component crosstalk. There does not exist the necessity to use a member of another component to contribute to the definitive identification of a component.
    • In such a parent-child relationship, the identifying definition of a parent must not depend on part of the set of member components of a child. A member component of a parent's identity must be the complete child identity without resorting to referencing any or all of the children of a child.
  7. Preempt bi-modal or multi-modal appearances of a data-model.
    • When there exists two candidate definitions of a component, it is an obvious sign that there exists two different data-models being mixed up as one. That means there is incoherence at the data-model level, or the field level.
    • A field of applications must use one and only one data-model, coherently.
  8. Detect and identify component mutation. Unless you have performed statistical component analysis of huge data, you probably do not see, or see the need to treat, component mutation.
    • A data-model may have its some of its components mutate cyclically or gradually.
    • The mode may be member-rotation or transposition-rotation.
    • Member-rotation mutation could be distinct swapping of child components between components. Or where completely new components would have to be defined.
    • Transpositional mutation would manifest as a dimensional-member mutating into an attribute, vice versa.
    • Each mutation cycle must be identified as a distinct data-modal.
  9. Versionize each mutation. Such that you can pull out a previous version of the data model, when perhaps the need arise to treat an 8 year old mutation of the data model.

In a field or grid of inter-servicing component-applications, there must be one and only one coherent data-model or exists a means for a data-model/version to identify itself.

Are we still asking if we could use Interface Constants? Really ?

There are data-normalization issues at stake more consequential than this mundane question. IF you don't solve those issues, the confusion that you think interface constants cause is comparatively nothing. Zilch.

From the data-model normalization then you determine the components as variables, as properties, as contract interface constants.

Then you determine which goes into value injection, property configuration placeholding, interfaces, final strings, etc.

If you have to use the excuse of needing to locate a component easier to dictate against interface constants, it means you are in the bad habit of not practicing data-model normalization.

Perhaps you wish to compile the data-model into a vcs release. That you can pull out a distinctly identifiable version of a data-model.

Values defined in interfaces are completely assured to be non-mutable. And shareable. Why load a set of final strings into your class from another class when all you need is that set of constants ??

So why not this to publish a data-model contract? I mean if you can manage and normalize it coherently, why not? ...

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"
      }
    }
  }
}

Now I can reference my apps' contracted labels in a way such as

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

This confuses the contents of the jar file? As a Java programmer I don't care about the structure of the jar.

This presents complexity to osgi-motivated runtime swapping ? Osgi is an extremely efficient means to allow programmers to continue in their bad habits. There are better alternatives than osgi.

Or why not this? There is no leakage of of the private Constants into published contract. All private constants should be grouped into a private interface named "Constants", because I don't want to have to search for constants and I am too lazy to repeatedly type "private final String".

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

Perhaps even this:

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

The only issue with interface constants worth considering is when the interface is implemented.

This is not the "original intention" of interfaces? Like I would care about the "original intention" of the founding fathers in crafting the US Constitution, rather than how the Supreme Court would interpret the written letters of the US Constitution ???

After all, I live in the land of the free, the wild and home of the brave. Be brave, be free, be wild - use the interface. If my fellow-programmers refuse to use efficient and lazy means of programming, am I obliged by the golden rule to lessen my programming efficiency to align with theirs? Perhaps I should, but that is not an ideal situation.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top