it-swarm.it

Qual è il modo migliore per implementare le costanti in Java?

Ho visto esempi come questo:

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

e supponevo che potessi avere una classe Constants per avvolgere le costanti, dichiarandole come finali statiche. Non conosco praticamente Java e mi chiedo se questo è il modo migliore per creare costanti.

373
mk.

Questo è perfettamente accettabile, probabilmente anche lo standard.

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

dove TYPE è il tipo, NAME è il nome in maiuscolo con caratteri di sottolineatura per gli spazi e VALUE è il valore costante;

Consiglio vivamente di NON mettere le costanti nelle proprie classi o interfacce.

Come nota a margine: le variabili dichiarate definitive e modificabili possono ancora essere modificate; tuttavia, la variabile non può mai puntare su un oggetto diverso.

Per esempio:

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

public static void main(String[] args){

    Origin.x = 3;

}

Questo è legale e Origin sarebbe quindi un punto in (3, 0).

403
jjnguy

Consiglio vivamente di non avere una singola classe di costanti. Può sembrare una buona idea al momento, ma quando gli sviluppatori rifiutano di documentare le costanti e la classe cresce fino a comprendere fino a 500 costanti che non sono affatto collegate tra loro (essendo legate a aspetti completamente diversi dell'applicazione), questo generalmente si trasforma nel file delle costanti completamente illeggibile. Anziché:

  • Se hai accesso a Java 5+, usa le enumerazioni per definire le costanti specifiche per un'area applicativa. Tutte le parti dell'area dell'applicazione devono riferirsi a enumerazioni, non a valori costanti, per queste costanti. Puoi dichiarare un enum simile a come dichiari una classe. Le enumerazioni sono forse la funzione più (e, probabilmente, solo) utile di Java 5+.
  • Se si dispone di costanti valide solo per una particolare classe o una delle sue sottoclassi, dichiararle come protette o pubbliche e posizionarle nella classe superiore nella gerarchia. In questo modo, le sottoclassi possono accedere a questi valori costanti (e se altre classi li accedono tramite public, le costanti non sono valide solo per una particolare classe ... il che significa che le classi esterne che usano questa costante potrebbero essere troppo strettamente accoppiate classe contenente la costante)
  • Se si dispone di un'interfaccia con il comportamento definito, ma i valori restituiti o i valori degli argomenti dovrebbero essere particolari, è perfettamente accettabile definire le costanti su tale interfaccia in modo che altri implementatori possano accedervi. Tuttavia, evita di creare un'interfaccia solo per contenere le costanti: può diventare altrettanto brutto di una classe creata solo per contenere le costanti.
235
MetroidFan2002

È un BAD PRACTICE usare le interfacce solo per contenere le costanti (chiamate modello di interfaccia costante di Josh Bloch). Ecco cosa consiglia Josh:

Se le costanti sono fortemente legate a una classe o un'interfaccia esistente, è necessario aggiungerle alla classe o all'interfaccia. Ad esempio, tutte le classi primitive numeriche in box, come Integer e Double, esportano le costanti MIN_VALUE e MAX_VALUE. Se le costanti sono viste al meglio come membri di un tipo enumerato, dovresti esportarle con un enum type. Altrimenti, dovresti esportare le costanti con una classe di utilità non affidabile.

Esempio:

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

Informazioni sulla convenzione di denominazione:

Per convenzione, tali campi hanno nomi composti da lettere maiuscole, con parole separate da caratteri di sottolineatura. È fondamentale che questi campi contengano valori primitivi o riferimenti a oggetti immutabili.

120
Marcio Aguiar

In Java efficace (2a edizione), si consiglia di utilizzare le enumerazioni invece di quelle statiche per le costanti.

C'è una buona recensione sull'enumerazione in Java qui: http://Java.Sun.com/j2se/1.5.0/docs/guide/language/enums.html

Si noti che alla fine di tale articolo la domanda posta è:

Quindi quando dovresti usare le enumerazioni?

Con una risposta di:

Ogni volta che hai bisogno di un set fisso di costanti

36
shelfoo

Basta evitare di usare un'interfaccia:

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

public class NeddsConstant implements MyConstants {

}

È allettante, ma viola l'incapsulamento e offusca la distinzione delle definizioni di classe.

21
stimpy

Io uso il seguente approccio:

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() {}
}

