Czytałem ten artykuł i zastanawiałem się, czy pozbyliśmy się wszystkich instrukcji zamiany, zastępując je słownikiem lub fabryką, aby w moich projektach nie było żadnych instrukcji switch.
Coś nie do końca się sumowało.
Pytanie brzmi: czy instrukcje przełączające mają jakiekolwiek zastosowanie, czy też zastępujemy je słownikiem lub metodą fabryczną (przy użyciu metody fabrycznej oczywiście do minimalnego wykorzystania instrukcji przełączających do tworzenia obiektów korzystanie z fabryki ... ale o to chodzi).
refactoring
switch-statement
Kanini
źródło
źródło
Odpowiedzi:
Zarówno
switch
oświadczenia, jak i polimorfizm mają swoje zastosowanie. Zauważ jednak, że istnieje również trzecia opcja (w językach, które obsługują wskaźniki funkcji / lambdas i funkcje wyższego rzędu): mapowanie danych identyfikatorów na funkcje obsługi. Jest to dostępne np. W C, który nie jest językiem OO, i C #, który jest *, ale nie (jeszcze) w Javie, która również jest OO *.W niektórych językach proceduralnych (nie posiadających polimorfizmu ani funkcji wyższego rzędu)
switch
/if-else
instrukcje były jedynym sposobem rozwiązania klasy problemów. Tak wielu programistów, przyzwyczajonych do tego sposobu myślenia, nadal używałoswitch
nawet w językach OO, w których polimorfizm jest często lepszym rozwiązaniem. Dlatego często zaleca się unikanie / refaktoryzowanieswitch
oświadczeń na korzyść polimorfizmu.W każdym razie najlepsze rozwiązanie zawsze zależy od wielkości liter. Pytanie brzmi: która opcja daje czystszy, bardziej zwięzły, łatwiejszy w utrzymaniu kod na dłuższą metę?
Instrukcje Switch mogą często stać się niewygodne, mając dziesiątki przypadków, co utrudnia ich utrzymanie. Ponieważ musisz trzymać je w jednej funkcji, funkcja ta może urosnąć. W takim przypadku należy rozważyć refaktoryzację w kierunku rozwiązania opartego na mapie i / lub polimorfii.
Jeśli to samo
switch
zacznie pojawiać się w wielu miejscach, polimorfizm jest prawdopodobnie najlepszą opcją do ujednolicenia wszystkich tych przypadków i uproszczenia kodu. Zwłaszcza jeśli oczekuje się, że w przyszłości pojawi się więcej przypadków; im więcej miejsc trzeba aktualizować za każdym razem, tym więcej możliwości błędów. Często jednak poszczególne procedury obsługi poszczególnych przypadków są tak proste lub jest ich tak wiele lub są tak powiązane, że przefakturowanie ich do pełnej polimorficznej hierarchii klas jest nadmierne lub powoduje wiele powielonych kodów i / lub splątanie, trudno utrzymać hierarchię klas. W takim przypadku może być łatwiej użyć funkcji / lambdas (jeśli Twój język na to pozwala).Jeśli jednak masz
switch
w jednym miejscu, a tylko kilka przypadków robi coś prostego, najlepszym rozwiązaniem może być pozostawienie go takim, jakim jest.* Używam tutaj luźno terminu „OO”; Nie interesują mnie koncepcyjne debaty nad tym, co jest „prawdziwe” lub „czyste” OO.
źródło
W tym miejscu wracam do bycia dinozaurem ...
Instrukcje Switch nie są same w sobie złe, ich użycie jest kwestią sporną.
Najbardziej oczywistym z nich jest „ta sama” instrukcja przełączania powtarzana w kółko przez twój kod, który jest zły (już tam zrobiono, dołożyłbym wszelkich starań, aby nie powtórzyć tego ponownie) - i to w tym ostatnim przypadku możesz być w stanie sobie poradzić z użyciem polimorfizmu. Zwykle jest też coś dość okropnego w zagnieżdżonych skrzynkach (kiedyś miałem absolutnego potwora - nie do końca jestem pewien, jak sobie z tym radzę, poza „lepszym”).
Słownik jako przełącznik Uważam, że jest trudniejszy - zasadniczo tak, jeśli twój przełącznik obejmuje 100% przypadków, ale tam, gdzie chcesz mieć domyślne przypadki braku akcji lub akcji, zaczyna być nieco bardziej interesujący.
Myślę, że chodzi o unikanie powtórzeń i upewnienie się, że tworzymy nasze wykresy obiektowe we właściwych miejscach.
Ale jest też argument zrozumienia (łatwości konserwacji), który ogranicza obie strony - gdy zrozumiesz, jak to wszystko działa (wzorzec i aplikacja, w której jest zaimplementowany), jest to łatwe ... ale jeśli dojdziesz do jednego wiersza kodu, w którym musisz dodać coś nowego, a następnie przeskoczyć w to miejsce, aby ustalić, co musisz dodać / zmienić.
Pomimo tego, że nasze środowiska programistyczne są ogromnie zdolne, nadal uważam, że pożądane jest, aby móc zrozumieć kod (tak jakby to był) wydrukowany na papierze - czy możesz śledzić kod palcem? Akceptuję to w rzeczywistości nie, przy wielu dobrych praktykach dzisiaj nie możesz i z dobrych powodów, ale to oznacza, że trudniej jest zacząć od kodowania (a może jestem po prostu stary ...)
źródło
Stwierdzenia zamiany kontra polimorfizm podtypów to stary problem i często jest przywoływany w społeczności FP w dyskusjach na temat problemu ekspresji .
Zasadniczo mamy typy (klasy) i funkcje (metody). Jak kodujemy rzeczy, aby można było łatwo dodawać nowe typy lub nowe metody?
Jeśli programujesz w stylu OO, trudno jest dodać nową metodę (ponieważ oznaczałoby to refaktoryzację wszystkich istniejących klas), ale bardzo łatwo jest dodać nowe klasy, które używają takich samych metod jak poprzednio.
Z drugiej strony, jeśli użyjesz instrukcji switch (lub jej odpowiednika OO, wzorca obserwatora), wówczas bardzo łatwo będzie dodać nowe funkcje, ale trudno będzie dodać nowe przypadki / klasy.
Nie jest łatwo mieć dobrą rozszerzalność w obu kierunkach, więc pisząc kod, określ, czy chcesz użyć polimorfizmu, czy przełączaj instrukcje, w zależności od tego, w którym kierunku będziesz bardziej skłonny je rozszerzyć.
źródło
Nie. Takie absoluty rzadko są dobrym pomysłem.
W wielu miejscach słownik / wyszukiwanie / fabryka / metoda polimorficzna zapewnia lepszy projekt niż instrukcja switch, ale nadal trzeba wypełnić słownik. W niektórych przypadkach może to zaciemnić to, co się faktycznie dzieje, a zwykłe umieszczenie instrukcji switch w wierszu jest bardziej czytelne i łatwiejsze w utrzymaniu.
źródło
Zważywszy na to, że jest to niezależne od języka, przejściowy kod najlepiej działa z
switch
instrukcjami:Równoważne z
if
, z bardzo niewygodnej przypadku domyślnym. I pamiętaj, że im więcej wpadnie, tym dłużej lista warunków dostanie:(Biorąc jednak pod uwagę to, co mówią niektóre inne odpowiedzi, wydaje mi się, że nie trafiłem w sedno pytania ...)
źródło
switch
a jest takie samogoto
. Jeśli algorytm, który ma zostać wykonany, wymaga przepływów sterowania, które pasują do strukturalnych struktur programowania, należy użyć takich konstrukcji, ale jeśli algorytm nie pasuje do takich konstrukcji, użyciegoto
może być lepsze niż próba dodania flag lub innej logiki sterowania w celu dopasowania do innych struktur kontroli .Instrukcje przełączające, ponieważ rozróżnianie wielkości liter ma rzeczywiste zastosowanie. Funkcjonalne języki programowania używają czegoś, co nazywa się dopasowywaniem wzorców, co pozwala definiować funkcje w różny sposób w zależności od wprowadzanych danych. Jednak w językach obiektowych ten sam cel można osiągnąć bardziej elegancko, stosując polimorfizm. Po prostu wywołujesz metodę, a w zależności od faktycznego typu obiektu zostanie wykonana odpowiednia implementacja metody. To jest przyczyna tego, że instrukcje switch mają zapach kodu. Jednak nawet w językach OO mogą okazać się przydatne do implementacji abstrakcyjnego wzorca fabrycznego.
tl; dr - są przydatne, ale dość często można to zrobić lepiej.
źródło