Le costanti a carattere singolo sono migliori dei letterali?


127

Di recente ho incontrato una classe che fornisce praticamente ogni singolo personaggio come costante; tutto da COMMAa BRACKET_OPEN. Chiedendosi se questo fosse necessario; Ho letto un "articolo" che suggerisce che può essere utile inserire letterali a carattere singolo in costanti. Quindi sono scettico.

L'appello principale dell'uso delle costanti è che minimizzano la manutenzione quando è necessaria una modifica. Ma quando inizieremo a utilizzare un simbolo diverso da "," per rappresentare una virgola?

L'unico motivo che vedo per l'utilizzo di costanti anziché letterali è rendere il codice più leggibile. Ma city + CharacterClass.COMMA + state(per esempio) è davvero più leggibile di city + ',' + state?

Per me i contro superano i pro, principalmente che introducete un'altra classe e un'altra importazione. E credo in meno codice ove possibile. Quindi, mi chiedo quale sia il consenso generale qui.



33
Hmm ... potrebbe essere utile per locali diversi, forse? Ad esempio, alcune lingue usano i guillements (virgolette angolari «e ») come virgolette invece dello standard inglese "(o più bello e ). A parte questo, sembra solo un insieme di personaggi magici. Supponendo due casi di CharacterClasschiamato englishCharse frenchChars, è possibile che englishChars.LEFT_QUOTEpotrebbe essere , mentre frenchChars.LEFT_QUOTEpotrebbe essere «.
Justin Time,

4
Ci sono molte varianti diverse tra virgole: en.wikipedia.org/wiki/Comma#Comma_variants - forse questa non è un'idea così stupida, specialmente se il tuo codice sorgente può essere codificato come utf-8.
Aaron Hall,

21
Nel tuo caso, è come chiamare un "numero" variabile. La tua costante avrebbe dovuto essere chiamata DELIMITER. O dovrebbe essere CITY_STATE = "{0}, {1}"
the_lotus

13
L'articolo che hai collegato è molto terribile. Le costanti non dovrebbero mai essere gettate in un secchio del genere. Inseriscili nelle classi in cui hanno un contesto: in sostanza, la classe con la costante fornisce il contesto in cui viene usata la costante. Ad esempio, Java File.separator. La classe ti dice il tipo di separatore. Avere una classe chiamata Constso Constantsnon fornisce alcun contesto e rende le costanti più difficili da usare correttamente.

Risposte:


183

Tautologia :

È molto chiaro se leggi la prima frase della domanda che questa domanda non riguarda usi appropriati come l' eliminazione dei numeri magici , si tratta al massimo di una terribile insensatezza insensata . È a questo che risponde questa risposta

Il buon senso vi dice che const char UPPER_CASE_A = 'A';o const char A = 'A'non aggiunge nulla, ma la manutenzione e la complessità al sistema. const char STATUS_CODE.ARRIVED = 'A'è un caso diverso.

Le costanti dovrebbero rappresentare elementi immutabili in fase di esecuzione, ma potrebbe essere necessario modificarli in futuro al momento della compilazione. Quando equivarrebbe const char A =correttamente a qualcosa di diverso da A?

Se vedi public static final char COLON = ':'nel codice Java, trova chi lo ha scritto e spezza le sue tastiere. Se la rappresentazione per COLONsempre cambia da :te avrà un incubo di manutenzione.

Offuscazione:

Cosa succede quando qualcuno lo cambia COLON = '-'perché dove lo usano ha bisogno di un -invece ovunque? Scriverai test unitari che dicono sostanzialmente assertThat(':' == COLON)per ogni singolo constriferimento per assicurarti che non vengano modificati? Solo qualcuno deve risolvere il test quando lo cambia?

Se qualcuno sostiene effettivamente che public static final String EMPTY_STRING = "";è utile e benefico, hai appena qualificato le loro conoscenze e ignorato in modo sicuro tutto il resto.

Avere tutti i caratteri stampabili disponibili con una versione con nome dimostra solo che chiunque lo abbia fatto, non è qualificato per scrivere codice senza supervisione.

Coesione:

Riduce anche artificialmente la coesione, perché allontana le cose dalle cose che le usano e sono correlate ad esse.

Nella programmazione informatica, la coesione si riferisce al grado in cui gli elementi di un modulo appartengono insieme. Pertanto, la coesione misura la forza della relazione tra elementi di funzionalità all'interno di un dato modulo. Ad esempio, nei sistemi altamente coesivi la funzionalità è fortemente correlata.

accoppiamento:

Abbina anche molte classi non correlate perché finiscono per fare riferimento a file che non sono realmente correlati a ciò che fanno.

Lo stretto accoppiamento avviene quando un gruppo di classi dipende fortemente l'uno dall'altro. Questo scenario si presenta quando una classe si assume troppe responsabilità o quando una preoccupazione è ripartita su più classi anziché avere una propria classe.

Se avessi usato un nome migliore come DELIMITER = ','quello avresti comunque lo stesso problema, perché il nome è generico e non porta semantico. Riassegnare il valore non aiuta più a fare un'analisi di impatto che cercare e sostituire il valore letterale ','. Perché qual è un codice che lo utilizza e necessita ,dell'utilizzo di un altro codice, ma ;ora è necessario ? Devo ancora guardare ogni uso manualmente e cambiarli.

Nella natura selvaggia:

