Magic Numbers, czyli bardzo złe praktyki w naszym kodzie

CSSFrontendJavaScript
Abstrakcyjna grafika przedstawiająca liczby unoszące się nad komputerem.

W tym wpisie omówimy dość popularny problem z magicznymi cyframi / liczbami (tytułowe magic numbers).

Czym są Magic Numbers?

„Magic Number” to wartość liczbowa użyta w naszym kodzie.
Może to być wartość w SASS, może to być wartość w JavaScript.

const password = 'abcd12345'

if (password.length > 8) {
  console.log('Hasło jest ok')
}

// aplikacja sprawdza, czy hasło użytkownika jest dłuższe, niż 8 znaków

// ========================

const shoppingCart = ['jabłka', 'mleko', 'lody']

if (shoppingCart.length > 2) {
  giveDiscount() 
}

if (shoppingCart.length > 2) {
  giveBonusPoints() 
}

// aplikacja przyznaje zniżkę oraz punkty lojalnościowe, jeśli klient kupi więcej, niż dwa produkty

W powyższych przykładach mamy dwa magiczne numery.
Długość hasła – cyfra 8, oraz ilość przedmiotów w koszyku zakupowym – cyfra 2.

Są to dość proste przykłady, więc po przeczytaniu kodu od razu wiadomo, co dana cyfra oznacza.

Natomiast są to zwykłe cyfry. Nie przedstawiają one żadnej informacji oraz są trudne do edycji.

Wyobraźmy sobie, że zmienia się promocja dotycząca zniżki na zakupy oraz zmienia się próg, od jakiego przyznawane są punkty lojalnościowe. Od teraz bonusy obowiązują od 4 przedmiotów w koszyku.

Przy obecnym kodzie, musimy tę wartość zaktualizować w dwóch miejscach, a nie jest powiedziane, że nie wykorzystamy jej jeszcze gdzieś indziej, prawda?

Pojawia się więc spory problem. Jeśli cyfra 2 byłaby wykorzystana w tysiącu miejsc, musielibyśmy zmarnować mnóstwo czasu na wprowadzenie poprawek.
Nie mielibyśmy też pewności, że nie popełnimy błędu.

Jak poradzić sobie z magicznymi cyframi?

Na szczęście rozwiązanie problemów z magicznymi liczbami jest banalnie proste. 🙂
Aby się ich pozbyć, wystarczy przypisać je do zmiennych.

const password = 'abcd12345'
const MIN_PASS_LENGTH = 8

if (password.length > MIN_PASS_LENGTH) {
  console.log('Hasło jest ok')
}

// ========================

const shoppingCart = ['jabłka', 'mleko', 'lody']
const MIN_NUMBER_OF_PRODUCTS_TO_INCLUDE_PROMOTION = 2

if (shoppingCart.length > MIN_NUMBER_OF_PRODUCTS_TO_INCLUDE_PROMOTION) {
  giveDiscount() 
}

if (shoppingCart.length > MIN_NUMBER_OF_PRODUCTS_TO_INCLUDE_PROMOTION) {
  giveBonusPoints() 
}

Dzięki temu od razu wiemy, do czego dana cyfra / liczba służy oraz jeśli w przyszłości będziemy musieli ją zaktualizować, wystarczy zrobić to w jednym miejscu.

Przy okazji – nie bójmy się długich nazw funkcji / zmiennych! 😉

Kod po zminifikowaniu i tak będzie odpowiednio przerobiony i ta długa nazwa zostanie zamieniona na ciąg kilku znaków, który dla komputerów nie będzie stanowił najmniejszego problemu.

Dla człowieka natomiast, dobra nazwa to oszczędność czasu i ułatwienie pracy.

Alternatywne rozwiązanie

Oczywiście nikt nie powiedział, że powyższe to jedyne rozwiązanie problemu magicznych cyfr.
Nie zawsze będziemy musieli lub chcieli tworzyć dodatkowe zmienne.

W kodzie możemy zostawić komentarz, który wytłumaczy, czym dana wartość jest.
Możemy też odpowiednio nazywać funkcje, tak aby nie pozostawiać żadnych wątpliwości.

function convertInchesToCentimeters(x) {
  return x * 2.54 // 1 cal to 2.54cm
}

Przy okazji mam nadzieję, że zauważyliście kolejny błąd w powyższym przykładzie, a więc parametr o tajemniczej nazwie x. Czym on jest?

Możemy zgadywać, że chodzi o cale, ale czy nie prościej i czytelniej byłoby go nazwać po prostu inches? 😉

function convertInchesToCentimeters(inches) {
  return inches * 2.54 // 1 cal to 2.54cm
}

Bonusowa porada

Będąc w temacie nazywania funkcji / zmiennych – błagam, unikajcie jakichś dziwnych zapisów skróconych!

Wiele razy spotykałem się z kodem, w którym zmienne były zapisywane za pomocą np. dwóch liter – „bo tak jest krócej”.

Dla przykładu – zmienna st. Co ona oznacza? Oczywiście autor wiedział, bo dopiero ją stworzył, ale gwarantuję, że gdyby wrócił do projektu po 2 tygodniach przerwy, straciłby mnóstwo czasu na rozszyfrowywaniu zagadki.

Nie wspomnę o osobach trzecich (np. ja), które czytały taki kod.

st… Co to może być… 🤔 Scroll top? Screen time? Super taco?
No właśnie. 😉

Pisząc kod, pamiętajcie, aby pisać go dla ludzi – nie dla maszyn.
Maszyny sobie ze wszystkim poradzą. 😉

Dobrze nazwane zmienne (oraz funkcje) zaoszczędzą nam – ludziom – mnóstwo czasu, problemów i domysłów.

Poprzedni wpis
Czas na zmiany!
Następny wpis
PROJEKT – Jak dodać śnieg na stronę WWW?