17 Domanda: Abuso costante?

domanda creata a Mon, Dec 7, 2009 12:00 AM

Ho incontrato un sacco di codice in alcuni progetti C # che hanno le seguenti costanti:

 
    const int ZERO_RECORDS = 0;
    const int FIRST_ROW = 0;
    const int DEFAULT_INDEX = 0;
    const int STRINGS_ARE_EQUAL = 0;

Qualcuno ha mai visto qualcosa di simile? C'è un modo per razionalizzare l'uso delle costanti per rappresentare i costrutti del linguaggio? IE: Il primo indice di C # in un array è in posizione 0. Penso che se uno sviluppatore deve dipendere da una costante per dire che la lingua è basata su 0, c'è un problema più grande a portata di mano.

L'utilizzo più comune di queste costanti è nella gestione delle tabelle dati o all'interno di cicli "for".

Sono fuori luogo pensando che si tratti di un odore di codice? Sento che questi non sono molto meglio di:

 
const int ZERO = 0;
const string A = "A";
    
19
  1. loro sono meglio! il secondo nel tuo esempio non verrà compilato;) a parte questo, no, anche i primi quattro esempi sembrano piuttosto ridondanti
    2009-12-07 20: 18: 03Z
  2. corretto il refuso, grazie
    2009-12-07 20: 23: 57Z
  3. Come nota a margine, vale sempre la pena tenere a mente che value di un campo const è parte dell'interfaccia pubblica del tuo assembly, e cambiarlo è probabile che sia un cambiamento a livello di binario (dato che tutti gli assembly esistenti compilati rispetto alla vecchia versione useranno il vecchio valore della costante). Nessuna delle costanti elencate qui sembra essere messa in pericolo da questo, ma qualcosa come public const int RECORDS_PER_PAGE=40; è molto probabile che sia, e molto spesso la linea è sfocata.
    2009-12-07 20: 29: 35Z
  4. Questo è un po 'accanto al punto, ma le costanti in C # non dovrebbero essere tutte maiuscole. Vedi irritatedvowel.com/Programming/Standards.aspx , ad esempio.
    2009-12-07 22: 36: 02Z
  5. Provo costante abuso anche sul mio posto di lavoro!
    2009-12-08 01: 25: 10Z
17 risposte                              17                         

Abuso, IMHO. "Zero" è solo una delle basi.

Sebbene il STRINGS_ARE_EQUAL possa essere facile, perché non ".Equaliti"?

Uso limitato consentito dei numeri magici?

    
10
2009-12-07 20: 23: 47Z
  1. Sono d'accordo. Sono tutto per la leggibilità, ma devi aspettarti alcune competenze di base. 1
    2009-12-08 01: 18: 43Z
  

Sono fuori luogo pensando che si tratti di un odore di codice? Sento che questi non sono molto meglio di:

Confronta il seguente:

 
if(str1.CompareTo(str2) == STRINGS_ARE_EQUAL) ...

con

 
if(str1.CompareTo(str2) == ZERO) ...
if(str1.CompareTo(str2) == 0) ...

Quale ha un senso più immediato?

    
12
2009-12-07 20: 34: 46Z
  1. str1.Equals (str2) ha senso: p
    2009-12-07 20: 20: 43Z
  2. Bene, l'ultimo ha più senso per me. I confronti in .NET restituiscono costantemente -N, 0 o N per indicare l'ordine, e se sei un programmatore .NET e don 'So che idioma, dovresti impararlo.
    2009-12-07 20: 25: 25Z
  3. Io uso == invece di .Equaliti per le stringhe. Per la massima leggibilità.
    2009-12-07 20: 26: 31Z
  4. Inoltre, non è solo "in .NET" - è un linguaggio molto vecchio, almeno vecchio come C strcmp, e forse più vecchio. È anche molto usato, compresi i linguaggi di alto livello.
    2009-12-07 20: 27: 15Z
  5. Se usi 0, tutti con qualsiasi esperienza sanno di cosa si tratta. Gli sviluppatori inesperti potrebbero doverli cercare, ma impareranno. Usa STRINGS_ARE_EQUAL e nessuno saprà effettivamente di cosa si tratta. Avranno una buona idea, ma il fatto che qualcosa di strano stia accadendo li farà controllare. I più esperti ricorderanno i momenti in cui sono stati morsi malamente assumendo che una costante fosse ciò che pensavano fosse.
    2009-12-07 20: 42: 39Z

