Utilizzo di classi pubbliche nidificate per organizzare le costanti


21

Sto lavorando ad un'applicazione con molte costanti. All'ultima revisione del codice è emerso che le costanti sono troppo sparse e dovrebbero essere organizzate in un unico file di costanti "master". Il disaccordo riguarda il modo in cui organizzarli. La maggior parte ritiene che l'uso del nome costante dovrebbe essere abbastanza buono, ma questo porterà a un codice simile al seguente:

public static final String CREDITCARD_ACTION_SUBMITDATA = "6767";
public static final String CREDITCARD_UIFIELDID_CARDHOLDER_NAME = "3959854";
public static final String CREDITCARD_UIFIELDID_EXPIRY_MONTH = "3524";
public static final String CREDITCARD_UIFIELDID_ACCOUNT_ID = "3524";
...
public static final String BANKPAYMENT_UIFIELDID_ACCOUNT_ID = "9987";

Trovo che questo tipo di convenzione di denominazione sia ingombrante. Ho pensato che potrebbe essere più facile usare la classe nidificata pubblica e avere qualcosa del genere:

public class IntegrationSystemConstants
{
    public class CreditCard
    {
        public static final String UI_EXPIRY_MONTH = "3524";
        public static final String UI_ACCOUNT_ID = "3524";
        ...
    }
    public class BankAccount
    {
        public static final String UI_ACCOUNT_ID = "9987";
        ...
    }
}

Questa idea non è stata ben accolta perché era "troppo complicata" (non ho avuto molti dettagli sul perché questo potrebbe essere troppo complicato). Penso che questo crei una migliore divisione tra gruppi di costanti correlate e il completamento automatico facilita anche la ricerca di questi. Non l'ho mai visto fatto, quindi mi chiedo se questa è una pratica accettata o se ci sono ragioni migliori per cui non dovrebbe essere fatto.


1
Preferisco l'idea. Mi sono ritrovato a fare qualcosa di simile in C ++ quando volevo uno scoping e un comportamento simile all'enum in stile C #, ma con valori significativi (penso che l'idea sia nata perché mi ero abituato ad usare le classi case al posto degli enumerazioni in Scala). Certo, questo era un progetto personale per divertimento e non uno sforzo di squadra.
KChaloux,

Risposte:


13

Non sono d'accordo con nessuna delle due proposte.

Le costanti dovrebbero essere nelle loro classi pertinenti , non in una classe costante in nessuna delle due forme proposte.

Non ci dovrebbero essere classi / interfacce solo costanti.

CreditCardDovrebbe esistere una classe (non una classe interna). Questa classe / interfaccia ha metodi relativi alle carte di credito nonché alle costanti UI_EXPIRY_MONTHe UI_ACCOUNT_ID.

Dovrebbe esistere una classe / interfaccia BankAccount(non una classe interna). Questa classe / interfaccia ha metodi relativi ai conti bancari oltre che costanti UI_ACCOUNT_ID.

Ad esempio nell'API Java ogni classe / interfaccia ha le sue costanti. Non fanno parte di una classe / interfaccia Costanti con centinaia di costanti, raggruppate in classi interne o meno.

Ad esempio, queste costanti pertinenti ai set di risultati si trovano nell'interfaccia ResultSet:

static int  CLOSE_CURSORS_AT_COMMIT 
static int  CONCUR_READ_ONLY 
static int  CONCUR_UPDATABLE 
static int  FETCH_FORWARD 
static int  FETCH_REVERSE 
static int  FETCH_UNKNOWN 
static int  HOLD_CURSORS_OVER_COMMIT 
static int  TYPE_FORWARD_ONLY 
static int  TYPE_SCROLL_INSENSITIVE 
static int  TYPE_SCROLL_SENSITIVE 

Questa interfaccia ha le firme dei metodi relative ai set di risultati e le classi di implementazione implementano quel comportamento. Non sono semplici detentori di costanti.

