Risposte:
Mettere membri statici in un'interfaccia (e implementare quell'interfaccia) è una cattiva pratica e c'è anche un nome per esso, Constant Interface Antipattern , vedi Effective Java , Item 17:
Il modello di interfaccia costante è un cattivo utilizzo delle interfacce . Che una classe utilizzi alcune costanti internamente è un dettaglio di implementazione. L'implementazione di un'interfaccia costante fa sì che questo dettaglio di implementazione trapeli nell'API esportata della classe. Non ha importanza per gli utenti di una classe che la classe implementa un'interfaccia costante. In effetti, potrebbe persino confonderli. Peggio ancora, rappresenta un impegno: se in una futura release la classe viene modificata in modo da non dover più utilizzare le costanti, deve comunque implementare l'interfaccia per garantire la compatibilità binaria. Se una classe non finale implementa un'interfaccia costante, tutte le sue sottoclassi avranno i loro spazi dei nomi inquinati dalle costanti nell'interfaccia.
Ci sono diverse interfacce costanti nelle librerie della piattaforma java, come
java.io.ObjectStreamConstants
. Queste interfacce dovrebbero essere considerate come anomalie e non dovrebbero essere emulate.
Per evitare alcune insidie dell'interfaccia costante (perché non puoi impedire alle persone di implementarla), dovrebbe essere preferita una classe appropriata con un costruttore privato (esempio preso in prestito da Wikipedia ):
public final class Constants {
private Constants() {
// restrict instantiation
}
public static final double PI = 3.14159;
public static final double PLANCK_CONSTANT = 6.62606896e-34;
}
E per accedere alle costanti senza doverle qualificare completamente (cioè senza doverle anteporre al nome della classe), usa un'importazione statica (da Java 5):
import static Constants.PLANCK_CONSTANT;
import static Constants.PI;
public class Calculations {
public double getReducedPlanckConstant() {
return PLANCK_CONSTANT / (2 * PI);
}
}
" Il modello di interfaccia costante è un cattivo uso delle interfacce "
Chiunque abbia inventato questa ipotesi, per quanto un guru possa essere, l'ha inventata sulla base della necessità di continuare a mettere in atto le cattive abitudini e pratiche in modo efficiente. L'ipotesi si basa sulla promozione della validità di cattive abitudini di progettazione del software.
Ho scritto una risposta di confutazione contro questa ipotesi qui: Qual è il modo migliore per implementare le costanti in Java? spiegando l'infondatezza di questa ipotesi.
Per 10 anni quella domanda era rimasta aperta, fino a quando non è stata chiusa entro 2 ore dopo che ho postato le mie ragioni scoraggiando questa ipotesi, esponendo così la DIS VOLONTA 'al dibattito da parte di coloro che si aggrappano a questa ipotesi sbagliata a caro prezzo.
Questi sono i punti che ho espresso contro l'ipotesi
La base per sostenere questa ipotesi è la necessità di metodi e regole RESTRITTIVE per far fronte agli effetti delle cattive abitudini e metodologie del software.
I sostenitori del sentimento " Il modello di interfaccia costante è un cattivo uso delle interfacce" non sono in grado di fornire ragioni diverse da quelle causate dalla necessità di far fronte agli effetti di quelle cattive abitudini e pratiche.
Risolvi il problema fondamentale.
E allora perché non fare pieno uso e sfruttare ogni caratteristica del linguaggio della struttura del linguaggio Java a proprio piacimento. Nessuna giacca richiesta. Perché inventare regole per barricare il tuo stile di vita inefficace per discriminare e incriminare stili di vita più efficaci?
è l'organizzazione dell'informazione. Le informazioni che mediano il processo e il comportamento di tali informazioni dovrebbero essere prima comprese, insieme alle cosiddette regole di business, prima di progettare o integrare soluzioni al processo. Questo metodo di organizzazione delle informazioni è stato chiamato normalizzazione dei dati alcuni decenni fa.
Quindi solo l'ingegnerizzazione di una soluzione sarà possibile perché allineare la granularità e la modularità dei componenti di una soluzione con la granularità e la modularità dei componenti delle informazioni è la strategia ottimale.
Ci sono due o tre ostacoli significativi all'organizzazione delle informazioni.
La mancanza di percezione della necessità di "normalizzazione" del modello di dati.
Le dichiarazioni di EF Codd sulla normalizzazione dei dati sono errate, difettose e ambigue.
L'ultima moda mascherata da ingegneria agile è l'idea sbagliata che non si dovrebbe pianificare e condizionare l'organizzazione dei moduli in anticipo perché è possibile eseguire il refactoring man mano che si procede. Il refactoring e il cambiamento continuo senza essere ostacolato da scoperte future è usato come scusa. Le scoperte essenziali del comportamento delle informazioni di processo sono quindi, utilizzando trucchi contabili per ritardare i profitti e l'assetization, per cui le conoscenze essenziali e il loro trattamento sono ritenute non necessarie ora.
Non inventare regole né emettere fatwa contro di esso solo perché ami le tue abitudini di programmazione ad hoc.
Non vietare la proprietà di armi con la ragione che ci sono persone che o non sanno come maneggiarle o sono inclini ad abusarne.
Se le regole che crei sono pensate per programmare i principianti incapaci di codificare professionalmente e che ti annoi tra di loro, allora dillo - non dichiarare la tua fatwa come applicabile a modelli di dati correttamente normalizzati.
Non mi interessa quali fossero le intenzioni originali dei padri fondatori per la costituzione degli Stati Uniti. Non mi interessano le intenzioni non scritte non modificate. Mi interessa solo ciò che è letteralmente codificato nella Costituzione scritta e come posso sfruttarli per il funzionamento efficace della società.
Mi interessa solo ciò che le specifiche del linguaggio / piattaforma Java mi consentono e intendo sfruttarle al massimo per offrirmi un mezzo per esprimere le mie soluzioni software in modo efficiente ed efficace. Non sono necessarie giacche.
Richiede la scrittura di codice aggiuntivo per mappare il parametro al valore. Il fatto che i fondatori di Java non abbiano fornito la mappatura valore-parametro senza che tu abbia scritto che il codice di mappatura dimostra che le costanti Enum sono un uso non intenzionale del linguaggio Java.
Soprattutto dal momento che non sei incoraggiato a normalizzare e componentizzare i tuoi parametri, ci sarebbe una falsa impressione che i parametri mescolati in una borsa Enum appartengano alla stessa dimensione.
Non dimenticarlo. Se hai progettato e normalizzato il tuo modello di dati e include costanti, quelle costanti sono contratti. Se non hai normalizzato il tuo modello di dati, dovresti conformarti alle fatwa fornite su come praticare la codifica restrittiva per far fronte a quella cattiva abitudine.
Pertanto, le interfacce sono un modo perfetto per implementare il contratto di Constants.
Sì. Chiunque potrebbe inavvertitamente implementare qualsiasi interfaccia inavvertitamente. Niente ostacolerà questi programmatori involontari.
Non inserire decreti restrittivi per proteggere presunte cattive pratiche che causano la fuoriuscita di parametri non contrattuali / vaganti nell'API. Risolvi il problema fondamentale, piuttosto che dare la colpa alle costanti dell'interfaccia.
Un programmatore normale ed EFFICACE non è lì per dimostrare quanto tempo può stare sott'acqua, quanto lontano potrebbe camminare in caso di caldo torrido o temporali umidi. Deve usare uno strumento efficiente come un'auto o un autobus o almeno una bicicletta per portarle al lavoro 10 miglia ogni giorno.
Non porre restrizioni agli altri programmatori solo perché hai un'ossessione esoterica di ascetismo con la programmazione senza IDE.
OSGI è un tale framework. E così è anche il decreto contro le Costanti di Interfaccia.
Le costanti di interfaccia sono un modo efficace ed efficiente per inserire nel contratto componenti ben progettati e normalizzati di un modello di dati.
Anche le costanti di interfaccia in un'interfaccia privata dal nome appropriato annidate in un file di classe sono una buona pratica per raggruppare tutte le costanti private piuttosto che spargerle in tutto il file.
Mi sono imbattuto in questa vecchia domanda diverse volte e la risposta accettata mi confonde ancora. Dopo molte riflessioni, penso che questa domanda possa essere ulteriormente chiarita.
Basta confrontarli:
public final class Constants {
private Constants() {
// restrict instantiation
}
public static final double PI = 3.14159;
public static final double PLANCK_CONSTANT = 6.62606896e-34;
}
vs
public interface Constants {
double PI = 3.14159;
double PLANCK_CONSTANT = 6.62606896e-34;
}
Stesso utilizzo. Molto meno codice.
Penso che la risposta di @Pascal Thivent abbia l'enfasi sbagliata, ecco la mia versione:
Mettere membri statici in un'interfaccia ( e implementare tale interfaccia ) è una cattiva pratica.
La citazione da Effective Java presuppone che l'interfaccia costante venga implementata da altri, cosa che penso non dovrebbe (e non accadrà).
Quando crei un'interfaccia costante chiamata qualcosa di simile Constants
, non dovrebbe essere implementata da nessuno. (sebbene tecnicamente possibile, che è l'unico problema qui)
La libreria standard non può permettersi alcun possibile uso improprio del design, quindi non ne vedrai nessuno.
Tuttavia , per i progetti di tutti i giorni di sviluppatori normali, utilizzando l'interfaccia costanti è molto più facile perché non c'è bisogno di preoccuparsi static
, final
,empty constructor
, ecc, e sarà non causa alcun problema di progettazione male. L'unico aspetto negativo a cui riesco a pensare è che ha ancora il nome di "interfaccia", ma niente di più.
Alla fine, penso che tutti stiano solo citando dai libri e dando opinioni e giustificazioni alle loro posizioni. Nessuna eccezione per me. Forse la decisione spetta ancora agli sviluppatori di ogni progetto. Vai avanti per usarlo se ti senti a tuo agio. Il meglio che possiamo fare è renderlo coerente durante tutto il progetto .
public
può anche essere omesso poiché è un'interfaccia, rendendolo semplicemente double PI = 3.14159;
Usage of Constants.PI
non ha bisogno della classe che lo usa per implementare l' Constants
interfaccia! Penso che l'approccio all'interfaccia sia molto più pulito in termini di utilizzo, IMHO
Joshua Bloch, "Effective Java - Programming Language Guide":
Il modello di interfaccia costante è un cattivo utilizzo delle interfacce. Che una classe utilizzi alcune costanti internamente è un dettaglio di implementazione. L'implementazione di un'interfaccia costante fa sì che questo dettaglio di implementazione trapeli nell'API esportata della classe. Non ha importanza per gli utenti di una classe che la classe implementa un'interfaccia costante. In effetti, potrebbe persino confonderli. Peggio ancora, rappresenta un impegno: se in una futura release la classe viene modificata in modo da non dover più utilizzare le costanti, dovrà comunque implementare l'interfaccia per garantire la compatibilità binaria. Se una classe non finale implementa un'interfaccia costante, tutte le sue sottoclassi avranno i loro spazi dei nomi inquinati dalle costanti nell'interfaccia.
Sono utili se si hanno costanti comuni che verranno utilizzate nelle classi che implementano l'interfaccia.
Ecco un esempio: http://www.javapractices.com/topic/TopicAction.do?Id=32
Ma si noti che la pratica consigliata è quella di utilizzare importazioni statiche invece di costanti nelle interfacce. Ecco un riferimento: http://www.javapractices.com/topic/TopicAction.do?Id=195
Ci sono risposte molto ragionevoli.
Ma ho alcuni pensieri su questa domanda. (potrebbe essere sbagliato)
A mio parere, i campi in un'interfaccia, non dovrebbero essere costanti all'intero progetto, sono solo mezzi per l'interfaccia e le interfacce la estendono e le classi che implementano queste interfacce o hanno una stretta relazione con esse. Dovrebbero essere utilizzati entro un certo intervallo non globale.
Due punti sull'interfaccia:
Un'interfaccia descrive un sottoinsieme di ciò che può fare un oggetto che lo implementa. (Questa è l'intuizione)
Un'interfaccia descrive le costanti comuni seguite da oggetti che la implementano.
Quindi penso che se Constants Interface non viene utilizzata per le costanti globali , allora è accettabile:
implements
farlo (e, ovviamente, utilizzare queste costanti comuni nell'implementazione).Esempio:
interface Drawable {
double GOLDEN_RATIO = 1.618033988;
double PI = 3.141592653;
...
// methods
...
}
public class Circle implements Drawable {
...
public double getCircumference() {
return 2 * PI * r;
}
}
void usage() {
Circle circle = new Circle(radius: 3.0);
double maxRadius = 5.0;
if ( circle.getCircumference() < 2 * Circle.PI * maxRadius ) {
...
}
}
In questo esempio:
Circle implements Drawable
, si capisce subito che Circle
probabilmente è conforme alle costanti definite in Drawable
, altrimenti devono scegliere un nome peggiore rispetto a quelli buoni PI
ed GOLDEN_RATIO
è già stato preso!Drawable
oggetti sono conformi allo specifico PI
e GOLDEN_RATIO
definito in Drawable
, possono esserci oggetti che non sono Drawable
con diversa precisione di pi greco e sezione aurea.L' javax.swing.SwingConstants
interfaccia è un esempio che ha dei campi statici che vengono utilizzati tra le classi swing. Ciò ti consente di utilizzare facilmente qualcosa di simile
this.add(LINE_START, swingcomponent);
this.add(this.LINE_START, swingcomponent);
o this.add(SwingComponents.LINE_START, swingcomponent);
Tuttavia questa interfaccia non ha metodi ...
Mi sono imbattuto in questa domanda e ho pensato di aggiungere qualcosa che non era menzionato. In generale, sono d'accordo con la risposta di Pascal qui . Tuttavia, non credo che le costanti su un'interfaccia siano "sempre" un antipattern.
Ad esempio, se le costanti che stai definendo fanno parte di un contratto per quell'interfaccia, penso che l'interfaccia sia un ottimo posto per le costanti. In alcuni casi, non è appropriato convalidare privatamente i parametri senza esporre il contratto agli utenti della tua implementazione. Senza un contratto pubblico, gli utenti possono solo indovinare con cosa stai convalidando, a meno di decompilare la classe e leggere il tuo codice.
Quindi, se implementi un'interfaccia e l'interfaccia ha le costanti che usi per garantire i tuoi contratti (come gli intervalli interi per esempio), un utente della tua classe può essere sicuro di utilizzare correttamente l'istanza dell'interfaccia controllando le costanti nell'interfaccia loro stessi. Ciò sarebbe impossibile se le costanti fossero private della tua implementazione o se la tua implementazione fosse privata del pacchetto o qualcosa del genere.
Uso le costanti dell'interfaccia quando si tratta di costanti condivise tra le classi.
public interface TestConstants
{
String RootLevelConstant1 = "RootLevelConstant1";
interface SubGroup1
{
String SubGroupConstant1 = "SubGroup1Constant1";
String SubGroupConstant2 = "SubGroup1Constant2";
}
interface SubGroup2
{
String SubGroupConstant1 = "SubGroup2Constant1";
String SubGroupConstant2 = "SubGroup2Constant2";
}
}
Il raggruppamento è una risorsa enorme, soprattutto con un ampio insieme di costanti.
Per usarli, li incateni semplicemente insieme:
System.out.println(TestConstants.SubGroup1.SubGroupConstant1);
System.out.println(TestConstants.SubGroup2.SubGroupConstant1);
System.out.println(TestConstants.RootLevelConstant1);
i campi dovrebbero essere dichiarati in un'interfaccia in modo che siano più facili da condividere e possano essere referenziati senza introdurre ulteriori accoppiamenti.
Fonte: stile di codifica degli strumenti per sviluppatori Java