Questo sicuramente un odore di codice.

L'intento potrebbe essere stato quello di "aggiungere leggibilità" al codice, tuttavia cose del genere in realtà riducono la leggibilità del codice a mio parere.

    
5
2009-12-07 20: 18: 47Z
  1. sì, è illeggibile:)
    2009-12-07 20: 20: 25Z

Alcune persone considerano qualsiasi numero grezzo all'interno di un programma come un "numero magico". Ho visto standard di codifica che sostanzialmente dicevano che non si poteva semplicemente scrivere un intero in un programma, doveva essere un const int.

    
5
2009-12-07 20: 21: 06Z
  1. Sì, mi sono imbattuto in questo prima. Lo standard del codice dice "nessun numero magico" e una persona SQA eccessivamente zelante dice che usare 0 è un numero magico. Sto immaginando un programmatore frustrato che li placa con una rapida serie di sacre.
    2009-12-07 20: 24: 10Z
  2. ho visto anche questo. Il fatto è che ci sono sempre delle eccezioni e gli zeri dovrebbero essere un'eccezione alla regola dei numeri magici.
    2009-12-07 20: 28: 23Z
  3. Lo abbiamo fatto in un posto in cui ho lavorato, perché avevamo sviluppatori offshore che erano meno stellari. Era molto più facile far rispettare "tutti i numeri grezzi sono numeri magici" rispetto a qualsiasi altro standard che avremmo potuto ottenere.
    2009-12-07 20: 56: 30Z
  

Sono fuori luogo pensando che si tratti di un odore di codice? Sento che questi non sono molto meglio di:

     

const int ZERO = 0;

     

const int A = 'A';

