Więc każda liczba w kodzie, który wysyłamy do metody jako argument, jest uważana za liczbę magiczną? Dla mnie nie powinno. Myślę, że jeśli jest jakaś liczba, powiedzmy, że jest to minimalna długość nazwy użytkownika i zaczynamy używać „6” w kodzie ... to tak, mamy problem z konserwacją, a tutaj „6” to magiczna liczba… ale jeśli wywołujemy metodę, w której jeden z jej argumentów przyjmuje liczbę całkowitą, na przykład jako ity element kolekcji, a następnie przekazujemy „0” do tego wywołania metody, w tym przypadku nie widzę tego „0” jako magii numer. Co myślisz?
programming-practices
Blake
źródło
źródło
Odpowiedzi:
Jeśli znaczenie liczby jest bardzo jasne w kontekście, nie sądzę, że jest to problem z „magiczną liczbą”.
Przykład: Załóżmy, że próbujesz pobrać podciąg łańcucha od początku do jakiegoś tokena, a kod wygląda następująco (wymyślony język i biblioteka):
W tym kontekście znaczenie liczby 0 jest wystarczająco jasne. Przypuszczam, że możesz zdefiniować
START_OF_SUBSTRING
i ustawić na 0, ale w tym przypadku myślę, że byłoby to przesadą (chociaż byłoby to właściwe podejście, gdybyś wiedział, że początek twojego podłańcucha może nie być 0, ale to zależy od specyfiki Twoja sytuacja).Innym przykładem może być próba ustalenia, czy liczba jest parzysta czy nieparzysta. Pisanie:
nie jest tak dziwny jak:
Testowanie liczb ujemnych jako
też wydaje mi się dziwne, wolałbym raczej zobaczyć
źródło
360
zaznaczenie pełnego obrotu ze zrozumieniem, że większość ludzi będzie wiedziała, co to znaczy (chociaż to to przypadek, w którym nie zaszkodzi zapewnić stałą)0
w kontekście mojego przykładu podłańcucha. W takim przypadku może to być najmniejsza ilość szkód, jakie mogą spowodować. Minęło dużo czasu, odkąd zrobiłem kodowanie, które wykonało obliczenia geometryczne, ale ogólnie wartości 15, 30, 45, 60, 90, 180, 360 były stałymi, które zostały zaakceptowane. Nigdy nie widziałem, żeby ktoś zdefiniowałFIFTEEN_DEGREES
...To oczywiste, że zero oznacza brak. Uważam, że 0 jest łatwiejsze do zrozumienia niż zmienna o nazwie „failedValue”.
To oczywiste, że 0 to pozycja początkowa. Byłbym zdezorientowany przez zmienną o nazwie „firstPosition”. Taka zmienna sprawiłaby, że zastanawiałem się, czy pozycja początkowa mogłaby się zmienić.
źródło
Sugerowałbym trzy kluczowe czynniki przy podejmowaniu decyzji, czy coś powinno być stałą deklaracją:
Coś w rodzaju pi powinno prawdopodobnie być zapisane jako nazwana stała, a nie jako literał liczbowy, ponieważ literał liczbowy może być niepotrzebnie gadatliwy, niepotrzebnie nieprecyzyjny lub jedno i drugie. Coś w rodzaju liczby miejsc w pamięci podręcznej powinno być nazwaną stałą (choć patrz uwaga poniżej), aby umożliwić możliwość rozszerzenia pamięci podręcznej bez konieczności modyfikowania całego kodu, który z niej korzysta. Rzeczy takie jak cyfry „4”, „28” i „29” w instrukcji
if ((year % 4)==0) FebruaryDays = 29; else FebruaryDays = 28;
prawdopodobnie nie powinny być nazwane stałymi, ponieważ wyrażenie jest prawie na pewno bardziej czytelne niżif ((year % YearsBetweenLeapYears)==0) FebruaryDays = FebruaryDaysInLeapYear; else FebruaryDays = FebruaryDaysInNonLeapYear;
. Pamiętaj, że osoby przestrzegające standardów wskazały, że długość 2100 lutego w tym roku nie będzie zgodna z powyższą formułą, przeszkoda w prawidłowej obsłudze takich dat (tzn. kod nie zostanie wyzwolony przez przepełnienie liczb całkowitych lub inne podobne problemy).Ważnym zastrzeżeniem związanym z zasadą nr 2 jest to, że w niektórych przypadkach kod może polegać na liczbach zakodowanych na stałe w sposób, którego nie można łatwo przedstawić za pomocą nazwanej stałej. Na przykład metoda, która oblicza iloczyn krzyżowy dwóch wektorów przekazanych jako parametry dyskretne, będzie miała znaczenie tylko w przypadku zastosowania w wektorach trójwymiarowych. Wymagana liczba wymiarów nie jest wartością, którą można znacznie zmienić bez całkowitego przepisania procedury. Nawet gdyby przewidzieć możliwą potrzebę obliczenia iloczynu krzyżowego trzech 4-wymiarowych wektorów, użycie nazwanej stałej dla wartości „3” niewiele by zrobiło, aby ułatwić zaspokojenie tej potrzeby.
źródło
To, jak wszystkie zasady, jest kwestią stopnia. Ogólnie rzecz biorąc, literały liczbowe w kodzie źródłowym są bardziej podejrzane, im są większe. Maksymalna długość jak 10 lub adres pamięci jak 0x587FB0 to oczywiście zła praktyka - jest prawie pewne, że prędzej czy później będziesz musiał powtórzyć te wartości więcej niż jeden raz, stwarzając ryzyko niezgodności i subtelnych błędów wprowadzanych w miejscach, które nie były zmienione.
0 znajduje się na drugim końcu skali; wciąż jest podejrzane, ale nie tak bardzo. Czy używasz 0 jako wartości wartownika? Wtedy prawdopodobnie powinieneś użyć stałej symbolicznej, tylko dlatego, że stała może wyjaśnić, co to znaczy. Czy jest to wyjątkowo zakorzenione porozumienie kulturowe, takie jak „0 oznacza pomyślne zakończenie”? To chyba OK. Czy to oznacza „pierwszy element w kolekcji”? Może to być nieszkodliwe, ale jeśli istnieje alternatywna metoda, taka
first()
, którą prawdopodobnie wolałbym.źródło
Każda nienazwana liczba, która nie jest od razu oczywista z kontekstu, jest liczbą magiczną. Trochę głupio jest definiować liczby, które mają znaczenie, które jest natychmiast oczywiste z kontekstu.
W django (frameworku Python) mogę zdefiniować pole bazy danych o nieprzetworzonej liczbie, takie jak:
co jest jaśniejsze (i zalecana praktyka ) niż powiedzieć
ponieważ prawdopodobnie nigdy nie będę musiał zmieniać długości (i zawsze mogę to porównać do
max_length
pola). Jeśli muszę zmienić długość pola po początkowym wdrożeniu aplikacji, muszę zmienić go dokładnie w jednym miejscu na pole w moim kodzie django, a następnie dodatkowo napisać migrację, aby zmienić schemat bazy danych. Jeśli kiedykolwiek będę potrzebować odwoływać sięmax_length
do zdefiniowanego pola typu obiektu, mogę to zrobić bezpośrednio - jeśli pola te definiująPerson
klasę, mogę użyć,Person._meta.get_field('firstname').max_length
aby uzyskaćmax_length
w użyciu (który jest zdefiniowany w jednym miejscu). Fakt, że tych samych 40 użyto do wielu pól, nie ma znaczenia, ponieważ mogę chcieć je zmienić niezależnie. Długość imienia nigdy nie powinna zależeć od długości imienia i nazwiska; są to osobne wartości i mogą się zmieniać niezależnie.Indeksy tablicowe często mogą używać liczb nienazwanych; na przykład, jeśli mam plik CSV danych, który chcę umieścić w słowniku Pythona, z pierwszym elementem w wierszu jako słownik
key
, który napisałbym:Pewnie, że mógłbym nazwać
index_column = 0
i zrobić coś takiego:lub gorzej zdefiniować,
after_index_col = index_col + 1
aby się go pozbyćindex_col+1
, ale to nie sprawia, że kod jest jaśniejszy. Ponadto, jeśli podamindex_col
nazwę, lepiej sprawię, aby kod działał, nawet jeśli kolumna nie jest równa 0 (stądrow[:index_col] +
część).źródło
max_lngth=40
vs.max_length=MAX_LENGTH_NAME
to klasyczny przykład magicznej liczby, która krzyczy, że jest symbolem. Nadejdzie dzień, w którym chcesz wesprzeć 45 nazw postaci, a teraz każde użycie „40” jest podejrzane i musi zostać dokładnie zbadane.40
do1
. Musisz pomyśleć o kontekście.