Ad esempio, uso Constants.DB.Connection.URL per diventare costante. Sembra più "oggetto orientato" come per me.

19
albus.ua

La creazione di costanti finali statiche in una classe separata può metterti nei guai. Il compilatore Java in realtà lo ottimizzerà e inserirà il valore effettivo della costante in qualsiasi classe che lo faccia riferimento.

Se in seguito cambi la classe 'Costanti' e non esegui una rigida ricompilazione su altre classi che fanno riferimento a quella classe, finirai con una combinazione di vecchi e nuovi valori usati.

Invece di pensare a questi come costanti, pensali come parametri di configurazione e crea una classe per gestirli. I valori devono essere non definitivi e anche prendere in considerazione l'utilizzo di getter. In futuro, quando si determina che alcuni di questi parametri dovrebbero essere configurabili dall'utente o dall'amministratore, sarà molto più facile da fare.

17
Kevin Day

L'errore numero uno che si può fare è la creazione di una classe accessibile globalmente chiamata con un nome generico, come Costanti. Questo viene semplicemente cosparso di spazzatura e si perde ogni capacità di capire quale parte del sistema utilizza queste costanti.

Invece, le costanti dovrebbero entrare nella classe che le "possiede". Hai una costante chiamata TIMEOUT? Probabilmente dovrebbe andare nella tua classe Communications () o Connection (). MAX_BAD_LOGINS_PER_HOUR? Entra in User (). E così via e così via.

L'altro possibile utilizzo sono i file Java .properties quando "costanti" possono essere definiti in fase di esecuzione, ma non facilmente modificabili dall'utente. Puoi comprimerli nel tuo .jars e farli riferimento con il resourceLoader di classe.

13
Yann Ramin

Questa è la strada giusta da percorrere.

Generalmente le costanti sono non mantenute in classi separate "Costanti" perché non sono rilevabili. Se la costante è rilevante per la classe corrente, tenerli lì aiuta il prossimo sviluppatore.

6
Jason Cohen

Sono d'accordo che l'utilizzo di un'interfaccia non è la strada da percorrere. Evitare questo modello ha anche il suo oggetto (# 18) in Effective Java di Bloch.

Un argomento di Bloch contro il modello di interfaccia costante è che l'uso delle costanti è un dettaglio di implementazione, ma l'implementazione di un'interfaccia per utilizzarle espone i dettagli di implementazione nell'API esportata.

Il pattern public|private static final TYPE NAME = VALUE; è un buon modo per dichiarare una costante. Personalmente, penso che sia meglio evitare di creare una classe separata per ospitare tutte le tue costanti, ma non ho mai visto una ragione per non farlo, a parte le preferenze personali e lo stile.

Se le tue costanti possono essere ben modellate come un'enumerazione, considera la enum struttura disponibile in 1.5 o successive.

Se stai utilizzando una versione precedente alla 1.5, puoi comunque estrarre le enumerazioni tipiche utilizzando le normali classi Java. (Vedi questo sito per ulteriori informazioni su questo).

5
Rob Dickerson

Che dire di un'enumerazione?

5
Sébastien D.

Preferisco usare i getter piuttosto che le costanti. Questi getter potrebbero restituire valori costanti, ad es. public int getMaxConnections() {return 10;}, ma tutto ciò che ha bisogno della costante passerà attraverso un getter.

Un vantaggio è che se il tuo programma supera la costante - trovi che deve essere configurabile - puoi semplicemente cambiare il modo in cui il getter restituisce la costante.