Di recente ho riformulato una 1,000,000+ LOCdomanda di 18 anni. Aveva cose del genere public static final COMMA = SPACE + "," + SPACE;. Questo non è in alcun modo migliore del solo indicare " , "dove è necessario.

Se vuoi discutere di leggibilità devi imparare a configurare il tuo IDE per visualizzare i whitespacepersonaggi dove puoi vederli o altro, questa è solo una ragione estremamente pigra per introdurre l'entropia in un sistema.

Aveva anche ,definito più volte con più errori di ortografia della parola COMMAin più pacchetti e classi. Con riferimenti a tutte le varianti mescolate insieme nel codice. È stato a dir poco un incubo provare a riparare qualcosa senza rompere qualcosa di completamente estraneo.

Stessa cosa con l'alfabeto, ci sono stati molteplici UPPER_CASE_A, A, UPPER_A, A_UPPERche la maggior parte del tempo sono stati pari a A ma in alcuni casi non erano . Per quasi tutti i personaggi, ma non per tutti i personaggi.

E dalle storie di modifica non sembrava che uno solo di questi fosse mai stato modificato o cambiato nel corso dei 18 anni, a causa di ciò che ora dovrebbe essere la ragione ovvia è che spezzerebbe troppe cose che non erano rintracciabili, quindi hai una nuova variabile nomi che indicano la stessa cosa che non possono mai essere cambiati per lo stesso motivo.

In nessuna realtà sana puoi sostenere che questa pratica non sta facendo altro che iniziare alla massima entropia.

Ho riformulato tutta questa confusione e sottolineato tutte le tautologie e le nuove assunzioni del college erano molto più produttive perché non dovevano dare la caccia attraverso più livelli di constriferimento indiretto a ciò che effettivamente indicavano questi riferimenti, perché non erano affidabili in come erano chiamati vs ciò che contenevano.


112
Forse dovresti aggiungere un controesempio: const char DELIMITER = ':'sarebbe effettivamente utile.
Bergi,

115
Vorrei fare diverse argomentazioni EMPTY_STRINGutili. (1) Posso trovare molto più facilmente tutti gli usi di EMPTY_STRINGin un file di quanti ne possa trovare tutti gli usi "". (2) quando vedo EMPTY_STRINGlo so per certo che lo sviluppatore intendeva che quella stringa fosse vuota e che non fosse una modifica errata o un segnaposto per una stringa da fornire in seguito. Ora, affermi che da parte mia argomentando che potresti qualificare la mia conoscenza e ignorarmi in modo sicuro per sempre. Quindi, come si qualificano le mie conoscenze? E hai intenzione di ignorare il mio consiglio per sempre? Non ho nessun problema in entrambi i casi.
Eric Lippert,

39
@immibis: possiamo smettere di pensare a queste cose come utili nel contesto della gestione del cambiamento. Sono costanti. Non cambiano. Considerali utili nel contesto della ricerca e della comprensione della semantica del codice da parte degli umani . Sapere che qualcosa è un delimitatore chiave-valore-coppia è molto più utile che sapere che sono due punti; questo è un dato di fatto relativo al dominio semantico delle preoccupazioni del programma, non alla sua sintassi .
Eric Lippert,

15
@EricLippert: sto vedendo il punto degli altri qui che sottolineano che l'unica garanzia che un constfornisce è che non cambierà in fase di esecuzione (dopo la compilazione), anche se concordo con te sul fatto che il significato semantico di constè molto più importante del suo utilizzo come strumento di gestione delle modifiche. Detto questo, posso certamente immaginare una const EARLIEST_OS_SUPPORTEDnon solo semanticamente coerente, ma cambierà anche nel tempo man mano che il programma si evolve e la vecchia rotta viene rimossa.
Robert Harvey,

16
@DanielJour: Quindi questo è un terzo argomento per EMPTY_STRING; che un IDE ben progettato presenterà strumenti che mi permettono di trattare questa entità in modo simbolico, piuttosto che sintattico. Generalizzare questo con un quarto argomento: che la libreria di strumenti di analisi del codice che si trova sotto l'IDE può consentire un'analisi programmatica avanzata della correttezza del codice a livello simbolico . Uno sviluppatore che desidera trarre vantaggio da strumenti più avanzati di quelli scritti letteralmente 40 anni fa deve solo apportare piccole modifiche alle proprie abitudini per raccogliere i frutti degli strumenti avanzati.
Eric Lippert,

145

L'appello principale dell'uso delle costanti è che minimizzano la manutenzione quando è necessaria una modifica.

ASSOLUTAMENTE NO. Questo non è affatto il motivo per usare le costanti perché le costanti non cambiano per definizione . Se una costante cambia mai, allora non era una costante, vero?

L'appello all'utilizzo delle costanti non ha nulla a che fare con la gestione del cambiamento e tutto ciò che ha a che fare con la possibilità di scrivere, comprendere e mantenere i programmi . Se voglio sapere ovunque nel mio programma dove vengono utilizzati i due punti come separatore di URL, allora posso saperlo molto facilmente se ho la disciplina per definire un URLSeparator costante e non posso sapere così facilmente se devo fare una richiesta per :e ottenere ogni singola posizione nel codice in cui :viene utilizzato per indicare una classe di base, un ?:operatore o qualsiasi altra cosa.

