Uso di classi pubbliche nidificate per organizzare le costanti

18

Sto lavorando a un'applicazione con molte costanti. All'ultima revisione del codice è emerso che le costanti sono troppo sparse e dovrebbero essere tutte organizzate in un singolo file di costanti "master". Il disaccordo riguarda il modo di organizzarli. La maggioranza ritiene che l'uso del nome costante dovrebbe essere abbastanza buono, ma ciò 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 sui nomi sia ingombrante. Ho pensato che potrebbe essere più semplice 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 accolta bene perché era "troppo complicata" (non ho avuto molti dettagli su perché potrebbe essere troppo complicato). Penso che questo crei una divisione migliore tra i gruppi di costanti correlate e il completamento automatico renda più facile trovarli. Non ho mai visto questo, però, mi chiedo se questa è una pratica accettata o se ci sono ragioni migliori per non farlo.

    
posta FrustratedWithFormsDesigner 26.10.2012 - 21:48
fonte

6 risposte

12

Non sono d'accordo con nessuna delle due proposte.

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

Non ci dovrebbero essere solo classi / interfacce di costanti.

Una classe CreditCard (non una classe interna) dovrebbe esistere. Questa classe / interfaccia ha metodi relativi alle carte di credito, nonché le costanti UI_EXPIRY_MONTH e UI_ACCOUNT_ID .

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

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

Ad esempio, queste costanti relative ai set di risultati sono 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 firme di metodo relative ai set di risultati e le classi di implementazione implementano tale comportamento. Non sono semplici sostenitori.

Queste costanti relative alle azioni dell'interfaccia utente sono 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 relativo alle azioni dell'interfaccia utente, non sono semplici titolari.

Conosco almeno un'interfaccia "costanti" ( SwingConstants ) senza metodi ma non ha centinaia di costanti, solo alcune, e sono tutte correlate alle direzioni e alle 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 sole classi di costanti non siano un buon design OO.

    
risposta data 26.10.2012 - 22:56
fonte
9

Hai ragione. Il tuo suggerimento consente a un programmatore di import static Constants.BankAccount.* ed elimina le ripetizioni infinite di "BANKACCOUNT_". La concatenazione è un cattivo sostituto per l'ambito effettivo. Detto questo, non ho molte speranze per te di cambiare la cultura della squadra. Hanno una nozione di pratiche corrette e non è probabile che cambino anche se mostri loro 100 esperti che affermano di avere torto.

Mi sto anche chiedendo perché tu abbia un singolo file 'Constants'. Questa è una pessima pratica, a meno che queste costanti non siano tutte collegate in qualche modo e siano molto stabili. Più tipicamente diventa una sorta di classe da cucina che cambia costantemente e dipende da tutto.

    
risposta data 26.10.2012 - 22:41
fonte
7

it came up that the constants are too scattered and should all be organized into a single "master" constants file.

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

Ad eccezione delle architetture dei livelli, le cose dovrebbero essere raggruppate in base al loro dominio e le costanti a maggior ragione in quanto si tratta di elementi di livello molto basso. Le costanti dovrebbero far parte delle classi o delle interfacce che le utilizzano come parte della loro API. Se non riesci a trovare un posto naturale in cui vivere, devi ripulire la progettazione dell'API.

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

    
risposta data 26.10.2012 - 23:23
fonte
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 all'interfaccia costante anti-pattern. Non vedo cosa sia complicato, ma è una discussione che dovresti avere con il tuo team.

    
risposta data 26.10.2012 - 22:14
fonte
1

Una delle sfide con la lunga lista di costanti è trovare la costante "corretta" da utilizzare. Invariabilmente, qualcuno aggiusta una costante alla fine della riga invece di aggiungerla al gruppo a cui apparteneva.

Che fa emergere un altro punto da discutere con la tua squadra: esiste già una categorizzazione delle costanti attraverso i loro nomi. Quindi non dovrebbe davvero essere un grande cambiamento per loro dallo stato attuale a quello che stai proponendo. L'utilizzo del completamento automatico semplifica ulteriormente le ricerche costanti.

Se non altro, il tuo suggerimento aiuta a scoraggiare l'uso della costante "sbagliata" anche se potrebbe rientrare in una situazione particolare. Con il wrapping delle costanti all'interno di una classe rappresentativa, incoraggerà gli sviluppatori a pensare se dovrebbero usarlo. Ad esempio, se sposto CreditCard.SomeConstant per l'utilizzo generale, dovrei davvero chiedermi perché non ci sia un General.SomeConstant per quella situazione.

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

    
risposta data 26.10.2012 - 22:24
fonte
1

Lo faccio occasionalmente (in C #), in particolare se ho bisogno di programmare contro / analizzare una struttura XML ben nota e fissa o qualcosa di simile annidato e stringa pesante ... per esempio un parser di blocchi di configurazione personalizzato.

Costruisco una struttura di classe nidificata che corrisponde alla struttura gerarchica di XML con i nomi di classe corrispondenti agli elementi contenenti una proprietà const "ElementName" e una proprietà simile corrispondente a ciascun Attributo (se presente).

Rende molto facile la programmazione rispetto all'Xml corrispondente.

    
risposta data 27.10.2012 - 01:07
fonte

Leggi altre domande sui tag