L'altro vantaggio è che per modificare la costante non è necessario ricompilare tutto ciò che lo utilizza. Quando si fa riferimento a un campo finale statico, il valore di tale costante viene compilato in qualsiasi codice byte che lo faccia riferimento.

5
big_peanut_horse

Sulla base dei commenti sopra, penso che questo sia un buon approccio per cambiare la classe costante globale vecchio stile (con variabili finali statiche pubbliche) al suo equivalente enum-like in un modo come questo:

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

}

Quindi posso riferirmi a mi piace:

Constants.StringConstant.DB_Host
4
Lorand Bendig

Una buona progettazione orientata agli oggetti non dovrebbe richiedere molte costanti disponibili pubblicamente. La maggior parte delle costanti dovrebbe essere incapsulata nella classe che ha bisogno di loro per svolgere il proprio lavoro.

3
Bradley Harris

C'è una certa dose di opinione per rispondere a questo. Per cominciare, le costanti in Java sono generalmente dichiarate pubbliche, statiche e definitive. Di seguito sono i motivi:

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

Non userei mai un'interfaccia per un accessorio/oggetto CONSTANTS semplicemente perché ci si aspetta che le interfacce siano implementate. Non sarebbe divertente?

String myConstant = IMyInterface.CONSTANTX;

Invece, sceglierei tra alcuni modi diversi, basati su alcuni piccoli compromessi, e quindi dipende da ciò di cui hai bisogno:

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

Qual è il modo migliore per implementare le costanti in Java?

Un approccio che dovremmo davvero evitare : usare le interfacce per definire le costanti.

La creazione di un'interfaccia specifica per dichiarare le costanti è davvero la cosa peggiore: sconfigge il motivo per cui sono state progettate interfacce: definizione del/i contratto/i metodo/i.

Anche se esiste già un'interfaccia per rispondere a un'esigenza specifica, dichiarare che le costanti in esse contenute non hanno realmente senso poiché le costanti non dovrebbero fare parte dell'API e il contratto fornito alle classi client.


Per semplificare, abbiamo generalmente 4 approcci validi .

Con il campo static final String/Integer:

  • 1) usando una classe che dichiara le costanti dentro ma non solo.
  • 1 variante) creando una classe dedicata solo a dichiarare le costanti.

Con Java 5 enum:

  • 2) dichiarare l'enum in una classe di scopo correlata (così come una classe annidata).
  • 2 variante) creando l'enum come classe autonoma (così definita nel proprio file di classe).

TLDR: qual è il modo migliore e dove individuare le costanti?

Nella maggior parte dei casi, il modo enum è probabilmente migliore del modo static final String/Integere personalmente penso che il modo static final String/Integer debba essere usato solo se abbiamo buone ragioni per non usare enum.
E su dove dovremmo dichiarare i valori costanti, l'idea è di cercare se esiste una singola classe esistente che possiede una coesione funzionale specifica e forte con valori costanti. Se troviamo una classe del genere, dovremmo usarla come titolare delle costanti . Altrimenti, la costante dovrebbe essere associata a nessuna classe particolare.


static final String/static final Integer RISPETTO A enum

L'uso di enumerazioni è davvero un modo per considerare fortemente.
Le enumerazioni hanno un grande vantaggio rispetto al campo costante String o Integer.
Impostano un vincolo di compilazione più forte. Se si definisce un metodo che accetta l'enum come parametro, è possibile solo passare un valore enum definito nella classe enum (o null).
Con String e Integer puoi sostituirli con qualsiasi valore di tipo compatibile e la compilazione andrà bene anche se il valore non è una costante definita nei campi static final String/static final Integer.

Ad esempio, sotto due costanti definite in una classe come campi static final String:

public class MyClass{

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

Ecco un metodo che si aspetta di avere una di queste costanti come parametro:

public void process(String constantExpected){
    ...    
}

Puoi invocarlo in questo modo:

process(MyClass.ONE_CONSTANT);

o

process(MyClass.ANOTHER_CONSTANT);

Ma nessun vincolo di compilazione ti impedisce di invocarlo in questo modo:

process("a not defined constant value");

Si avrebbe l'errore solo in fase di esecuzione e solo se si esegue in un momento un controllo sul valore trasmesso.

Con enum, i controlli non sono richiesti in quanto il client può solo passare un valore enum in un parametro enum.

Ad esempio, qui due valori definiti in una classe enum (così costante out of the box):

public enum MyEnum {

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

    private String value;

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

Ecco un metodo che si aspetta di avere uno di questi valori enum come parametro:

public void process(MyEnum myEnum){
    ...    
}

Puoi invocarlo in questo modo:

process(MyEnum.ONE_CONSTANT);

o

process(MyEnum.ANOTHER_CONSTANT);

Ma la compilazione non ti consentirà mai di invocarla in questo modo:

process("a not defined constant value");

Dove dovremmo dichiarare le costanti?

Se la tua applicazione contiene una singola classe esistente che possiede una coesione funzionale specifica e forte con i valori costanti, 1) e 2) appaiono più intuitivi.
Generalmente, facilita l'uso delle costanti se queste sono dichiarate nella classe principale che le manipola o che ha un nome molto naturale per indovinare che lo troveremo all'interno.

Ad esempio nella libreria JDK, i valori esponenziali e pi cost sono dichiarati in una classe che dichiara non solo dichiarazioni costanti (Java.lang.Math).

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

I client che utilizzano le funzioni matematiche fanno spesso affidamento sulla classe Math. Quindi, possono trovare le costanti abbastanza facilmente e possono anche ricordare dove E e PI sono definiti in modo molto naturale.

Se la tua applicazione non contiene una classe esistente che ha una coesione funzionale molto specifica e forte con i valori di costante, la variante 1 e la 2 variante) appaiono più intuitive.
Generalmente, non facilita l'uso delle costanti se queste sono dichiarate in una classe che le manipola mentre abbiamo anche 3 o 4 altre classi che le manipolano tanto e nessuna di queste classi sembra essere più naturale di altri per ospitare valori costanti.
Qui, la definizione di una classe personalizzata per contenere solo valori costanti ha senso.
Ad esempio nella libreria JDK, l'enum Java.util.concurrent.TimeUnit non è dichiarato in una classe specifica in quanto non esiste una sola e specifica classe JDK che appare come la più intuitiva per mantenerla:

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

Molte classi dichiarate in Java.util.concurrent li usano: BlockingQueue, ArrayBlockingQueue<E>, CompletableFuture, ExecutorService, ... e in realtà nessuno di loro sembra più appropriato per contenere l'enum.

2
davidxxx

FWIW, un valore di timeout in secondi dovrebbe probabilmente essere un'impostazione di configurazione (letto da un file delle proprietà o tramite l'iniezione come in primavera) e non una costante.

1
Tim Howland

Qual è la differenza

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

e usando MyGlobalConstants.TIMEOUT_IN_SECS ovunque ci sia bisogno di questa costante. Penso che entrambi siano uguali.

1
chandrayya

Una singola classe di costanti generica è una cattiva idea. Le costanti dovrebbero essere raggruppate insieme alla classe a cui sono più strettamente correlate.

Piuttosto che usare variabili di qualsiasi tipo (specialmente enumerazioni), ti suggerirei di usare metodi. Creare un metodo con lo stesso nome della variabile e restituire il valore assegnato alla variabile. Ora elimina la variabile e sostituisci tutti i riferimenti ad essa con le chiamate al metodo appena creato. Se ritieni che la costante sia abbastanza generica da non dover creare un'istanza della classe solo per usarla, allora rendi il metodo costante un metodo di classe.

1
ab

Una costante, di qualsiasi tipo, può essere dichiarata creando una proprietà immutabile all'interno di una classe (che è una variabile membro con il modificatore final). In genere vengono forniti anche i modificatori static e public.

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