Non sono pienamente d'accordo con le altre risposte che affermano che si tratta di una inutile perdita di tempo. Le costanti nominate aggiungono significato a un programma e tali semantiche possono essere utilizzate sia dagli umani che dalle macchine per comprendere un programma più profondamente e mantenerlo in modo più efficace.

Il trucco qui non è quello di evitare le costanti, ma piuttosto di nominarle con le loro proprietà semantiche piuttosto che con le loro proprietà sintattiche . A cosa serve la costante? Non chiamarlo a Commameno che il dominio commerciale del tuo programma non sia tipografia, analisi della lingua inglese o simili. Chiamalo ListSeparatoro qualcosa del genere, per chiarire la semantica della cosa.


42
Mentre sono d'accordo con lo spirito di ciò che stai dicendo qui, la tua seconda / terza frase non sono davvero corrette. Una costante può cambiare tra le versioni di un file. In effetti, la maggior parte dei programmi che scrivo hanno una costante con un nome simile MY_VER, che contiene il numero di versione corrente del programma, che può quindi essere utilizzato per tutto il resto del programma piuttosto che una stringa magica come "5.03.427.0038". Il vantaggio aggiunto è come dici tu che ha fornito informazioni semantiche.
Monty Harder,

50
Per essere onesti, il punto di una costante è che non cambia durante il runtime dopo essere stato inizializzato, non che non cambi tra le compilazioni. Dal punto di vista di un compilatore, il punto è che il compilatore può fare ipotesi che il programma non è in grado di modificarlo; se il programmatore è autorizzato a modificarlo quando si ricompila non cambia la sua costanza. Ci possono anche essere casi in cui il software prende un valore di sola lettura dall'hardware, magari dereferenziando un const volatile T*puntatore a un indirizzo predeterminato; mentre il programma non può cambiarlo, l'hardware può farlo.
Justin Time,

6
@MontyHarder: buon punto. La mia opinione è informata dal fatto che in genere utilizzo linguaggi che distinguono tra costanti - che devono essere per sempre immutabili - e variabili che possono essere assegnate una volta - che possono cambiare da versione a versione, da corsa a corsa o altro. Una costante e una variabile sono cose diverse; uno rimane uguale e uno varia nel tempo.
Eric Lippert,

7
@SteveCox: sono d'accordo; il modo in cui C / C ++ caratterizza "const" è strano e di uso limitato. La proprietà che desidero delle costanti è che i loro valori non cambiano, non che io sia limitato a cambiarli in alcune funzioni ma non in altre.
Eric Lippert,

15
"Questo non è affatto il motivo per usare le costanti perché le costanti non cambiano per definizione. Se una costante cambia, allora non era una costante, vero?" Cambiare le costanti in fase di compilazione (ovviamente non in fase di esecuzione) è perfettamente normale. Ecco perché in primo luogo li hai resi una "cosa" chiaramente etichettata. Naturalmente, le costanti del PO sono spazzatura, ma pensare a qualcosa di simile const VERSION='3.1.2'o di const KEYSIZE=1024o qualsiasi altra cosa.
AnoE

61

No, è stupido.

Ciò che non è necessariamente stupido è trascinare cose del genere in etichette nominate per motivi di localizzazione. Ad esempio, il delimitatore delle migliaia è una virgola in America (1.000.000), ma non una virgola in altre lingue. Tirandolo in un'etichetta denominata (con un nome appropriato, non virgola), il programmatore può ignorare / astrarre quei dettagli.

Ma fare una costante perché "le stringhe magiche sono cattive" è solo un culto del carico.


8
La localizzazione di solito è più complicata delle sole costanti di stringa. Ad esempio, alcune lingue desiderano il delimitatore di elenco tra tutti gli elementi dell'elenco, mentre altri escludono il delimitatore prima dell'ultimo elemento. Quindi, di solito non sono necessarie costanti localizzate, ma regole localizzate .
Vlad

19
In realtà il delimitatore delle migliaia non è necessariamente un delimitatore delle migliaia in altre località (Cina / Giappone). Non è nemmeno impostato dopo un numero costante di cifre (India). Oh, e potrebbero esserci delimitatori diversi a seconda che si tratti di un delimitatore 1000 o del delimitatore 1000000 (Messico). Ma questo è meno un problema che non usare le cifre ASCII 0-9 in alcune localizzazioni (farsi). ux.stackexchange.com/questions/23667/…
Peter

1
La localizzazione di @Vlad è molto più complessa di così, tuttavia, il separatore delle migliaia è un esempio ben noto che la gente riconosce.

Dipende dalla strategia di localizzazione ... cambi tutte le costanti nel tuo programma per tradurlo? O dovresti piuttosto leggere i valori da un file (o altro archivio dati), rendendoli effettivamente variabili di runtime?
Paŭlo Ebermann,

Quindi non sarebbe affatto utile come costante. Il programma dovrebbe essere ricompilato per le versioni locali, il che è una pratica terribile. Dovrebbero essere variabili caricate dai file di definizione e cercate secondo necessità. Non che non sia d'accordo con il punto (ho votato a favore della risposta), ma prenderei una posizione più difficile sulla questione.

29

Ci sono alcuni personaggi che possono essere ambigui o utilizzati per diversi scopi. Ad esempio, usiamo '-'come un trattino, un segno meno o anche un trattino. Puoi creare nomi separati come:

static const wchar_t HYPHEN = '-';
static const wchar_t MINUS = '-';
static const wchar_t EM_DASH = '-';

Successivamente, puoi scegliere di modificare il codice per chiarire le ambiguità ridefinendole come:

static const wchar_t HYPHEN = '-';
static const wchar_t MINUS = '\u2122';
static const wchar_t EM_DASH = '\u2014';

Questo potrebbe essere un motivo per cui prendere in considerazione la definizione di costanti per determinati singoli caratteri. Tuttavia , il numero di personaggi ambigui in questo modo è piccolo. Al massimo, sembra che lo faresti solo per quelli. Direi anche che potresti aspettare fino a quando non avrai effettivamente bisogno di distinguere i caratteri ambigui prima di considerare il codice in questo modo.

Poiché le convenzioni tipografiche possono variare in base alla lingua e alla regione, probabilmente è meglio caricare una punteggiatura così ambigua da una tabella di traduzione.


Per me questa è l'unica ragione valida per cui si potrebbero creare costanti di caratteri
FP

2
L'uso -come trattino di em è abbastanza fuorviante ... è molto breve per quello nella maggior parte dei caratteri. (È anche più corto di un trattino.)
Paŭlo Ebermann,

OK, non il miglior esempio. Ho iniziato con strings piuttosto wchar_ts e ho usato la convenzione standard del manoscritto "--"per il trattino. Ma l'esempio originale stava usando singoli caratteri, quindi sono passato alla verità. Ci sono persone che -scrivono per trattini, specialmente quando si lavora con un carattere a passo fisso.
Adrian McCarthy,

1
@ PaŭloEbermann No, tradizionalmente un trattino è la larghezza del carattere "m" di un carattere e un trattino è la larghezza di un carattere "n".
Dizzley,

@Dizzley sì, e trattino-larghezza <n-larghezza <m-larghezza.
Paŭlo Ebermann,

22

Una costante deve aggiungere significato.

Definire COMMA come virgola non aggiunge significato, perché sappiamo che una virgola è una virgola. Invece distruggiamo il significato, perché ora COMMA potrebbe in realtà non essere più una virgola.

Se si utilizza una virgola per uno scopo e si desidera utilizzare una costante con nome, denominarla in base allo scopo. Esempio:

  • city + CharacterClass.COMMA + state = cattivo
  • city + CITY_STATE_DELIMITER + state = buono

Utilizzare le funzioni per la formattazione

Personalmente preferisco FormatCityState(city, state)e non mi preoccupo di come il corpo di quella funzione appare fintanto che è corto e supera i casi di test.


1
Ah, ma una virgola non è sempre la stessa virgola. Potrei definire COMMA = '\ u0559' o '\ u060C' ecc. (Vedi Unicode) o persino trasformarlo in una variabile in un secondo momento e leggerlo da un file di configurazione. In questo modo, avrà ancora lo stesso significato , ma solo un valore diverso. Che ne dici di quello.
Mr Lister,

2
@MrLister: YAGNI. Se ne hai bisogno: fantastico! Hai una soluzione eccellente. Ma se non lo fai, non ingombrare il codice perché forse un giorno potresti farlo. Inoltre, nella mia esperienza se provi a introdurre astrazioni senza alcuna funzione nella tua base di codice, le persone non sono brave a essere coerenti. Quindi, anche se hai definito COMMA con l'intento di utilizzare qualche altro punto di codice, in un programma di dimensioni ed età sufficienti in modo tale che la scelta sia importante, è probabile che la costante non sia stata usata ovunque avrebbe dovuto stato (e viceversa, potrebbe essere stato usato anche in modo inappropriato).
Eamon Nerbonne,

17

L'idea che una COMMA costante sia migliore ','o ","piuttosto semplice da sfatare. Certo, ci sono casi in cui ha senso, ad esempio facendo final String QUOTE = "\"";un grosso risparmio sulla leggibilità senza tutte le barre, ma escludendo caratteri di controllo del linguaggio come \ 'e "non li ho trovati molto utili.

L'uso final String COMMA = ","non è solo una cattiva forma, è pericoloso! Quando qualcuno vuole cambiare il separatore da ","in ";"potrebbe andare a cambiare il file delle costanti in COMMA = ";"perché è più veloce per loro farlo e funziona. Tranne, sai, tutte le altre cose che hanno usato COMMA ora sono anche punti e virgola, comprese le cose inviate a consumatori esterni. Quindi supera tutti i test (poiché anche tutto il codice di marshalling e unmarshalling utilizzava COMMA) ma i test esterni falliranno.

Ciò che è utile è dare loro nomi utili. E sì, a volte più costanti avranno gli stessi contenuti ma nomi diversi. Per esempio final String LIST_SEPARATOR = ",".

Quindi la tua domanda è "le costanti a carattere singolo sono migliori dei letterali" e la risposta è inequivocabilmente no, non lo sono. Ma anche meglio di entrambi è un nome variabile con ambito ristretto che dice esplicitamente quale sia il suo scopo. Certo, spenderai qualche byte in più su quei riferimenti extra (supponendo che non vengano compilati su di te, cosa che probabilmente faranno) ma nella manutenzione a lungo termine, che è dove si trova la maggior parte del costo di un'applicazione, loro valgono il tempo di fare.