Queste costanti pertinenti alle azioni dell'interfaccia utente si trovano nell'interfaccia javax.swing.Action:

static String   ACCELERATOR_KEY 
static String   ACTION_COMMAND_KEY 
static String   DEFAULT 
static String   LONG_DESCRIPTION 
static String   MNEMONIC_KEY 
static String   NAME 
static String   SHORT_DESCRIPTION 
static String   SMALL_ICON 

Le classi di implementazione hanno un comportamento rispetto alle azioni dell'interfaccia utente, non sono semplici detentori costanti.

Conosco almeno un'interfaccia "costanti" ( SwingConstants) senza metodi ma non ha centinaia di costanti, solo alcune, e sono tutte correlate alle direzioni e posizioni degli elementi dell'interfaccia utente:

static int  BOTTOM 
static int  CENTER 
static int  EAST 
static int  HORIZONTAL 
static int  LEADING 
static int  LEFT 
static int  NEXT 
static int  NORTH 
static int  NORTH_EAST 
static int  NORTH_WEST 
static int  PREVIOUS 
static int  RIGHT 
static int  SOUTH 
static int  SOUTH_EAST 
static int  SOUTH_WEST 
static int  TOP 
static int  TRAILING 
static int  VERTICAL 
static int  WEST 

Penso che le costanti solo le classi non siano un buon design OO.


1
Anche se concordo sul fatto che le sole classi costanti nella maggior parte dei casi sono un segno di cattiva progettazione, ci sono usi legittimi. Ad esempio, la costante non "appartiene" sempre a una determinata classe. Le chiavi per gli extra Intent nella programmazione Android sono un esempio concreto.
curioustechizen,

1
+1, ma le costanti dell'interfaccia utente probabilmente non dovrebbero trovarsi in modelli di business come BankAccount. Appartengono a una classe UI.
Kevin Cline,

10

è emerso che le costanti sono troppo disperse e dovrebbero essere organizzate in un unico file di costanti "master".

Questa è la soluzione errata al 100% al problema delle costanti che sono "difficili da trovare". È un errore fondamentale (purtroppo troppo comunemente perpetrato dai programmatori) raggruppare le cose secondo criteri tecnici come essere costanti, enumerazioni o interfacce.

Ad eccezione delle architetture di layer, le cose dovrebbero essere raggruppate per il loro dominio e le costanti tanto più che sono elementi di livello molto basso. Le costanti dovrebbero far parte delle classi o interfacce che le usano come parte della loro API. Se non riesci a trovare un posto naturale in cui vivere, devi ripulire il tuo design API.

Inoltre, un unico enorme file di costanti uccide la velocità di sviluppo in Java perché le costanti sono incorporate nelle classi che le utilizzano al momento della compilazione, quindi qualsiasi modifica impone una ricompilazione di tutti quei file e tutto ciò che dipende da essi. Se hai un file con costanti che vengono utilizzati ovunque, perdi in gran parte il vantaggio della compilazione incrementale: guarda Eclipse bloccarsi per 15 minuti mentre ricompila l'intero progetto per ogni modifica a quel file. E poiché quel file contiene tutte le costanti utilizzate ovunque, lo cambierai abbastanza spesso. Sì, sto parlando per esperienza personale.


Non ero a conoscenza del potenziale impatto sull'ambiente di sviluppo e immagino che l'approccio di classe nidificata non sarà di grande aiuto, giusto?
FrustratedWithFormsDesigner,

1
@FrustratedWithFormsDesigner: dipende da quanto sforzo il meccanismo di compilazione incrementale dedica alle dipendenze della modellazione.
Michael Borgwardt,

9

Hai ragione. Il tuo suggerimento consente a un programmatore di import static Constants.BankAccount.*eliminare innumerevoli ripetizioni di "BANKACCOUNT_". La concatenazione è un pessimo sostituto dell'effettivo scoping. Detto questo, non ho molte speranze per te di cambiare la cultura della squadra. Hanno una nozione di pratiche adeguate e non sono suscettibili di cambiare anche se mostri loro 100 esperti che affermano di avere torto.

