Jestem dość nowy w inżynierii oprogramowania, dlatego jako ćwiczenie napisałem grę w szachy. Mój przyjaciel rzucił na to okiem i zwrócił uwagę, że mój kod wygląda
for (int i = 0; i < 8; i++){
for (int j = 0; j < 8; j++){
podczas gdy nalegał, aby tak było
for (int i = 0; i < CHESS_CONST; i++){
for (int j = 0; j < CHESS_CONST; j++){
z jakąś lepszą nazwą symbolu, o której nie mogę teraz myśleć.
Teraz oczywiście wiem, że na ogół unikam używania magicznych liczb, ale od tego czasu mam na to ochotę
- liczba ta nigdy się nie zmieni;
- i tak nazwa nie może być tak opisowa, ponieważ numer jest używany w tak wielu miejscach w całym kodzie; i
- każdy, kto przechodzi przez kod źródłowy programu szachowego, powinien wiedzieć wystarczająco dużo o szachach, aby wiedzieć, do czego służy 8,
tak naprawdę nie ma potrzeby stałej symbolicznej.
Więc co myślicie? Czy to przesada, czy powinienem pójść zgodnie z konwencją i użyć symbolu?
coding-style
coding-standards
chocolatedevil
źródło
źródło
i
ij
zmienne pętli. Nie mogę z mojego życia ustalić, który z nich ma reprezentować rangę, a który ma reprezentować plik. Szeregi zakresie od 1..8 oraz pliki wahają się od a..h, ale w twoim przypadku, zarównoi
ij
zakres od 0..7, tak że nie pomoże mi zobaczyć co jest czym. Czy istnieje jakiś kryzys związany z brakiem listów międzynarodowych, o którym nie wiem, lub co jest złego w zmianie nazwy narank
ifile
?foreach(var rank in Ranks)
. Rozważę również połączenie obu pętli w jedną, w której każdy element jest krotką (ranga, plik).Odpowiedzi:
IMHO twój przyjaciel ma rację używając nazwy symbolicznej, chociaż myślę, że nazwa powinna zdecydowanie być bardziej opisowa (jak
BOARD_WIDTH
zamiastCHESS_CONST
).Nawet jeśli liczba nigdy się nie zmieni w trakcie trwania programu, mogą istnieć inne miejsca w twoim programie, w których liczba 8 będzie miała inne znaczenie. Zastąpienie „8”
BOARD_WIDTH
wszędzie tam, gdzie oznacza się szerokość płytki, i użycie innej symbolicznej nazwy, gdy chodzi o inną rzecz, czyni te różne znaczenia wyraźnymi, oczywistymi, a cały program jest bardziej czytelny i łatwy do utrzymania. Umożliwia także globalne wyszukiwanie w programie (lub wyszukiwanie symboli odwrotnych, jeśli zapewnia to Twoje środowisko) na wypadek, gdybyś musiał szybko zidentyfikować wszystkie miejsca w kodzie, które zależą od szerokości płyty.Zobacz także poprzedni post na SE.SE, aby dowiedzieć się, jak (lub jak nie) wybierać nazwy dla liczb.
Na marginesie, ponieważ zostało to omówione tutaj w komentarzach : jeśli w kodzie twojego prawdziwego programu ma znaczenie to, czy zmienna
i
odnosi się do wierszy ij
kolumn tablicy lub odwrotnie, zaleca się wybranie nazw zmiennych, które wyraźne rozróżnienie, jakrow
icol
. Zaletą takich nazw jest to, że sprawiają, że zły kod wygląda źle.źródło
Ok, oto kilka komentarzy, które mam:
Pozbycie się magicznych liczb to świetny pomysł. Istnieje pojęcie znane jako DRY, które często jest fałszywie przedstawiane, ale chodzi o to, że nie powielasz znajomości pojęć w swoim projekcie. Więc jeśli masz klasę o nazwie ChessBoard, możesz zachować stałą o nazwie BOARD_SIZE lub ChessBoard.SIZE dołączoną do niej. W ten sposób istnieje jedno jedyne źródło tych informacji. Pomaga to również w czytelności później:
Nawet jeśli liczba nigdy się nie zmienia, Twój program jest prawdopodobnie lepszy. Każda osoba, która go czyta, wie więcej informacji o tym, co robi kod.
Złe imię jest gorsze niż brak imienia, ale to nie znaczy, że czegoś nie należy nazywać. Po prostu zmień nazwę. Nie wylewaj dziecka z kąpielą. : p Nazwa może być opisowa, o ile dobrze rozumiesz, co ona opisuje. Następnie tę koncepcję można zastosować do wielu różnych rzeczy.
źródło
To, czego naprawdę chcesz, to wyeliminowanie odwołań do stałych reklam na stałe, bez względu na to, czy są nazwane, czy nie
Jeśli zamierzasz rozpowszechniać stałą, powtarzając takie pętle i tak dalej, najlepiej trzymać się tego
8
.8
jest samoopisujący; to nie makro oznacza coś innego.Nie zmienisz go nigdy w program szachowy 9x9, a jeśli kiedykolwiek to zrobisz, mnożenie 8 nie będzie główną trudnością.
Możemy przeszukać 150 000 baz kodu linii dla tokena 8 i sklasyfikować, które wystąpienia oznaczają co w sekundach.
O wiele ważniejsza jest modularyzacja kodu, aby wiedza szachowa była skoncentrowana w jak najmniejszej liczbie miejsc. Lepiej mieć jeden, dwa, może trzy moduły szachowe, w których występuje dosłownie 8, niż trzydzieści siedem modułów związanych z odpowiedzialnością szachową, odnosząc się do 8 poprzez symboliczną nazwę.
Kiedy lub jeśli ta 8 stała się źródłem napięcia w twoim programie, możesz to łatwo naprawić w tym czasie. Napraw prawdziwe problemy, które mają miejsce teraz. Jeśli nie czujesz, że przeszkadza ci ta konkretna 8, idź z tym instynktem.
Załóżmy, że w przyszłości chcesz obsługiwać alternatywne wymiary płyty. W takim przypadku pętle te będą musiały zmienić, czy używają nazwanej stałej, czy
8
, ponieważ wymiary zostaną odczytane przez jakieś wyrażenie, takie jakboard.width
iboard.height
. Jeśli maszBOARD_SIZE
zamiast8
, te miejsca będą łatwiejsze do znalezienia. To mniej wysiłku. Nie należy jednak zapominać o wysiłku zastąpienia8
goBOARD_SIZE
. Ogólny wysiłek nie jest niższy. Dokonywanie jednej przejść nad kodem do zmian8
doBOARD_SIZE
, a potem jeszcze do wspierania alternatywnych wymiarów, nie jest tańsze niż po prostu się z8
alternatywnej wsparcia wymiaru.Możemy też na to spojrzeć z czysto zimnej, obiektywnej analizy stosunku korzyści do ryzyka. Program ma teraz w sobie stałe. Jeśli zostaną one zastąpione stałą, nie ma korzyści; program jest identyczny. Przy każdej zmianie istnieje niezerowe ryzyko. W tym przypadku jest mały. Mimo to nie należy podejmować ryzyka bez korzyści. Aby „sprzedać” zmianę w obliczu tego rozumowania, musimy postawić hipotezę korzyści: przyszłej korzyści, która pomoże w innym programie: przyszłej wersji programu, która nie istnieje teraz. Jeśli planowany jest taki program, hipoteza i związane z nią rozumowanie są w dobrej wierze i należy je traktować poważnie.
Na przykład, jeśli dzieli Cię kilka dni od dodania więcej kodu, który jeszcze bardziej rozpowszechni te stałe, możesz z nich zrezygnować. Jeśli te instancje stałych to w przybliżeniu wszystkie instancje, które kiedykolwiek będą istnieć, to po co się tym przejmować.
Jeśli kiedykolwiek pracujesz nad oprogramowaniem komercyjnym, zastosowanie będą miały również argumenty dotyczące ROI. Jeśli program nie sprzedaje, a zamiana niektórych liczb zakodowanych na stałe nie poprawi sprzedaży, wysiłek nie zostanie zrekompensowany. Zmiana ma zerowy zwrot z inwestycji czasu. Argumenty dotyczące ROI generalizują się poza pieniądzem. Napisałeś program, inwestując czas i wysiłek, i coś z tego wyciągnąłeś: to twój zwrot, twoje „R”. Jeśli dokonując tej zmiany samodzielnie, uzyskasz więcej tego „R”, cokolwiek to jest, to za wszelką cenę. Jeśli masz jakiś plan dalszego rozwoju, a ta zmiana poprawi twoje „R”, to samo. Jeśli zmiana nie ma dla Ciebie natychmiastowego lub przewidywalnego „R”, zapomnij o tym.
źródło
8
NIE jest tak samoopisujące się, to liczba, która może znaczyć cokolwiek. A może chcą zagrać w szachy 9x9, dlaczego nie? Jeśli masz 150 000 wierszy kodu, nie ma możliwości zapamiętania znaczenia każdego z nich8
w kodzie, a nawet gdybyś mógł, dlaczego miałbyś to zrobić? To tylko wiele dodatkowych problemów. Jeśli chodzi o modularyzację, zastąpienie8
czegoś podobnegoNUM_RANKS
nie szkodzi modułowości, w rzeczywistości pomaga, ponieważ ułatwia manipulowanie kodem.8
zeBOARD_SIZE
na pierwszym miejscu” - czas pan spędził kontrolowania nad kodzie próbując zrozumieć, co każdy8
robi w programie miesięcy od teraz najprawdopodobniej przekroczy czas spędzony wymiany8
z znacząca stała na poziomie modułu.