Questo uso di un overkill costante simbolico?

34

Sono abbastanza nuovo nell'ingegneria del software, e quindi come esercizio di apprendimento ho scritto un gioco di scacchi. Il mio amico ha dato un'occhiata a questo e ha sottolineato che il mio codice sembrava tipo

for (int i = 0; i < 8; i++){
    for (int j = 0; j < 8; j++){

mentre ha insistito sul fatto che dovrebbe essere

for (int i = 0; i < CHESS_CONST; i++){
    for (int j = 0; j < CHESS_CONST; j++){

con un nome di simbolo migliore che non posso essere disturbato a pensare al momento.

Ovviamente so di solito evitare di usare numeri magici, ma mi sento come se

  1. questo numero non cambierà mai;
  2. il nome non può essere comunque descrittivo in quanto il numero è utilizzato in così tanti punti del codice; e
  3. chiunque abbia a che fare con il codice sorgente per un programma di scacchi dovrebbe sapere abbastanza sugli scacchi per sapere a cosa serve l'8,

non c'è davvero bisogno di una costante simbolica.

Quindi cosa ne pensate voi ragazzi? Questo è eccessivo, o dovrei andare con le convenzioni e usare un simbolo?

    
posta chocolatedevil 08.04.2017 - 09:43
fonte

3 risposte

102

IMHO il tuo amico ha ragione ad usare un nome simbolico, anche se penso che il nome debba essere decisamente più descrittivo (come BOARD_WIDTH invece di CHESS_CONST ).

Anche quando il numero non cambierà mai per tutta la durata del programma, potrebbero esserci altri punti del programma in cui il numero 8 si presenterà con un significato diverso. Sostituendo "8" di BOARD_WIDTH ovunque si intenda la larghezza della tavola e usando un altro nome simbolico quando si intende una cosa diversa, questi diversi significati sono espliciti, ovvi e il tuo programma generale più leggibile e mantenibile. Ti consente anche di effettuare una ricerca globale sul tuo programma (o una ricerca di simboli inversa, se il tuo ambiente lo fornisce) nel caso in cui sia necessario identificare rapidamente tutti i punti del codice che dipendono dalla larghezza della scheda.

Vedi anche questo post precedente di SE.SE per una discussione su come (o come non farlo) scegli i nomi per i numeri.

Come nota a margine, poiché è stato discusso qui nei commenti : se, nel codice del tuo programma reale, è importante se la variabile i si riferisce alle righe e j a colonne di la scheda, o viceversa, allora è raccomandabile selezionare nomi di variabili che rendano chiara la distinzione, come row e col . Il vantaggio di tali nomi è che rendono codice errato con un aspetto errato.

    
risposta data 08.04.2017 - 09:56
fonte
10

Ok, ecco alcuni commenti che ho:

Liberarsi dei numeri magici è una grande idea. Esiste un concetto noto come DRY, che viene spesso travisato, ma l'idea è che non si duplichi la conoscenza dei concetti nel progetto. Quindi se hai una classe chiamata ChessBoard, puoi mantenere una costante chiamata BOARD_SIZE o ChessBoard.SIZE ad essa allegata. In questo modo c'è un'unica fonte per questa informazione. Inoltre, questo aiuta la leggibilità più tardi:

for (int i = 0; i < ChessBoard.SIZE; i++){
  for (int j = 0; j < ChessBoard.SIZE; j++){

Anche se il numero non cambia mai, il tuo programma è indubbiamente migliore. Qualsiasi persona che lo legge conosce più informazioni su ciò che sta facendo il codice.

Un brutto nome è peggio di nessun nome, ma ciò non significa che qualcosa non debba essere nominato. Basta cambiare il nome. Non buttare via il bambino con l'acqua del bagno. : p Il nome può essere descrittivo se si capisce bene cosa sta descrivendo. Quindi, questo concetto può essere utilizzato per più cose diverse.

    
risposta data 08.04.2017 - 16:28
fonte
-7

Quello che vuoi veramente è eliminare i riferimenti nauseum alle costanti, indipendentemente dal fatto che siano nominati o nudi:

for_each_chess_square (row, col) {
  /*...*/
}

Se stai effettivamente facendo proliferare la costante ripetendo tali cicli e quant'altro, è meglio restare fedeli a 8 .

8 è auto-descrittivo; non è una macro che sta per qualcos'altro.

Non lo farai mai (TM) trasformalo in un programma di scacchi 9x9 e se mai lo farai, la proliferazione di 8 non sarà la maggiore difficoltà.

Possiamo cercare una base di codice di linea di 150.000 per il token 8 e classificare quali occorrenze significano cosa in secondi.

Molto più importante è modulare il codice in modo che la conoscenza degli scacchi sia concentrata nel minor numero di posti possibile. È meglio avere uno, due, forse tre moduli specifici per scacchi in cui si verifica un letterale 8, di trentasette moduli legati alla responsabilità specifica degli scacchi, riferendosi a 8 attraverso un nome simbolico.

Quando o se questa costante 8 diventa una fonte di tensione nel tuo programma, puoi facilmente risolverlo in quel momento. Risolve i problemi reali che stanno accadendo ora. Se non ti senti ostacolato da quel particolare 8, segui quell'istinto.

Supponiamo che in futuro si desideri supportare dimensioni scheda alternative. In tal caso, tali loop dovranno cambiare se utilizzano una costante denominata o 8 , poiché le dimensioni verranno recuperate da alcune espressioni come board.width e board.height . Se hai BOARD_SIZE anziché 8 , questi luoghi saranno più facili da trovare. Quindi questo è meno sforzo. Tuttavia, non devi dimenticare lo sforzo di sostituire 8 con BOARD_SIZE in primo luogo. Lo sforzo complessivo non è inferiore. Fare un passaggio sul codice per cambiare 8 in BOARD_SIZE , e poi un altro per supportare dimensioni alternative, non è più economico di andare da 8 a supporto di dimensioni alternative.

Possiamo anche considerare questo da un'analisi rischio / beneficio puramente fredda, oggettiva. Il programma ha costanti nude in esso ora. Se questi sono sostituiti da una costante, non vi è alcun vantaggio; il programma è identico. Con qualsiasi cambiamento, c'è un rischio diverso da zero. In questo caso, è piccolo. Tuttavia, nessun rischio dovrebbe essere preso senza un beneficio. Per "vendere" il cambiamento di fronte a questo ragionamento, dobbiamo ipotizzare un beneficio: un beneficio futuro che aiuterà con un programma diverso: una versione futura del programma che non esiste ora. Se un tale programma viene pianificato, questa ipotesi e il relativo ragionamento associato sono in buona fede e dovrebbero essere presi sul serio.

Ad esempio, se mancano pochi giorni all'aggiunta di altro codice che farà proliferare ulteriormente queste costanti, potresti volerle eliminare. Se quelle istanze delle costanti sono approssimativamente tutte le istanze che esisteranno, allora perché preoccuparsi.

Se lavori su un software commerciale, si applicheranno anche gli argomenti del ROI. Se un programma non viene venduto e la modifica di alcuni numeri codificati in costanti non migliorerà le vendite, non sarai ricompensato per lo sforzo. Il cambiamento ha zero ritorno sull'investimento di tempo. Gli argomenti del ROI si generalizzano al di là del denaro. Hai scritto un programma, investendo tempo e fatica, e ne hai ricavato qualcosa: questo è il tuo ritorno, la tua "R". Se facendo questo cambiamento da solo, si ottiene più di quella "R", qualunque essa sia, quindi con tutti i mezzi. Se hai qualche piano per ulteriori sviluppi, e quel cambiamento migliora la tua "R", idem. Se la modifica non ha alcuna "R" immediata o prevedibile per te, dimenticala.

    
risposta data 08.04.2017 - 17:54
fonte

Leggi altre domande sui tag