Esistono numerose applicazioni in cui il valore di una costante indica una selezione da una n-Tupla (ad es. enumerazione ) di scelte. Nel nostro esempio, possiamo scegliere di definire un tipo enumerato che limiterà i possibili valori assegnati (cioè migliorato type-safety ):

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

Non definirei la classe uguale (a parte il caso) come costante ... Avrei almeno una classe di "Impostazioni", o "Valori", o "Costanti", in cui tutte le costanti dovrebbero vivere. Se ne ho un gran numero, li raggrupperei in classi logiche costanti (UserSettings, AppSettings, ecc.)

0
Joel Martinez

static final è la mia preferenza, userei solo enum se l'oggetto fosse effettivamente enumerabile.

0
wulfgarpro

È abitudine BAD e pratica terribilmente ANIMALE per citare Joshua Bloch senza comprendere il fondamentale fondamentalismo ground-zero.

Non ho letto nulla nemmeno su Joshua Bloch

  • lui è un programmatore terribile
  • o le persone fino ad ora che trovo che lo citano (Joshua è il nome di un ragazzo che presumo) stanno semplicemente usando il suo materiale come script religioso per giustificare le loro indulgenze religiose sul software.

Come nel fondamentalismo biblico, tutte le leggi bibliche possono essere riassunte da

  • Ama l'identità fondamentale con tutto il tuo cuore e tutta la tua mente
  • Ama il tuo prossimo come te stesso

e in modo simile il fondamentalismo dell'ingegneria del software può essere riassunto da

  • dedica te stesso ai fondamenti ground zero con tutta la tua potenza e la tua mente di programmazione
  • e dedicare all'eccellenza dei tuoi colleghi programmatori come faresti per te stesso.

Inoltre, tra i circoli biblici fondamentalisti viene disegnato un corollario forte e ragionevole

  • Prima Ama te stesso. Perché se non ti ami molto, allora il concetto "ama il prossimo come te stesso" non ha molto peso, poiché "quanto ti ami" è la linea di riferimento sopra la quale amerai gli altri.

Allo stesso modo, se non ci si rispetti come programmatore e solo accettare le dichiarazioni e le profezie di alcuni di programmazione guru-nath senza mettere in discussione i fondamenti, le vostre citazioni e dipendenza da Joshua Bloch (e simili) non ha senso. E quindi, non avresti alcun rispetto per i tuoi colleghi programmatori.

Le leggi fondamentali della programmazione del software

  • la pigrizia è la virtù di un buon programmatore
  • devi rendere la tua programmazione semplice, pigra e quindi efficace
  • devi rendere le conseguenze e le viscere della tua programmazione semplici, pigre e quindi efficaci per i tuoi programmatori vicini che lavorano con te e raccolgono le tue viscere programmatiche.

Le costanti dell'interfaccia modello sono una cattiva abitudine ???

Sotto quali leggi di programmazione fondamentalmente efficace e responsabile si inserisce questo editto religioso?

Basta leggere l'articolo di Wikipedia su costanti interfaccia-modello ( https://en.wikipedia.org/wiki/Constant_interface ), e le scuse sciocche si afferma contro costanti interfaccia-modello.

  • Whatif-No IDE? Chi mai come programmatore di software non userebbe un IDE? Molti di noi sono programmatori che preferiscono non dover dimostrare di avere un survivalismo aescetico da un punto di vista evitatore dell'uso di un IDE.

    • Inoltre, aspetta un secondo sostenitore della programmazione micro-funzionale come mezzo per non aver bisogno di un IDE. Aspetta di leggere la mia spiegazione sulla normalizzazione del modello di dati.
  • Inquina lo spazio dei nomi con variabili non utilizzate nell'ambito corrente? Potrebbe essere sostenitori di questa opinione

    • non sono a conoscenza e la necessità della normalizzazione del modello di dati
  • L'utilizzo di interfacce per l'applicazione di costanti è un abuso di interfacce. I sostenitori di tali hanno una cattiva abitudine di

    • non vedendo che le "costanti" devono essere considerate come un contratto. E le interfacce sono utilizzate per far rispettare o proiettare la conformità a un contratto.
  • È difficile, se non impossibile, convertire le interfacce in classi implementate in futuro. Hah .... hmmm ... ???

    • Perché vorresti impegnarti in un simile modello di programmazione come il tuo persistente sostentamento? IOW, perché dedicare te stesso a una tale abitudine di programmazione AMBIVALENTE e cattiva?