Probabilmente un po 'di odore, ma decisamente migliore di ZERO = 0 e A =' A '. Nel primo caso stanno definendo delle costanti logiche, ad esempio un'idea astratta (l'uguaglianza delle stringhe) con un'implementazione del valore concreto.

Nel tuo esempio, stai definendo delle costanti letterali - le variabili rappresentano i valori stessi. Se questo è il caso, penso che sia preferibile un'enumerazione poiché raramente sono valori singolari.

    
3
2009-12-07 20: 28: 51Z

Questa è una brutta codifica.

Dico che le costanti dovrebbero essere utilizzate solo dove necessario dove le cose potrebbero cambiare qualche volta dopo. Per esempio, ho un sacco di opzioni di "configurazione" come SESSION_TIMEOUT definite dove dovrebbe rimanere lo stesso, ma forse potrebbe essere ottimizzato più avanti lungo la strada. Non credo che il ZERO possa mai essere ottimizzato.

Inoltre, per i numeri magici zero non dovrebbe essere incluso.

Sono un po 'strano, credo su quella convinzione, anche se direi che qualcosa del genere andrà molto lontano

 
//input is FIELD_xxx where xxx is a number
input.SubString(LENGTH_OF_FIELD_NAME); //cut out the FIELD_ to give us the number
    
3
2009-12-07 20: 53: 14Z

Dovresti dare un'occhiata ad alcune delle cose a thedailywtf

One2Pt20462262185th

e

Enterprise SQL

    
2
2009-12-07 20: 32: 54Z

Penso che a volte le persone seguano ciecamente gli "standard di codifica" che dicono "Non usare valori hardcoded, definirli come costanti in modo che sia più facile gestire il codice quando deve essere aggiornato" - che è abbastanza giusto per cose come:

 
const in MAX_NUMBER_OF_ELEMENTS_I_WILL_ALLOW = 100

Ma non ha senso per:

 
if(str1.CompareTo(str2) == STRINGS_ARE_EQUAL)

Perché ogni volta che vedo questo codice ho bisogno di cercare ciò che STRINGS_ARE_EQUAL è definito come e quindi verificare con i documenti se è corretto.

Invece, se vedo:

 
if(str1.CompareTo(str2) == 0)

Salto il passaggio 1 (cerca ciò che STRINGS_ARE... è definito come) e posso controllare le specifiche per quale valore 0 significa.

Avresti ragionevolmente voglia di sostituire questo con Equals() e usare CompareTo() nei casi in cui sei interessato a più di un solo caso, ad esempio:

 
switch (bla.CompareTo(bla1))
{
     case IS_EQUAL:
     case IS_SMALLER:
     case IS_BIGGER:
     default:
}

utilizzando le dichiarazioni if/else, se appropriato (non si ha idea di cosa restituisce CompareTo() ...)

Continuerò a controllare se hai definito i valori correttamente in base alle specifiche.

Questo è ovviamente diverso se le specifiche definiscono qualcosa come il valore ComparisonClass::StringsAreEqual o qualcosa del genere (l'ho appena fatto) quindi non useresti 0 ma la variabile appropriata.

Quindi dipende, quando hai specificamente bisogno di accedere al primo elemento dell'array arr[0] è meglio del arr[FIRST_ELEMENT] perché andrò comunque a controllare ciò che hai definito come FIRST_ELEMENT perché non mi fido di te e potrebbe essere qualcosa di diverso da 0 - per esempio il tuo elemento 0 è dud e il vero primo elemento è memorizzato in 1 - chissà.

    
2
2009-12-08 01: 19: 21Z

Vado per l'odore del codice. Se questi tipi di costanti sono necessari, inseriscili in un enum:

 
enum StringEquality
{
    Equal,
    NotEqual
}

(Tuttavia, sospetto che il STRINGS_ARE_EQUAL sia ciò che viene restituito da string.Compare, quindi hackerarlo per restituire un enum potrebbe essere ancora più dettagliato.)

Modifica: Anche SHOUTING_CASE non è particolarmente . Convenzione di denominazione in stile NET .

    
1
2009-12-07 20: 20: 22Z
  1. enum casting non segue alcuna convenzione di stile .NET che abbia mai visto.
    2009-12-07 20: 30: 12Z
  2. @ micahtan, da cui la parola 'hack' - non è un suggerimento serio
    2009-12-07 20: 31: 44Z

non so se li chiamerei odori, ma sembrano ridondanti. Sebbene DEFAULT_INDEX potrebbe effettivamente essere utile.

Il punto è evitare i numeri magici e gli zeri non sono davvero magici.

    
1
2009-12-07 20: 20: 49Z
  1. yea default_index potrebbe essere utile se si desidera mantenere la compatibilità in avanti nel caso in cui microsoft passi dall'indicizzazione basata su 0 all'indicizzazione basata su -13 ....
    2009-12-07 20: 55: 57Z
  2. @ Paul, pensavo che fosse una funzionalità in .NET 4.0 - Puoi cambiare la tua base indice nel file di configurazione web /app. :)
    2009-12-07 21: 00: 18Z

Questo codice è qualcosa nel tuo ufficio o qualcosa che hai scaricato?

Se è in ufficio, penso che sia un problema con la gestione se le persone posizionano le costanti in modo casuale. Globalmente, non ci dovrebbero essere costanti a meno che tutti abbiano un'idea chiara o un accordo su ciò per cui sono usate queste costanti.

In C # idealmente vorresti creare una classe che contenga costanti che vengono usate globalmente da ogni altra classe. Ad esempio,

 
class MathConstants
{
 public const int ZERO=0;
}

Quindi nelle classi successive qualcosa come:

 
....
if(something==MathConstants.ZERO)
...

Almeno è così che lo vedo. In questo modo tutti possono capire cosa sono quelle costanti senza nemmeno leggere altro. Ridurrebbe la confusione.

    
1
2009-12-07 21: 36: 22Z
  1. Quali benefici otterresti da MathConstants.ZERO?
    2009-12-07 22: 07: 51Z
  2. Quello che sto ottenendo è che è una costante concordata piuttosto che delle costanti che sono scritte dappertutto. In questo modo, qualsiasi sviluppatore futuro può facilmente capire le costanti. Come FIRST e SECOND, mi confondono, ma se fossero concordati sulle costanti da parte del team, sarebbe molto più comprensibile. Almeno è così che lo vedo.
    2009-12-08 16: 00: 25Z

Ci sono generalmente quattro ragioni per cui posso pensare di usare una costante:

  1. Come sostituto di un valore che potrebbe ragionevolmente cambiare in futuro (ad es. IdColumnNumber = 1).
  2. Come etichetta per un valore che potrebbe non essere facile da comprendere o significativo da solo (ad es. FirstAsciiLetter = 65),
  3. Come un modo più breve e meno soggetto a errori di digitare un valore lungo o difficile da digitare (ad es. LongSongTitle = "Supercalifragilisticexpialidocious")
  4. Come aiuto di memoria per un valore difficile da ricordare (ad es. PI = 3.14159265)

Per i tuoi esempi particolari, ecco come giudicherei ogni esempio:

 
const int ZERO_RECORDS = 0;
// almost definitely a code smell

const int FIRST_ROW = 0;
// first row could be 1 or 0, so this potentially fits reason #2,
// however, doesn't make much sense for standard .NET collections
// because they are always zero-based

const int DEFAULT_INDEX = 0;
// this fits reason #2, possibly #1

const int STRINGS_ARE_EQUAL = 0;
// this very nicely fits reason #2, possibly #4
// (at least for anyone not intimately familiar with string.CompareTo())

Quindi, direi che, no, non sono peggio di Zero = 0 o A = "A".

    
1
2009-12-08 00: 15: 51Z
  1. first_row e default_index vengono utilizzati solo durante l'iterazione di un ciclo. IE: (per int i = default_index ...). first_row viene utilizzato allo stesso modo durante l'iterazione su una tabella di dati.
    2009-12-08 14: 58: 41Z
  2. Se è così che vengono usati, direi sicuramente odore di codice.
    2009-12-08 17: 48: 07Z

Se lo zero indica qualcosa di diverso da zero (in questo caso STRINGS_ARE_EQUAL) allora IS IS Magical. Creare una costante per questo è accettabile e rende il codice più leggibile.

Creare una costante chiamata ZERO è inutile e uno spreco di energia dito!

    
0
2009-12-07 20: 39: 59Z
  1. Direi che lo zero non è neanche magico in quel senso. String.Compare segue lo standard abituale sui valori di ritorno per indicare il successo /il fallimento - che cosa è così magico in questo?
    2009-12-07 20: 43: 30Z
  2. È magico perché indica qualcosa di diverso da zero. Il codice leggibile è codice leggibile, standard o meno.
    2009-12-08 12: 31: 28Z
  3. 0 è un valore di ritorno ben noto. Penso che 0 significhi vero /falso, successo /fallimento siano ovvi.
    2009-12-08 14: 52: 36Z

Gli odori un po ', ma potrei vedere casi in cui ciò avrebbe senso, specialmente se i programmatori passano continuamente dalla lingua alla lingua.

Ad esempio, MATLAB è a un indice, quindi potrei immaginare che qualcuno si stia annoiando con errori off-one quando cambiano lingua e definendo DEFAULT_INDEX in entrambi i programmi C ++ e MATLAB per astrarre la differenza. Non necessariamente elegante, ma se è quello che serve ...

    
0
2009-12-07 21: 27: 41Z

Giusto, devi interrogare questo giovane guerriero del codice dell'odore. Tuttavia, queste costanti nominate derivano da pratiche di codifica molto più vecchie rispetto all'alba di Visual Studio. Probabilmente sono ridondanti ma potresti fare peggio che capire l'origine della convenzione. Pensa ai computer della NASA, molto indietro quando ...

    
0
2009-12-07 21: 56: 05Z

Potresti vedere qualcosa di simile in una situazione multipiattaforma in cui useresti il ​​file con l'insieme di costanti appropriato per la piattaforma. Ma probabilmente non con questi esempi reali. Sembra che un coder COBOL stia cercando di far apparire il suo C # più simile alla lingua inglese (nessun reato destinato ai programmatori COBOL).

    
0
2009-12-07 23: 16: 45Z
  1. Cosa !? Io sempre cogli l'occasione per offendere i programmatori COBOL! : -)
    2009-12-08 00: 47: 58Z

Va ​​bene usare le costanti per rappresentare valori astratti, ma un altro per rappresentare i costrutti nella tua lingua.

const int FIRST_ROW = 0 non ha senso.

const int MINIMUM_WIDGET_COUNT = 0 ha più senso.

La presunzione di dover seguire uno standard di codifica ha senso. (Ovvero, gli standard di codifica sono presumibilmente corretti all'interno di un'organizzazione). Seguirne pedissequamente quando la presunzione non viene soddisfatta non ha senso.

Quindi sono d'accordo con i manifesti precedenti che alcune delle costanti puzzolenti derivavano probabilmente dal seguire uno standard di codifica ("nessun numero magico") alla lettera senza eccezioni. Questo è il problema qui.

    
0
2009-12-13 16: 32: 24Z
fonte posta Qui