Ich bin ziemlich neu in der Softwareentwicklung und habe als Lernübung ein Schachspiel geschrieben. Mein Freund schaute es sich an und wies darauf hin, dass mein Code so aussah
for (int i = 0; i < 8; i++){
for (int j = 0; j < 8; j++){
während er darauf bestand, dass es stattdessen sein sollte
for (int i = 0; i < CHESS_CONST; i++){
for (int j = 0; j < CHESS_CONST; j++){
mit einem besseren Symbolnamen, an den ich im Moment gar nicht denken kann.
Jetzt weiß ich natürlich, dass ich es generell vermeiden soll, magische Zahlen zu verwenden, aber ich fühle mich wie seitdem
- Diese Zahl wird sich nie ändern.
- der Name konnte sowieso nicht so aussagekräftig sein, da die Nummer an so vielen Stellen im Code verwendet wird; und
- Jeder, der den Quellcode für ein Schachprogramm durchläuft, sollte genug über Schach wissen, um zu wissen, wofür die 8 ist.
Es ist wirklich keine symbolische Konstante erforderlich.
Also, was denkt ihr? Ist das übertrieben, oder sollte ich mich einfach an die Konvention halten und ein Symbol verwenden?
coding-style
coding-standards
Schokoladenteufel
quelle
quelle
i
undj
die Schleifenvariablen viel irritierender als die magische Zahl . Ich kann für mein ganzes Leben nicht herausfinden, welcher eine Rang und welcher eine Akte darstellen soll. Ränge reichen von 1..8 und Dateien reichen von a..h, aber in Ihrem Fall reichen beidei
undj
0..7, so dass mir das nicht hilft zu sehen, welche welche ist. Gibt es eine internationale Briefknappheit, von der ich nichts weiß, oder was ist falsch daran, sie inrank
undfile
umzubenennen?foreach(var rank in Ranks)
. Ich würde auch in Betracht ziehen, beide Schleifen zu einer zusammenzuführen, wobei jedes Element ein Tupel (rank, file) ist.Antworten:
IMHO hat Ihr Freund Recht, wenn er einen symbolischen Namen verwendet, obwohl ich denke, dass der Name definitiv aussagekräftiger sein sollte (wie
BOARD_WIDTH
anstelle vonCHESS_CONST
).Auch wenn sich die Zahl während der gesamten Laufzeit des Programms nicht ändert, kann es in Ihrem Programm andere Stellen geben, an denen die Zahl 8 eine andere Bedeutung hat. Das Ersetzen von "8" durch "
BOARD_WIDTH
wo immer die Kartenbreite gemeint ist" und das Verwenden eines anderen symbolischen Namens, wenn etwas anderes gemeint ist, macht diese unterschiedlichen Bedeutungen explizit, offensichtlich und Ihr Gesamtprogramm lesbarer und wartbarer. Es ermöglicht Ihnen auch eine globale Suche über Ihr Programm (oder eine Rückwärtssymbolsuche, falls Ihre Umgebung dies vorsieht), falls Sie schnell alle Stellen im Code identifizieren müssen, die von der Kartenbreite abhängen.Siehe auch diesen früheren SE.SE-Beitrag für eine Diskussion, wie man Namen für Zahlen auswählt (oder nicht).
Als Randnotiz, da es hier in den Kommentaren besprochen wurde : Wenn es im Code Ihres realen Programms darauf ankommt, ob sich die Variable
i
auf Zeilen undj
Spalten der Karte bezieht oder umgekehrt, dann ist es empfehlenswert, Variablennamen auszuwählen, die Machen Sie die Unterscheidung klar, wierow
undcol
. Der Vorteil solcher Namen ist, dass sie falschen Code falsch aussehen lassen.quelle
Ok, hier sind ein paar Kommentare, die ich habe:
Sich von magischen Zahlen zu befreien, ist eine großartige Idee. Es gibt ein Konzept namens DRY, das häufig falsch dargestellt wird, aber die Idee ist, dass Sie das Wissen über die Konzepte in Ihrem Projekt nicht duplizieren. Wenn Sie also eine Klasse mit dem Namen ChessBoard haben, können Sie eine Konstante mit dem Namen BOARD_SIZE oder ChessBoard.SIZE daran anhängen. Auf diese Weise gibt es eine einzige Quelle für diese Informationen. Dies trägt auch zur späteren Lesbarkeit bei:
Auch wenn sich die Anzahl nie ändert, ist Ihr Programm wohl besser. Jede Person, die es liest, weiß mehr darüber, was der Code tut.
Ein schlechter Name ist schlimmer als kein Name, aber das bedeutet nicht, dass etwas nicht benannt werden sollte. Ändern Sie einfach den Namen. Werfen Sie das Baby nicht mit dem Badewasser weg. : p Der Name kann beschreibend sein, solange Sie gut verstehen, was er beschreibt. Dann kann dieses Konzept für mehrere verschiedene Dinge verwendet werden.
quelle
Was Sie wirklich wollen, ist, Ad-nauseum- Verweise auf Konstanten zu entfernen , egal ob sie benannt oder nackt sind:
Wenn Sie die Konstante tatsächlich vermehren wollen, indem Sie solche Schleifen und so weiter wiederholen, ist es am besten, sich daran zu halten
8
.8
ist selbstbeschreibend; Es ist kein Makro, das für etwas anderes steht.Sie werden es nicht (TM) in ein 9x9-Schachprogramm verwandeln, und wenn Sie es jemals tun, wird die Verbreitung von 8 nicht die Hauptschwierigkeit sein.
Wir können eine 150.000-Zeilen-Code-Basis nach dem Token 8 durchsuchen und in Sekunden festlegen, welche Vorkommen was bedeuten.
Viel wichtiger ist es, den Code so zu modularisieren, dass das Schachwissen an möglichst wenigen Stellen konzentriert wird. Es ist besser, ein, zwei, vielleicht drei schachspezifische Module zu haben, in denen eine wörtliche 8 vorkommt, als siebenunddreißig Module mit schachspezifischer Verantwortung, die sich auf 8 durch einen symbolischen Namen beziehen.
Wenn diese 8-Konstante zu einer Spannungsquelle in Ihrem Programm wird, können Sie sie zu diesem Zeitpunkt problemlos beheben. Beheben Sie echte Probleme, die gerade auftreten. Wenn Sie nicht das Gefühl haben, von dieser bestimmten 8 behindert zu werden, gehen Sie mit diesem Instinkt um.
Angenommen, Sie möchten in Zukunft alternative Platinenabmessungen unterstützen. In diesem Fall müssen diese Schleifen ändern, ob sie eine benannte Konstante oder verwenden
8
, da die Dimensionen durch einen Ausdruck wieboard.width
und abgerufen werdenboard.height
. Wenn SieBOARD_SIZE
stattdessen haben8
, werden diese Orte leichter zu finden sein. Das ist also weniger Aufwand. Sie müssen jedoch nicht um den Aufwand zu ersetzen , vergessen8
mitBOARD_SIZE
an erster Stelle. Der Gesamtaufwand ist nicht geringer. Machen ein Pass über den Code zu ändern8
zuBOARD_SIZE
, und dann auf eine andere alternative Dimensionen zu unterstützen, ist nicht billiger als gerade aus gehen8
auf alternative Dimension zu unterstützen.Wir können dies auch anhand einer rein kalten, objektiven Risiko-Nutzen-Analyse betrachten. Das Programm enthält jetzt nackte Konstanten. Wenn diese durch eine Konstante ersetzt werden, gibt es keinen Nutzen; Das Programm ist identisch. Bei jeder Änderung besteht ein Risiko ungleich Null. In diesem Fall ist es klein. Dennoch sollte kein Risiko ohne Nutzen eingegangen werden. Um die Änderung angesichts dieser Überlegungen zu "verkaufen", müssen wir einen Nutzen annehmen: einen zukünftigen Nutzen, der bei einem anderen Programm helfen wird: eine zukünftige Version des Programms, die es derzeit nicht gibt. Wenn ein solches Programm geplant ist, sind diese Hypothese und die damit verbundenen Überlegungen zutreffend und sollten ernst genommen werden.
Wenn Sie beispielsweise noch Tage Zeit haben, um weiteren Code hinzuzufügen, der diese Konstanten weiter vermehrt, möchten Sie sie möglicherweise beseitigen. Wenn diese Instanzen der Konstanten ungefähr alle Instanzen sind, die jemals existieren werden, warum dann?
Wenn Sie jemals an kommerzieller Software arbeiten, gelten auch die ROI-Argumente. Wenn sich ein Programm nicht verkauft und das Ändern einiger fest codierter Zahlen in Konstanten den Umsatz nicht verbessert, werden Sie nicht für den Aufwand entschädigt. Die Änderung hat keine Rendite auf die Investition von Zeit. ROI-Argumente gehen über das Geld hinaus. Sie haben ein Programm geschrieben, Zeit und Mühe investiert und etwas daraus gemacht: Das ist Ihre Rendite, Ihr "R". Wenn Sie diese Änderung alleine vornehmen, erhalten Sie mit allen Mitteln mehr von diesem "R", was auch immer es ist. Wenn Sie einen Plan für die weitere Entwicklung haben und diese Änderung Ihr "R" verbessert, dito. Wenn die Änderung kein unmittelbares oder vorhersehbares "R" für Sie hat, vergessen Sie es.
quelle
8
ist NICHT so selbstbeschreibend, es ist eine Zahl, die alles bedeuten könnte. Und vielleicht wollen sie ein 9x9 Schachspiel machen, warum nicht? Wenn Sie über 150.000 Codezeilen verfügen, können Sie sich auf keinen Fall merken, was die einzelnen8
Codezeilen bedeuten, und selbst wenn Sie dies könnten, warum sollten Sie das tun ? Das ist nur eine Menge zusätzlicher Aufwand. Was die Modularisierung angeht, schadet das Ersetzen8
durch etwasNUM_RANKS
nicht der Modularität. Tatsächlich hilft es, weil es das Basteln des Codes erleichtert.8
durch vergessenBOARD_SIZE
" - Die Zeit, die Sie damit verbracht hatten, Ihren Code zu überprüfen, um herauszufinden, was jeder8
in den nächsten Monaten in Ihrem Programm tut, würde höchstwahrscheinlich die Zeit überschreiten, die für das Ersetzen8
durch aufgewendet wurde eine sinnvolle Konstante auf Modulebene.