A prescindere dalle scuse, NON ESISTE UN VALIDO ESCLUSIVO quando si tratta di ingegneria del software EFFICACE FONDAMENTALE per delegittimare o in generale scoraggiare l'uso delle costanti dell'interfaccia.

Non importa quali siano stati gli intenti originali e gli stati mentali dei padri fondatori che hanno creato la Costituzione degli Stati Uniti. Potremmo discutere gli intenti originali dei padri fondatori, ma tutto quello che mi interessa sono le dichiarazioni scritte della Costituzione degli Stati Uniti. Ed è responsabilità di ogni cittadino statunitense sfruttare il fondamentalismo letterario scritto, non gli intenti fondativi non scritti, della Costituzione degli Stati Uniti.

Allo stesso modo, non mi interessa quali siano le intenzioni "originali" dei fondatori della piattaforma Java e del linguaggio di programmazione per l'interfaccia. Quello che mi interessa sono le funzionalità efficaci fornite dalla specifica Java e intendo sfruttare al meglio queste funzionalità per aiutarmi a soddisfare le leggi fondamentali della programmazione del software responsabile. Non mi interessa se sono percepito come "violare l'intenzione delle interfacce". Non mi interessa cosa dice Gosling o qualcuno Bloch riguardo al "modo corretto di usare Java", a meno che ciò che dicono non violi il mio bisogno di EFFETTIVO raggiungimento dei fondamentali.

Il fondamentale è la normalizzazione del modello di dati

Non importa come il tuo modello di dati è ospitato o trasmesso. Sia che si utilizzino interfacce o enumerazioni o qualsiasi cosa, relazionale o no-SQL, se non si comprende la necessità e il processo di normalizzazione del modello di dati.

Dobbiamo prima definire e normalizzare il modello di dati di un insieme di processi. E quando abbiamo un modello di dati coerente, SOLO possiamo usare il flusso di processo dei suoi componenti per definire il comportamento funzionale ei blocchi di processo un campo o regno di applicazioni. E solo allora possiamo definire l'API di ogni processo funzionale.

Persino le sfaccettature della normalizzazione dei dati proposte da EF Codd sono ora seriamente messe in discussione e messe a dura prova. per esempio. la sua affermazione su 1NF è stata criticata come ambigua, disallineata e troppo semplificata, come del resto le sue affermazioni, specialmente nell'avvento dei moderni servizi di dati, repo-tecnologia e trasmissione. IMO, le dichiarazioni di EF Codd dovrebbero essere completamente abbandonate e sarà progettata una nuova serie di affermazioni matematicamente plausibili.

Una vistosa imperfezione di EF Codd e la causa del suo disallineamento per un'efficace comprensione umana è la sua convinzione che i dati multidimensionali e mutabili percepibili dall'uomo possano essere percepiti in modo efficiente attraverso una serie di mappature bidimensionali frammentarie.

Nozioni di base sulla normalizzazione dei dati

Cosa non ha espresso EF Codd.

