To bardzo niejasny tytuł, ale nie mogłem wymyślić lepszego sposobu na sformułowanie go. Ale, jako przykład, zastanów się, w jakim kierunku porusza się postać w grze. Po prostu używanie sznurka, a następnie robienie czegoś takiego, wydaje się trochę niewłaściwe if(character.direction == "left")
. Wydaje mi się, że nie pozostawia zbyt wiele miejsca na błędy głupie, jak przypadkowo użyciu Left
lub l
czy cokolwiek zamiast left
. Czy moje podejrzenia są prawidłowe? Jeśli tak, jaki jest preferowany sposób osiągnięcia czegoś takiego?
19
bash
.Odpowiedzi:
Jeśli używany język obsługuje użycie wyliczeń, użyłbym ich. Pozwala ograniczyć liczbę opcji dostępnych dla danego typu. np. w Javie:
źródło
enum
takimi jak java. Wiele języków (np. VBA) maenum
, ale może to nie być najlepsza opcja, ponieważ brakuje tego samego zabezpieczenia na przyszłość. Zobacz moją odpowiedź na dyskusję, dlaczegoenum
sam jest niekompletnym, często kruchym i specyficznym dla języka rozwiązaniem.Straszną praktyką jest używanie w kodzie literałów (lub liczb magicznych).
Wyliczenia są dobre lub przynajmniej używają stałych (wyliczenia są oczywiście tylko typem otoki dla jednej lub więcej powiązanych ze sobą stałych).
Ten prosty przełącznik ma tak wiele zalet, że nawet nie wiedziałbym, od czego zacząć je wyjaśniać (przynajmniej nie bez kawy). Czytając magiczne liczby, jest to ta sama dokładna koncepcja, stosowana tylko do wartości liczbowej zamiast wartości ciągu.
Oto jeden szybki przegląd, jestem pewien, że jest jeszcze setki: /programming/47882/what-is-a-magic-number-and-why-is-it-bad
źródło
Krótka odpowiedź: Tak, ciągi nie są idealne do zadań innych niż przechowywanie i uzyskiwanie dostępu do sekwencji znaków tekstowych, a nawet jeśli leżącymi u podstaw bitami abstrakcji są ciągi znaków, odniesienie ich jako zmiennych lub stałych jest korzystne .
Długa odpowiedź: większość języków oferuje typy, które są bliżej dziedziny twojego problemu, a nawet jeśli nie, prawdopodobnie mają jakąś metodę, dzięki której możesz zdefiniować
left
jako byt inny niżright
(itp. Itp.). Przekształcenie go w ciąg za pomocą"left"
jest po prostu przepadkiem języka i pomocnej funkcji IDE, takiej jak sprawdzanie błędów. Nawet jeśli musisz użyćlub coś równoważnego, ma tę zaletę, że używa łańcucha, gdy odwołujesz się do niego w całym kodzie. Na przykład,
zostanie wykryty jako błąd czasu kompilacji (najlepszy przypadek, java itp.) lub oznaczony przez dowolne IDE warte swoich bitów jako zły (najgorszy przypadek, podstawowy itp.).
Ponadto posiadanie pojęcia bycia
left
odniesieniem pomoże ci dostosować się do dowolnego kierunku, w którym zdecydujesz się pójść z typem kierunku. Używając"left"
, kierunek jest zobowiązany do byciaString
. Jeśli znajdziesz lub utworzysz lepszą abstrakcję dla tego typu, musisz przejść do przeszukiwania całego kodu, zmieniając każde wystąpienie"left"
. Stała lub zmienna nie będzie wymagać żadnych zmian, jeśli typ zostanie opracowany.Typ, który naprawdę chcesz, jest specyficzny dla Twojej domeny. Co planuje zrobić z twoim kodem
left
? Być może będziesz chciał wykonać kopię lustrzaną osi x tekstury lub duszka skierowanego w lewo lub poruszającego się do przodu; jeśli tak, możesz chcieć utworzyćleft
obiekt za pomocą właściwości lub metody, która odzwierciedla to zachowanie, a twójright
obiekt ma przeciwny wynik bez dublowania. Możesz wykonać tę logikę w obiekcie reprezentującym duszki lub tekstury, w którym to przypadku ponownie będziesz cierpieć z powodu używania"left"
zamiast zleft
powodów wymienionych powyżej.W Javie (i prawdopodobnie w innych językach, których jeszcze nie znam)
enum
jest dobrą alternatywą, ponieważ w Javieenum
jest równie przydatna, jakfinal class
ze skończonym zestawem instancji. Możesz zdefiniować zachowania, jeśli ich potrzebujesz, i możesz przejść do otwartej klasy bez żadnych kłopotów poza plikiem, który deklarujeenum
, ale wiele języków postrzegaenum
jako prymitywny typ lub wymaga specjalnej składni. To przeciekaenum
kod do kodu, który nie ma z tym nic wspólnego i może wymagać późniejszej korekty.enum
Przed rozważeniem tej opcji upewnij się, że rozumiesz koncepcję swojego języka .źródło
Nie określiłeś swojego języka, ale aby dać ogólną odpowiedź, powinieneś używać ciągów, gdy naprawdę potrzebujesz tekstu, a nie reprezentować coś. Podany przykład, na przykład, byłby po prostu nie do zaakceptowania w oprogramowaniu produkcyjnym.
Każdy język ma różne podstawowe typy danych i powinieneś użyć tego, który jest najbardziej odpowiedni dla zadania. Na przykład możesz użyć stałych numerycznych do reprezentowania różnych stanów. Tak więc lewy mógłby mieć wartość zero, a prawy byłby jeden. Poza wymienionym powodem wartości liczbowe zajmują mniej miejsca (pamięci) i zawsze jest szybsze porównywanie liczb niż porównywanie ciągów znaków.
Jak sugerowano, użyj wyliczeń, jeśli Twój język na to pozwala. W twoim konkretnym przykładzie jest to zdecydowanie lepszy wybór.
źródło
if (uppercase(foo) == "LEFT")
Wystarczy użyć typu danych, który ma sens w danej sytuacji.
Użycie tego
string
typu jako podstawowej komunikacji między aplikacjami nie jest z natury problemem. W rzeczywistości czasem lepiej jest używać ciągów: jeśli masz publiczny interfejs API, może być pożądane, aby wartości wchodzące i wychodzące z interfejsu API były czytelne dla człowieka. Ułatwia osobom używającym interfejsu API naukę i debugowanie.Prawdziwy problem z twoim kodem polega na powtarzaniu wartości.
Nie rób tego:
Jeśli popełniłeś literówkę w jednym z tych warunków lub innym użyciu „pozostawionego” gdzieś, możesz nie być w stanie skutecznie przeprowadzić wyszukiwania w całej bazie kodu, ponieważ źle ją wpisałeś!
Zamiast tego koduj na podstawie wyliczenia lub stałej - w zależności od tego, który obsługuje typ danych, którego potrzebujesz w używanym języku (językach).
Że środki
LEFT
powinny być przypisane do raz i tylko raz w swojej aplikacji. Reszta kodu powinna wykorzystywać te wyliczenia lub stałe:Umożliwia to także łatwiejszą później zmianę typu danych używanych w kierunkach, jeśli tak zdecydujesz.
źródło
Czy to zła praktyka?
Prawdopodobnie tak, ale zależy to dokładnie od tego , co robisz, a także od używanego języka programowania.
W twoim przykładzie możemy wnioskować, że istnieje mały i ustalony na zawsze zestaw wartości, które może przyjąć kierunek. W tym przypadku nie ma żadnych korzyści z używania łańcucha i pewne wyraźne wady. W tym przykładzie:
enum
byłby typ, jeśli Twój język programowania to obsługuje.Ale odpowiedź może być inna, jeśli zbiór wartości można dynamicznie modyfikować lub z czasem musi on ewoluować. W większości języków zmiana
enum
typu (np. Dodanie lub usunięcie wartości) wymaga pełnej ponownej kompilacji. (Na przykład usunięcie wartości wyliczeniowej w Javie psuje zgodność binarną.) To samo dotyczy nazwanych stałych całkowitych.W takich scenariuszach może być wymagane inne rozwiązanie, a użycie ciągów jest jedną z opcji. (I możesz łączyć literały łańcuchowe i nazwane stałe ... jeśli scenariusz zawiera stały rdzeń z dynamicznymi rozszerzeniami.)
Jeśli wdrażasz w Javie,
character.direction == "left"
jest to zła praktyka z innego powodu. Nie powinieneś używać==
do porównywania ciągów, ponieważ testuje to tożsamość obiektu, a nie równość ciągów. (Działałoby, gdybyś mógł zagwarantować, że wszystkie wystąpienia"left"
łańcucha zostały internowane, ale wymaga to analizy całej aplikacji).źródło
String
do przedstawienia kierunków spowodowałoby prawie zerową różnicę w nakładzie pracy związanym z wprowadzeniem zmian. Bardziej rozsądnym podejściem jest założenie, że liczba kierunków się nie zmieni, i uznanie, że miałbyś dużo pracy do zrobienia w obie strony, gdyby zasady gry uległy tak zasadniczej zmianie.Zgodnie z sugestią powinieneś używać Enums. Jednak samo użycie Enum jako zamiennika Strignów nie jest wystarczające IMHO. W twoim przykładzie prędkość gracza powinna być w rzeczywistości wektorem za pomocą fizyki:
Ten wektor powinien następnie zostać użyty do aktualizacji pozycji gracza przy każdym tiku.
Następnie możesz połączyć to z wyliczeniem dla większej czytelności:
źródło