Che ne dite di definire condizionalmente DISP_APOSTROPHE come un carattere ASCII 0x27 o un carattere di virgoletta a destra singola Unicode (che è una rappresentazione più tipograficamente appropriata di un apostrofo), a seconda della piattaforma di destinazione?
supercat,

3
in realtà, l' QUOTEesempio dimostra che è una cattiva idea, dal momento che la si sta assegnando a ciò che è generalmente / popolarmente noto come DOUBLE QUOTEe QUOTEimplica SINGLE_QUOTEche è più correttamente indicato come APOSTROPHE.

3
@JarrodRoberson Non credo che la citazione implichi una singola citazione, personalmente - ma questa è un'altra buona ragione per rimuovere l'ambiguità dove puoi!
corsiKa

2
Non mi piace l' QUOTEesempio per un motivo aggiuntivo: rende ancora più difficile la lettura di stringhe costruite con esso, "Hello, my name is " + QUOTE + "My Name" + QUOTEquesto è un esempio banale e tuttavia sembra ancora brutto. Oh, certo, invece di concatenare puoi usare i token di sostituzione, "Hello, my name is %sMy Name%s".format(QUOTE, QUOTE)potrebbe anche essere peggio. Ma, ehi, proviamo i token indicizzati "Hello, my name is {0}My Name{0}".format(QUOTE)ugh, non molto meglio. Qualsiasi stringa non banale generata con virgolette in essa sarebbe anche peggio.
VLAZ,

2
@corsiKa - Vivrò con le virgolette effettive evase. Se manco di scapparne uno, l'IDE che uso si lamenterebbe immediatamente. Molto probabilmente neanche il codice verrà compilato. È abbastanza facile da individuare. Quanto è facile fare un errore quando lo faccio, "My name is" + QUOTE + "My Name" + QUOTEho effettivamente fatto lo stesso errore tre volte scrivendo il commento sopra. Riesci a individuarlo? Se ti ci vuole un po ', è lo spazio mancante dopo è . Formattate la stringa? In tal caso, una stringa con più token da sostituire sarà ancora peggio da risolvere. Come posso usarlo in modo che sia più leggibile?
VLAZ,

3

Ho fatto un po 'di lavoro scrivendo lexer e parser e ho usato costanti intere per rappresentare terminali. I terminali a carattere singolo avevano il codice ASCII come valore numerico per semplicità, ma il codice avrebbe potuto essere qualcos'altro. Quindi, avrei un T_COMMA a cui è stato assegnato il codice ASCII per ',' come valore costante. Tuttavia, c'erano anche costanti per i non terminali a cui erano assegnati numeri interi sopra l'insieme ASCII. Osservando i generatori di parser come yacc o bison o i parser scritti usando questi strumenti, ho avuto l'impressione che in pratica lo facessero tutti.

Quindi, mentre, come tutti gli altri, penso che sia inutile definire costanti allo scopo esplicito di usare le costanti anziché i letterali in tutto il codice, penso che ci siano casi limite (parser, diciamo) in cui potresti incontrare codice pieno di costanti come le descrivi. Si noti che nel caso del parser, le costanti non sono solo lì per rappresentare i caratteri letterali; rappresentano entità che potrebbero capitare di essere letterali dei personaggi.

Mi viene in mente qualche altro caso isolato in cui potrebbe avere senso usare le costanti invece dei corrispondenti letterali. Ad esempio, potresti definire NEWLINE come letterale '\ n' su una casella unix, ma '\ r \ n' o '\ n \ r' se sei su windows o mac box. Lo stesso vale per l'analisi dei file che rappresentano dati tabulari; potresti definire le costanti FIELDSEPARATOR e RECORDSEPARATOR. In questi casi, in realtà stai definendo una costante per rappresentare un personaggio che svolge una determinata funzione. Tuttavia, se tu fossi un programmatore alle prime armi, forse potresti nominare la costante COMMA del tuo separatore di campo, non rendendoti conto che avresti dovuto chiamarlo FIELDSEPARATOR, e quando ti rendessi conto, il codice sarebbe in produzione e saresti il ​​prossimo progetto,

Infine, la pratica che descrivi potrebbe avere senso in alcuni casi in cui scrivi codice per gestire i dati codificati in una specifica codifica dei caratteri, ad esempio iso-8859-1, ma ti aspetti che la codifica cambi in seguito. Naturalmente in tal caso sarebbe molto più sensato utilizzare la localizzazione o la codifica e la decodifica delle librerie per gestirla, ma se per qualche motivo non fosse possibile utilizzare una libreria di questo tipo per gestire i problemi di codifica per te, usando le costanti avresti solo dover ridefinire in un unico file invece di letterali hardcoded disseminati in tutto il codice sorgente potrebbe essere una strada da percorrere.

Per quanto riguarda l'articolo a cui ti sei collegato: non credo che provi a fare un caso per sostituire i letterali dei personaggi con costanti. Penso che stia cercando di illustrare un metodo per utilizzare le interfacce per estrarre le costanti in altre parti della tua base di codice. Le costanti di esempio usate per illustrare questo sono scelte molto male, ma non credo che contino in alcun modo.


2
Penso che stia cercando di illustrare un metodo per utilizzare le interfacce per estrarre le costanti in altre parti della tua base di codice. che è un anti-pattern ancora peggiore e che è strettamente accoppiato e anche a bassa coesione, non c'è motivo valido neanche per farlo.

3