Mi chiedo anche perché tu abbia un singolo file "Costanti". Questa è una pessima pratica, a meno che queste costanti non siano tutte in qualche modo correlate e siano molto stabili. Più in genere diventa una specie di classe lavello che cambia costantemente e dipende da tutto.


Al momento disponiamo di un file Costanti che contiene la maggior parte delle costanti dell'ID del campo dell'interfaccia utente e un paio di altri file di costanti specifici del sottoprogetto. Ma ora, le costanti specifiche del sottoprogetto devono essere utilizzate da altri sottoprogetti correlati, quindi è ciò che ha spinto l'idea di unirle tutte in un file di costanti "master". Il che è meglio di adesso perché a volte non so nemmeno quale file di costanti fare riferimento per un valore, e qualcun altro ha creato un duplicato di una costante perché non è riuscito a trovarlo nel file delle costanti di un altro sottoprogetto.
FrustratedWithFormsDesigner,

8
Una classe di costanti che cambia costantemente ... c'è qualcosa di zen lì dentro, se scavi abbastanza forte.
KChaloux,

2
@FrustratedWithFormsDesigner: ID campo UI? Non sai dove trovare un valore? Sembra un enorme mucchio di WTF. Hai la mia simpatia.
Kevin Cline,

6

Entrambi gli approcci funzionano e questo è ciò che è importante alla fine della giornata.

Detto questo, il tuo approccio è abbastanza comune da essere considerato un pattern, o più precisamente un miglioramento abbastanza buono rispetto al costante anti-pattern dell'interfaccia . Non vedo cosa sia complicato, ma è una discussione che dovresti avere con la tua squadra.


Per un elenco abbastanza lungo di costanti, preferirei persino interfacce costanti piuttosto che averle tutte nella stessa classe. È pericolosamente possibile scegliere quello sbagliato dal completamento automatico. Certo, dipende da quanto tempo dura abbastanza :)
Goran Jovic,

1
@GoranJovic Beh, ogni anti-pattern è utile in qualche modo (o almeno conveniente), non sarebbe uno schema se non lo fosse.
yannis,

1

Una delle sfide con il lungo elenco di costanti è trovare la costante "corretta" da utilizzare. Invariabilmente, qualcuno inserisce una costante alla fine della linea invece di aggiungerla al gruppo a cui apparteneva.

Il che fa emergere un altro punto da discutere con il tuo team: esiste già una categorizzazione di fatto delle costanti attraverso i loro nomi. Quindi non dovrebbe davvero essere un grande passaggio per loro dallo stato attuale a quello che stai proponendo. L'uso del completamento automatico semplifica ulteriormente le ricerche costanti.

Semmai, il tuo suggerimento aiuta a scoraggiare l'uso della costante "sbagliata" anche se potrebbe adattarsi a una situazione particolare. Avvolgendo le costanti all'interno di una classe rappresentativa, incoraggerà gli sviluppatori a riflettere se dovrebbero usarlo. Ad esempio, se tiro CreditCard.SomeConstantper uso generale, dovrei davvero chiedermi perché non esiste invece una General.SomeConstantsituazione del genere.

Ho partecipato a progetti con quantità mostruose di costanti e avrei preferito avere il metodo che stai suggerendo. È più pulito, più diretto e aiuta a evitare l'uso involontario.


1

Lo faccio di tanto in tanto (in C #), in particolare se ho bisogno di programmare / analizzare una struttura XML ben nota e fissa o qualcosa di simile nidificato e pesantemente una stringa ... ad esempio un parser di blocchi di configurazione personalizzato.

Costruisco una struttura di classe nidificata corrispondente alla struttura gerarchica dell'XML con i nomi di classe corrispondenti agli elementi che contengono una proprietà const String "ElementName" e una proprietà simile corrispondente a ciascun attributo (se presente).

Rende molto facile programmare contro l'Xml corrispondente.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.