goto
jest prawie powszechnie odradzany. Czy korzystanie z tego oświadczenia jest kiedykolwiek opłacalne?
goto
programming-practices
Casebash
źródło
źródło
goto
jest tym, co ostatecznie robią procesory, ale to nie działa dobrze z tym, co ludzie muszą zrozumieć i abstrakcyjnie, ponieważ nie ma śladu na docelowym końcu. Porównaj z IntercalCOMEFROM
.goto
nie jest wymagane. Jest to po prostu najbardziej racjonalny sposób implementacji ich w imperatywnych językach, ponieważ jest najbliżej samej semantyki przejścia państwowego. A jego miejsce docelowe może znajdować się dość daleko od źródła, nie utrudni to czytelności. Moim ulubionym przykładem takiego kodu jest implementacja gry przygodowej DE Knuth.Odpowiedzi:
Zostało to kilkakrotnie omówione na temat przepełnienia stosu, a Chris Gillum podsumował możliwe zastosowania
goto
:Twierdziłbym, podobnie jak wielu innych, że we wszystkich tych przypadkach użycie
goto
jest używane jako sposób na wydostanie się z zakątka, w który się zakodowano, i ogólnie jest objawem kodu, który można by zrefaktoryzować.źródło
finally
bloków we współczesnych językach, a drugi rozwiązany jest przez oznaczeniebreak
s. Jeśli jednak utkniesz z C,goto
jest to właściwie jedyny sposób na eleganckie rozwiązanie tych problemów.finally
jest poprawne tylko w tych warunkach. Istnieją bardzo rzadkie, ale ważne sytuacje, w których goto jest najlepszym rozwiązaniem.break 3
lubbreak myLabel
igoto myLabel
. Och, właśnie to słowo kluczowe. Jeśli używaszbreak
,continue
lub jakiś podobny kluczowe jesteś rzeczywiście użyciugoto
(jeśli używaszfor, while, foreach, do/loop
używasz warunkową Goto.)Konstrukcje przepływów sterowania wyższego poziomu zwykle odpowiadają pojęciom w dziedzinie problemów. If / else jest decyzją opartą na pewnych warunkach. Pętla mówi, aby powtarzać pewne działania. Nawet stwierdzenie przerwania mówi: „robiliśmy to wielokrotnie, ale teraz musimy przestać”.
Z drugiej strony instrukcja goto zwykle odpowiada koncepcji w uruchomionym programie, a nie w dziedzinie problemów. Mówi, aby kontynuować wykonywanie w określonym punkcie programu . Ktoś czytający kod musi wywnioskować, co to oznacza w odniesieniu do domeny problemu.
Oczywiście wszystkie konstrukcje wyższego poziomu można zdefiniować w kategoriach gotos i prostych gałęzi warunkowych. To nie znaczy, że są tylko głupcami w przebraniu. Pomyśl o nich jako o ograniczonych gotosach - i to dzięki ograniczeniom są one przydatne. Instrukcja break jest implementowana jako przeskok na koniec otaczającej pętli, ale lepiej jest myśleć o niej jako o działaniu na całej pętli.
Wszystkie pozostałe elementy są jednakowe, kod, którego struktura odzwierciedla strukturę problematycznej domeny, jest zwykle łatwiejszy do odczytania i utrzymania.
Nie ma przypadków, w których instrukcja goto jest absolutnie wymagana (istnieje takie twierdzenie ), ale są przypadki, w których może to być najmniej złe rozwiązanie. Przypadki te różnią się w zależności od języka, w zależności od tego, jakie konstrukcje wyższego poziomu obsługują język.
Na przykład w C uważam, że istnieją trzy podstawowe scenariusze, w których goto jest odpowiednie.
Z drugiej strony, jawną maszynę skończoną można również zaimplementować za pomocą instrukcji switch wewnątrz pętli. Ma to tę zaletę, że każdy stan zaczyna się w tym samym miejscu w kodzie, co może być przydatne na przykład przy debugowaniu.
Głównym zastosowaniem goto w dość nowoczesnym języku (takim, który obsługuje if / else i pętle) jest symulacja konstrukcji przepływu sterowania, której brakuje w tym języku.
źródło
goto
. SSSM to często dobre struktury do użycia, ponieważ oddzielają stan SM od konstrukcji wykonawczej, ale tak naprawdę nie eliminują „gotos”.Z pewnością zależy to od języka programowania. Główny powód
goto
budził kontrowersje ze względu na jego złe skutki, które pojawiają się, gdy kompilator pozwala na zbyt swobodne korzystanie z niego. Mogą pojawić się problemy, na przykład, jeśli pozwala to na użyciegoto
w taki sposób, że można teraz uzyskać dostęp do niezainicjowanej zmiennej lub, co gorsza, przejść do innej metody i zadzierać ze stosem wywołań. Kompilator powinien być odpowiedzialny za niedopuszczenie do bezsensownego przepływu sterowania.Java podjęła próbę „rozwiązania” tego problemu poprzez
goto
całkowite niedozwolenie . Jednak Java pozwala używaćreturn
wewnątrzfinally
bloku, a tym samym powoduje przypadkowe połknięcie wyjątku. Nadal występuje ten sam problem: kompilator nie wykonuje swojej pracy. Usunięciegoto
z języka nie naprawiło tego.W języku C #,
goto
jest równie bezpieczna jakbreak
,continue
,try/catch/finally
ireturn
. Nie pozwala używać niezainicjowanych zmiennych, nie pozwala wyskoczyć z bloku w końcu itp. Kompilator będzie narzekał. Jest tak, ponieważ rozwiązuje prawdziwy problem, który jest jak powiedziałem nonsensowny przepływ kontroli.goto
nie magicznie anuluje analizy określonego przypisania i innych uzasadnionych kontroli kompilatora.źródło
goto
nie jest zły? Jeśli tak, dotyczy to każdego rutynowo używanego współczesnego języka zgoto
konstrukcją, nie tylko C # ...Tak. Gdy twoje pętle są zagnieżdżone na kilku poziomach,
goto
jest to jedyny sposób na eleganckie wyrwanie się z wewnętrznej pętli. Inną opcją jest ustawienie flagi i wyłamanie się z każdej pętli, jeśli flaga spełnia warunek. To jest naprawdę brzydkie i dość podatne na błędy. W takich przypadkachgoto
jest po prostu lepszy.Oczywiście, etykieta Javy
break
robi to samo, ale nie pozwala przeskoczyć do dowolnego punktu w kodzie, co rozwiązuje problem starannie, nie dopuszczając rzeczy, które powodujągoto
zło.źródło
Do
pętla. Czemu? Ponieważ mogę zmienić jedną pętlę, która wymaga głębokiego przerwania wDo
pętli i pisania,Exit Do
i nie maGoTo
. Zagnieżdżone pętle zdarzają się cały czas. Przełamywanie stosów zdarza się przez pewien czas.Większość zniechęcenia pochodzi z pewnego rodzaju „religii”, która została stworzona przez Boga Djikstrę, która na początku lat 60. przekonała o swojej masowej mocy do:
Nie ma to nic więcej wspólnego z
goto
wypowiedzią współczesnych języków, których istnienie jest po prostu spowodowane wspieraniem tworzenia struktur kodu innych niż te dostarczone przez język.W szczególności pierwszy główny punkt powyżej jest już dozwolony, a drugi jest czyszczony (jeśli wyjdziesz
goto
z bloku, stos jest odpowiednio rozwijany i wywoływane są wszystkie odpowiednie niszczyciele)Możesz odnieść się do tej odpowiedzi, aby zorientować się, w jaki sposób nawet kod nieużywający goto może być nieczytelny. Problemem nie jest samo goto, ale jego złe użycie.
Mogę napisać cały program bez użycia
if
, tylkofor
. Oczywiście nie będzie dobrze czytelny, nieporadny i niepotrzebnie skomplikowany.Ale problem nie jest
for
. To ja.Rzeczy takie jak
break
,continue
,throw
,bool needed=true; while(needed) {...}
, itd. Są odnotowując ponad maskaradygoto
, aby uciec z dala od jataganów tych Djikstrarian fanatyków, że -50 lat po wynalezieniu nowoczesnego laguages- nadal chcą ich więźniów. Zapomnieli o czym mówił Djikstra, pamiętają tylko tytuł jego notatki (GOTO uważał ją za szkodliwą, a nawet nie był to jego tytuł: został zmieniony przez redaktora) i obwiniają, uderzają, uderzają i obwiniają każdy contruct posiadający te 4 litera umieszczona w sekwencji.Jest rok 2011: nadszedł czas, aby zrozumieć, że zauważono,
goto
żeGOTO
Djikstra była przekonująca.źródło
break n
nie jest dostępna w C ++, dlategogoto escape
nawet jeśliescape
nie jest wymagane, aby była po prostu poza pętlą n-ple.Dziwne goto tu czy tam, o ile jest lokalne dla funkcji, rzadko znacząco szkodzi czytelności. Często przynosi to korzyści, zwracając uwagę na fakt, że w tym kodzie dzieje się coś niezwykłego, co wymaga użycia nieco nietypowej struktury kontrolnej.
Jeśli (lokalne) goto znacznie szkodzą czytelności, oznacza to zwykle, że funkcja zawierająca goto stała się zbyt złożona.
Ostatnim goto, które umieściłem w kodzie C było zbudowanie pary blokujących się pętli. Nie pasuje do normalnej definicji „akceptowalnego” użycia goto, ale w rezultacie funkcja okazała się znacznie mniejsza i wyraźniejsza. Aby uniknąć goto, wymagałoby to szczególnie niechlujnego naruszenia SUSZENIA.
źródło
Myślę, że cała ta sprawa dotyczy szczekania niewłaściwego drzewa.
GOTO jako takie nie wydaje mi się problematyczne, ale raczej bardzo często jest to objaw prawdziwego grzechu: kod spaghetti.
Jeśli GOTO powoduje poważne przecięcie linii kontroli przepływu, to źle, kropka. Jeśli nie przecina linii kontroli przepływu, jest nieszkodliwy. W szarej strefie pomiędzy mamy takie rzeczy jak ratowanie pętli, wciąż istnieje kilka języków, które nie dodały konstrukcji, które obejmują wszystkie uzasadnione szare przypadki.
Jedynym przypadkiem, z którego faktycznie korzystam od wielu lat, jest przypadek pętli, w której punkt decyzyjny znajduje się w środku pętli. Pozostaje Ci powielony kod, flaga lub GOTO. Uważam, że rozwiązanie GOTO jest najlepsze z trzech. Nie ma tu przecięcia linii kontroli przepływu, jest nieszkodliwy.
źródło
goto
który przeskakuje do pętli (jeśli język na to pozwala; od drugiego przypadku skacze poza pętlą w środku, jest zwykle trywialny bezgoto
).goto
krzyczę TUTAJ PRZEPŁYW STERUJĄCY NIE PASUJE DO NORMALNYCH WZORÓW PROGRAMOWANIA STRUKTURALNEGO . Ponieważ przepływy kontroli, które pasują do strukturalnych schematów programowania, są łatwiejsze do uzasadnienia niż te, które tego nie robią, należy w miarę możliwości próbować wykorzystywać takie wzorce; jeśli kod pasuje do takich wzorców, nie należy krzyczeć, że tak nie jest. Z drugiej strony, w przypadkach, gdy kod naprawdę nie pasuje do takich wzorców, wykrzykiwanie go może być lepsze niż udawanie, że kod pasuje, kiedy tak naprawdę nie jest.Tak, goto można wykorzystać, aby skorzystać z doświadczenia programisty: http://adamjonrichardson.com/2012/02/06/long-live-the-goto-statement/
Jednak, podobnie jak w przypadku każdego potężnego narzędzia (wskaźniki, wielokrotne dziedziczenie itp.), Trzeba zdyscyplinować się przy jego użyciu. Przykład podany w linku używa PHP, który ogranicza użycie konstrukcji goto do tej samej funkcji / metody i wyłącza możliwość przeskakiwania do nowego bloku kontrolnego (np. Pętla, instrukcja switch itp.)
źródło
Zależy od języka. Na przykład jest nadal szeroko stosowany w programowaniu Cobola. Pracowałem również na urządzeniu Barionet 50, którego językiem programowania oprogramowania jest wczesny dialekt BASIC, który oczywiście wymaga użycia Goto.
źródło
Powiedziałbym „nie”. Jeśli zauważysz potrzebę korzystania z GOTO, założę się, że istnieje potrzeba przeprojektowania kodu.
źródło
goto
może być przydatny podczas przenoszenia starszego kodu asemblera do C. W pierwszej kolejności konwersja instrukcja po instrukcji do C, wykorzystującagoto
jako zamiennik instrukcji asemblerabranch
, może umożliwić bardzo szybkie przenoszenie.źródło
Twierdziłbym, że nie. Powinny zawsze być zastąpione narzędziem bardziej specyficznym dla problemu, do którego rozwiązania goto jest używany (chyba że nie jest dostępny w twoim języku). Na przykład instrukcje break i wyjątki rozwiązują wcześniej rozwiązane problemy ucieczki pętli i obsługi błędów.
źródło
goto
zwykle nie ma ich w tych językach.goto
najbliższa jest bardzo problematyczna semantyka domeny, wszystko inne byłoby brudnym włamaniem.