Oltre a tutte le belle risposte qui, vorrei aggiungere come spunto di riflessione, che una buona programmazione consiste nel fornire astrazioni appropriate che possono essere costruite su di te e forse su altri, senza dover ripetere lo stesso codice più volte.

Le buone astrazioni rendono il codice facile da usare da un lato e facile da mantenere dall'altro.

Sono totalmente d'accordo sul fatto DELIMITER=':'che di per sé è una cattiva astrazione, e solo meglio di COLON=':'(poiché quest'ultimo è totalmente impoverito).

Una buona astrazione che coinvolge stringhe e separatori includerebbe un modo per impacchettare uno o più singoli elementi di contenuto nella stringa e per decomprimerli anche dalla stringa compressa, prima di tutto, prima di dirti qual è il delimitatore. Tale astrazione sarebbe raggruppata come un concetto, nella maggior parte delle lingue come una classe; ad esempio, in modo che il suo utilizzo sia praticamente autocompattante, in quanto è possibile cercare tutti i luoghi in cui viene utilizzata questa classe ed essere sicuri di quale sia l'intenzione del programmatore in merito al formato delle stringhe impaccate in ogni caso in cui viene utilizzata qualche astrazione.

Una volta che un tale astrazione è prevista, sarebbe facile da usare, senza mai dover consultare quale il valore del DELIMITERo COLONè, e, cambiando i dettagli di implementazione sarà generalmente limitato alla realizzazione. Quindi, in breve, queste costanti dovrebbero davvero essere dettagli di implementazione nascosti all'interno di un'astrazione appropriata.

L'appello principale dell'uso delle costanti è che minimizzano la manutenzione quando è necessaria una modifica.

Le buone astrazioni, che sono in genere composizioni di diverse capacità correlate, sono migliori nel ridurre al minimo la manutenzione. Innanzitutto, separano chiaramente il fornitore dai consumatori. In secondo luogo, nascondono i dettagli di implementazione e forniscono invece funzionalità direttamente utili. In terzo luogo, documentano ad alto livello quando e dove vengono utilizzati.


2

L'unica volta che ho visto tali costanti utilizzate in modo efficace è abbinare un'API o un documento esistente. Ho visto simboli come quelli COMMAusati perché un particolare software era direttamente collegato a un parser che usava COMMAcome tag in un albero di sintassi astratto. Ho anche visto che corrispondeva a una specifica formale. nelle specifiche formali, a volte vedrai simboli simili COMMApiuttosto che ','perché vogliono essere il più chiaro possibile.

In entrambi i casi, l'uso di un simbolo con nome simile COMMAaiuta a fornire coesione a un prodotto altrimenti disgiunto. Tale valore può spesso superare il costo di notazioni eccessivamente dettagliate.


2

Osserva che stai cercando di creare un elenco.

Quindi, refactural come: String makeList(String[] items)

In altre parole, estrapolare la logica anziché i dati .
Le lingue potrebbero essere diverse nel modo in cui rappresentano gli elenchi, ma le virgole sono sempre virgole (è una tautologia). Quindi, se la lingua cambia, cambiare il carattere virgola non ti aiuterà - ma questo lo farà.


0

Se questa era una classe scritta come parte di un'applicazione dai tuoi colleghi sviluppatori, questa è quasi sicuramente una cattiva idea. Come altri hanno già sottolineato, ha senso definire costanti come SEPARATOR = ','dove è possibile modificare il valore e la costante ha ancora senso ma molto meno costanti il ​​cui nome descrive solo il loro valore.

Tuttavia, ci sono almeno due casi in cui ha senso dichiarare costanti il ​​cui nome descrive esattamente il loro contenuto e in cui non è possibile modificare il valore senza modificare in modo appropriato il nome della costante:

  • Costanti matematiche o fisiche, ad es PI = 3.14159. Qui, il ruolo della costante è di agire come un mnemonico poiché il nome simbolico PIè molto più breve e più leggibile del valore che rappresenta.
  • Elenchi esaustivi di simboli in un parser o tasti su una tastiera. Potrebbe anche avere senso avere un elenco di costanti con la maggior parte o tutti i caratteri Unicode ed è qui che potrebbe cadere il tuo caso. Alcuni personaggi come Asono ovvi e chiaramente riconoscibili. Ma puoi dirlo facilmente Аe a Aparte? Il primo è il cirillico lettera А mentre il secondo è latino lettera A . Sono lettere diverse, rappresentate da diversi punti di codice Unicode, anche se graficamente sono quasi identiche. Preferirei avere costanti CYRILLIC_CAPITAL_AeLATIN_CAPITAL_Anel mio codice di due caratteri quasi identici. Naturalmente, questo è inutile se sai che lavorerai solo con caratteri ASCII che non contengono cirillico. Allo stesso modo: uso quotidianamente l'alfabeto latino, quindi se stessi scrivendo un programma che aveva bisogno di un carattere cinese, probabilmente preferirei usare una costante piuttosto che inserire un carattere che non capisco. Per chi usa quotidianamente i caratteri cinesi, un carattere cinese può essere ovvio, ma uno latino può essere più facile da rappresentare come costante con nome. Quindi, come vedi, dipende dal contesto. Tuttavia, una libreria potrebbe contenere costanti simboliche per tutti i personaggi poiché gli autori non possono sapere in anticipo come verrà utilizzata la libreria e quali caratteri potrebbero aver bisogno di costanti per migliorare la leggibilità in un'applicazione specifica.