All'interno di ciascun modello di dati coerente, questi sono l'ordine progressivo graduato della coerenza del modello di dati da raggiungere.

  1. L'unità e identità delle istanze di dati.
    • progettare la granularità di ciascun componente di dati, per cui la loro granularità è a un livello in cui ogni istanza di un componente può essere identificata e recuperata in modo univoco.
    • assenza di aliasing dell'istanza. cioè, non esiste alcun mezzo per cui un'identificazione produce più di un'istanza di un componente.
  2. Assenza di crosstalk di istanza. Non esiste la necessità di utilizzare una o più altre istanze di un componente per contribuire all'identificazione di un'istanza di un componente.
  3. L'unità e l'identità dei componenti/dimensioni dei dati.
    • Presenza di de-aliasing dei componenti. Deve esistere una definizione in base alla quale una componente/dimensione può essere identificata in modo univoco. Qual è la definizione principale di un componente;
    • dove la definizione primaria non risulterà nell'esposizione di sub-dimensioni o componenti membri che non fanno parte di un componente previsto;
  4. Mezzi unici di dealing dei componenti. Deve esistere una e una sola definizione di de-aliasing di componente per un componente.
  5. Esiste una sola e sola interfaccia di definizione o contratto per identificare un componente genitore in una relazione gerarchica di componenti.
  6. Assenza di crosstalk dei componenti. Non esiste la necessità di utilizzare un membro di un altro componente per contribuire all'identificazione definitiva di un componente.
    • In una relazione genitore-figlio, la definizione di identificazione di un genitore non deve dipendere da una parte dell'insieme di componenti membri di un bambino. Un componente membro dell'identità di un genitore deve essere l'identità del bambino completa senza ricorrere al riferimento a uno o tutti i figli di un bambino.
  7. Prevenire le apparenze bi-modali o multimodali di un modello di dati.
    • Quando esistono due definizioni candidate di un componente, è un segno evidente che esistono due diversi modelli di dati che vengono mescolati come uno. Ciò significa che c'è un'incoerenza a livello di modello di dati o livello di campo.
    • Un campo di applicazioni deve utilizzare uno e un solo modello di dati, in modo coerente.
  8. Rileva e identifica la mutazione del componente. A meno che tu non abbia eseguito l'analisi statistica dei componenti di enormi dati, probabilmente non vedi, o vedi la necessità di trattare, la mutazione dei componenti.
    • Un modello di dati può avere alcuni dei suoi componenti mutare ciclicamente o gradualmente.
    • La modalità può essere la rotazione dei membri o la trasposizione-rotazione.
    • La mutazione di rotazione dei membri potrebbe essere lo scambio di parti secondarie tra componenti. O dove dovrebbero essere definiti componenti completamente nuovi.
    • La mutazione trasposizionale si manifesterebbe come un membro dimensionale che si muta in un attributo, viceversa.
    • Ogni ciclo di mutazione deve essere identificato come un distinto modale di dati.
  9. Versionize ogni mutazione. Tale che è possibile estrarre una versione precedente del modello di dati, quando forse è necessario per trattare una mutazione di 8 anni del modello di dati.

In un campo o in una griglia di applicazioni componenti inter-servizio, deve esserci un solo ed unico modello di dati coerente o esiste un mezzo per un modello/versione di dati per identificarsi.

Stiamo ancora chiedendo se potremmo usare le costanti di interfaccia? Veramente ?

Ci sono problemi di normalizzazione dei dati in gioco più consequenziali di questa banale domanda. Se non risolvi questi problemi, la confusione che pensi che le costanti dell'interfaccia causino è comparativamente nulla. Zilch.

Dalla normalizzazione del modello di dati, si determinano i componenti come variabili, come proprietà, come costanti dell'interfaccia del contratto.

Quindi si determina quale valore va all'iniezione del valore, alla posizione di configurazione delle proprietà, alle interfacce, alle stringhe finali, ecc.

Se devi usare la scusa di dover individuare un componente più facile da dettare contro le costanti dell'interfaccia, significa che hai la brutta abitudine di non praticare la normalizzazione del modello di dati.

Forse desideri compilare il modello di dati in una versione vcs. Che puoi estrarre una versione chiaramente identificabile di un modello di dati.

I valori definiti nelle interfacce sono completamente certi di non essere mutabili. E condivisibile. Perché caricare un set di stringhe finali nella tua classe da un'altra classe quando tutto ciò di cui hai bisogno è quell'insieme di costanti ??

Quindi, perché non pubblicare un contratto modello di dati? Voglio dire se riesci a gestirlo e normalizzarlo in modo coerente, perché no? ...

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

Ora posso fare riferimento alle etichette contrattate delle mie app in un modo come

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

Questo confonde il contenuto del file jar? Come programmatore Java non mi interessa la struttura del barattolo.

Questo presenta complessità per lo scambio di runtime osgi-motivato? Osgi è un mezzo estremamente efficiente per consentire ai programmatori di continuare nelle loro cattive abitudini. Ci sono alternative migliori di osgi.

O perché no? Non c'è nessuna perdita delle costanti private nel contratto pubblicato. Tutte le costanti private devono essere raggruppate in un'interfaccia privata denominata "Costanti", poiché non desidero cercare le costanti e sono troppo pigro per digitare ripetutamente "String finale privata".

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

Forse anche questo:

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

L'unico problema con le costanti dell'interfaccia che vale la pena considerare è quando l'interfaccia è implementata.

Questa non è "l'intenzione originale" delle interfacce? Come se mi interessasse la "intenzione originale" dei padri fondatori nell'elaborare la Costituzione degli Stati Uniti, piuttosto che come la Corte Suprema interpreterebbe le lettere scritte della Costituzione degli Stati Uniti ???

Dopotutto, vivo nella terra dei liberi, dei selvaggi e dei coraggiosi. Sii coraggioso, sii libero, sii selvaggio - usa l'interfaccia. Se i miei colleghi programmatori si rifiutano di usare mezzi di programmazione efficienti e pigri, sono obbligato dalla regola d'oro a ridurre la mia efficienza di programmazione per allinearsi con la loro? Forse dovrei, ma non è una situazione ideale.

0
Blessed Geek

Per fare un ulteriore passo avanti, è possibile inserire costanti globalmente utilizzate in un'interfaccia in modo che possano essere utilizzate a livello di sistema. Per esempio.

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

Ma non applicarlo. Basta fare riferimento a loro direttamente nel codice tramite il nome di classe completo.

0

Io uso static final per dichiarare le costanti e andare con la notazione di denominazione ALL_CAPS. Ho visto molte istanze di vita reale in cui tutte le costanti sono raggruppate in un'interfaccia. Alcuni post hanno giustamente definito questa una cattiva pratica, principalmente perché non è ciò a cui è destinata un'interfaccia. Un'interfaccia dovrebbe imporre un contratto e non dovrebbe essere un posto dove inserire costanti non correlate. Metterlo insieme in una classe che non può essere istanziata (attraverso un costruttore privato) va bene anche se la semantica costante non appartiene a una classe specifica ( es). Metto sempre una costante nella classe a cui è più legata, perché ha senso ed è anche facilmente mantenibile.

Le enumerazioni sono una buona scelta per rappresentare un intervallo di valori, ma se si memorizzano le costanti standalone con un'enfasi sul valore assoluto (ad esempio TIMEOUT = 100 ms) si può semplicemente adottare l'approccio static final.

0
bincob

Per Costanti, Enum è una scelta migliore IMHO. Ecco un esempio

classe pubblica 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

Sono d'accordo con ciò che più stanno dicendo, è meglio usare le enumerazioni quando si ha a che fare con una collezione di costanti. Tuttavia, se si sta programmando su Android, esiste una soluzione migliore: 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'annotazione IntDef è superiore alle enumerazioni in un modo semplice, richiede molto meno spazio in quanto è semplicemente un indicatore in fase di compilazione. Non è una classe e non ha la proprietà di conversione automatica delle stringhe.

0
Quinn Turner

Una delle cose che faccio è creare una classe 'Globale' con i valori costanti e fare un'importazione statica nelle classi che hanno bisogno di accedere alla costante.

0
Javamann