Tuttavia, tali casi sono generalmente gestiti da classi di sistema o librerie per scopi speciali e la loro occorrenza nel codice scritto dagli sviluppatori di applicazioni dovrebbe essere molto rara a meno che non si stia lavorando a qualche progetto molto speciale.


-1

Può essere.

Le costanti a carattere singolo sono relativamente difficili da distinguere. Quindi può essere piuttosto facile perdere il fatto che stai aggiungendo un punto anziché una virgola

city + '.' + state

mentre questo è un errore relativamente difficile da affrontare

city + Const.PERIOD + state

A seconda dell'ambiente di internazionalizzazione e globalizzazione, la differenza tra un apostrofo ASCII e l'apostrofo apri e chiudi Windows-1252 (o la virgoletta doppia ASCII e la virgoletta doppia apri e chiudi Windows-1252) può essere significativa ed è notoriamente difficile da visualizzare. al codice.

Ora, presumibilmente, se inserire erroneamente un punto anziché una virgola fosse un problema funzionale significativo, avresti un test automatico che troverebbe l'errore di battitura. Se il tuo software sta generando file CSV, mi aspetto che la tua suite di test scoprirà abbastanza rapidamente che hai avuto un periodo tra la città e lo stato. Se il tuo software dovrebbe essere eseguito per client con una varietà di configurazioni di internazionalizzazione, presumibilmente la tua suite di test verrà eseguita in ogni ambiente e prenderà se hai un preventivo Microsoft open se intendevi avere un apostrofo.

Potrei immaginare un progetto in cui ha più senso optare per un codice più dettagliato che potrebbe risolvere questi problemi in particolare quando hai un codice più vecchio che non ha una suite di test completa anche se probabilmente non scriverei in questo modo un progetto di sviluppo del campo verde. E l'aggiunta di una costante per ogni carattere di punteggiatura piuttosto che solo quelli potenzialmente problematici nella tua particolare applicazione è probabilmente un eccesso eccessivo.


2
cosa succede quando un deficiente cambia Const.PERIODin modo che sia uguale ~? Non vi è alcuna giustificazione per una tautologia di personaggi nominati, aggiunge semplicemente la manutenzione e la complessità che è necessaria negli ambienti di programmazione moderni. Hai intenzione di scrivere una serie di test unitari che sostanzialmente dicono assert(Const.PERIOD == '.')?

3
@JarrodRoberson - Sarebbe bello, certo. Ma avresti altrettanto problemi se qualcuno aggiungesse una costante Unicode che assomiglia quasi esattamente a una virgola piuttosto che a una virgola reale. Come ho detto, questo non è il genere di cose che farei in un progetto di sviluppo greenfield. Ma se hai una base di codice legacy con una suite di test spotty in cui hai inciampato nella virgola / punto o apostrofo / problemi di apostrofi di abominio Microsoft un paio di volte, creare alcune costanti e dire alle persone di usarle può essere un modo ragionevole per fare il codice migliore senza passare un anno a scrivere test.
Justin Cave,

3
il tuo esempio legacy è scadente, ho appena finito di refactoring una base di codice LOC 1.000.000+ che ha 18 anni. Aveva ogni carattere stampabile definito in questo modo più volte, anche con nomi contrastanti diversi. E molte volte le cose nominate COMMAerano effettivamente impostate = SPACE + "," + SPACE. Sì, qualche idiota aveva una SPACEcostante. Li ho rifattorizzati TUTTI e il codice era ordini di grandezza più leggibili e le assunzioni del college erano molto più in grado di rintracciare le cose e risolverle senza avere 6 livelli di riferimento indiretto per scoprire a cosa era effettivamente impostato qualcosa.

-1

Le costanti a carattere singolo sono migliori dei letterali?

Ci sono molte confusioni galleggianti qui intorno. Fammi vedere se riesco a stuzzicarli.

Le costanti forniscono:

  • semantica
  • cambiamento, durante lo sviluppo
  • indirezione

Scendere al nome di un singolo personaggio influisce solo sulla semantica. Un nome dovrebbe essere utile come commento e chiaro nel contesto. Dovrebbe esprimere significato, non valore. Se riesce a fare tutto questo con un singolo carattere, va bene. Se non è possibile, per favore non farlo.

Un letterale e una costante possono cambiare durante lo sviluppo. Questo è ciò che solleva il problema del numero magico. Anche le stringhe possono essere numeri magici.

Se esiste un significato semantico e poiché entrambi sono costanti, allora se la costante ha più valore di un valore letterale si riduce all'indirizzamento.

L'indirizzamento può risolvere qualsiasi problema, oltre a quello indiretto.

L'indirizzamento può risolvere il problema del numero magico perché ti consente di decidere un valore per un'idea in un unico posto. Semanticamente, affinché ciò valga la pena, il nome deve rendere chiara l'idea. Il nome dovrebbe riguardare l'idea, non il valore.

L'indirizzamento può essere esagerato. Alcuni preferiscono cercare e sostituire i letterali per apportare le loro modifiche. Va bene finché 42 è chiaramente il significato della vita e non mescolato con 42, il numero atomico di molibdeno.

Se puoi fare utili distinzioni come questa con una sola lettera dipende in gran parte dal contesto. Ma non avrei preso l'abitudine.


1
Semantica è la chiave. Se e "A" ha più semantica che semplicemente essere una "A", allora vale la pena associare lo stesso semantico allo stesso "riferimento". Non importa se è una costante o no. Sono totalmente d'accordo.
oopexpert,

-1

Come contrappunto filosofico all'opinione della maggioranza, devo affermare che ci sono alcuni di noi, che apprezzano il programmatore contadino francese del XIX secolo non sofisticato e

ricordava la sua monotona lucidità eterna, le sue visioni incredibilmente sensibili di tutto, la sua colossale contentezza con i truismi semplicemente perché erano veri. "Confuso tutto!" gridò Turnbull a se stesso, "se è nel manicomio, non ci può essere nessuno fuori".

GK Chesterton, The Ball and The Cross

Non c'è nulla di sbagliato nell'apprezzare la verità e non c'è nulla di sbagliato nell'affermare la verità, specialmente quando si parla al computer.

Se menti al computer, ti prenderà

Perry Farrar - Germantown, Maryland (da More Programming Pearls)


Ma, per la maggior parte, sono d'accordo con le persone che dicono che è stupido. Sono troppo giovane per aver imparato a programmare FORTRAN, ma ho sentito dire che potresti ridefinire 'A' = 'Q'e inventare ogni sorta di meravigliosi crittogrammi. Non lo stai facendo.

Al di là dei problemi di i18n sollevati in precedenza (che non stanno ridefinendo il glifo "COMMA", ma ridefinendo veramente il glifo di un DECIMAL_POINT). Costruire citazioni carotiche francesi o virgolette singole britanniche per trasmettere significato agli umani è una cosa e quelli dovrebbero essere davvero variabili, non costanti. La costante sarebbe AMERICAN_COMMA := ','e ilcomma := AMERICAN_COMMA

E, se stavo usando un modello builder per costruire una query SQL, preferirei vedere

sb.append("insert into ")
 .append(table_name)
 .append(" values ")
 .append(" ( ")
 .append(val_1)
 .append(",")
 .append(val_2)
 .append(" ); ")

di ogni altra cosa, ma se avessi intenzione di aggiungere costanti, lo sarebbe

INSERT_VALUES_START = " ( "
INSERT_VALUES_END = " ) "
INSERT_VALUES_SEPARATOR = " , "
QUERY_TERMINATOR = ";"

sb.append("insert into ")
 .append(table_name)
 .append(" values ")
 .append(INSERT_VALUES_START)
 .append(val_1)
 .append(INSERT_VALUES_SEPARATOR)
 .append(val_2)
 .append(INSERT_VALUES_END)
 .append(QUERY_TERMINATOR)

Tuttavia, se hai mai visto qualcun altro programma (o tipo) potresti notare alcune stranezze interessanti. Non tutti noi siamo dattilografi stellari. Molti di noi sono entrati in programmazione tardi o sono stati cresciuti con tastiere sovietiche (dove i tasti digitano su di te) e ci piace tagliare e incollare singole lettere invece di cercare di trovarle sulla tastiera e / o fare affidamento sul completamento automatico.

Niente completerà automaticamente una stringa per te, quindi se posso ottenere una virgola premendo 'con', alt-spazio, giù, giù, giù, inserisci e ottieni un preventivo premendo 'con', alt-spazio, giù, giù, entra. Potrei farlo.


Un'altra cosa da ricordare sui letterali stringa è il modo in cui sono compilati. Almeno in Delphi, (che è l'unica lingua che ho ossessionato dalla pila di), finirai con i letterali spuntati nella pila di ogni funzione. Quindi, molti letterali = molte funzioni generali; "," in function_A non è lo stesso bit di memoria di un "," in function_B ". Per combattere questo, c'è una" stringa di risorse "che può essere costruita e collegata lateralmente - ed è così che fanno i18n cose (uccidendo due uccelli con un solo cespuglio) In Python tutti i letterali delle stringhe sono oggetti e potrebbe effettivamente sembrare piacevole da usare utils.constants.COMMA.join(["some","happy","array","strings"]), ma non è un'idea stellare per i punti ripetuti più e più volte in questa pagina.


-4

Ma quando inizieremo a utilizzare un simbolo diverso da "," per rappresentare una virgola?

Per la localizzazione.

Nei paesi di lingua inglese, il simbolo che separa le parti intere e frazionarie di un decimale è ".", Che chiamiamo "punto decimale". In molti altri paesi, il simbolo è "," ed è in genere chiamato l'equivalente di "virgola" nella lingua locale. Allo stesso modo, dove i paesi di lingua inglese usano "," per separare gruppi di tre cifre in grandi numeri (come 1.000.000 per un milione), i paesi che usano una virgola come punto decimale utilizzano un punto (1.000.000).

Quindi c'è un caso per rendere costanti DECIMAL_POINT e COMMA se si sta eseguendo la globalizzazione.


2
Ma poi COMMA e DECIMAL_POINT non sono i nomi corretti per le entità (motivo per cui probabilmente sei stato sottoposto a downgrade).
Kyle Strand,

Dovresti compilare specifiche versioni localizzate. Le costanti letterali non sono adatte a questo; quel caso d'uso richiederebbe i file di definizione e le ricerche al loro interno (che potrebbero coinvolgere costanti, ma costanti di ricerca, non caratteri costanti).
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.