Jesteśmy w trakcie zmiany sposobu, w jaki nasza aplikacja AS3 komunikuje się z naszym zapleczem, i jesteśmy w trakcie wdrażania systemu REST, aby zastąpić nasz stary.
Niestety deweloper, który rozpoczął pracę, jest teraz na długoterminowym zwolnieniu chorobowym i został mi przekazany. Pracowałem z tym przez mniej więcej tydzień i rozumiem system, ale martwi mnie jedna rzecz. Wydaje się, że wiele funkcji przechodzi w funkcje. Na przykład nasza klasa, która wywołuje nasze serwery, przyjmuje funkcję, którą następnie wywoła i przekaże obiekt po zakończeniu procesu i obsłużeniu błędów itp.
Daje mi to „złe przeczucie”, kiedy czuję, że to okropna praktyka. Mogę wymyślić kilka powodów, ale chcę trochę potwierdzenia, zanim zaproponuję przerobienie systemu. Zastanawiałem się, czy ktoś miał jakieś doświadczenie z tym możliwym problemem?
źródło
Odpowiedzi:
To nie jest problem.
To znana technika. Są to funkcje wyższego rzędu (funkcje, które przyjmują funkcje jako parametry).
Ten rodzaj funkcji jest również podstawowym elementem składowym programowania funkcjonalnego i jest szeroko stosowany w językach funkcjonalnych, takich jak Haskell .
Takie funkcje nie są złe ani dobre - jeśli nigdy nie spotkałeś się z pojęciem i techniką, na początku mogą być trudne do uchwycenia, ale mogą być bardzo potężne i są dobrym narzędziem w pasku narzędzi.
źródło
Nie służą tylko do programowania funkcjonalnego. Mogą być również nazywane wywołaniami zwrotnymi :
Pomyśl przez chwilę o kodzie asynchronicznym. Przekazujesz funkcję, która na przykład wysyła dane do użytkownika. Dopiero po zakończeniu kodu wywołujesz tę funkcję z wynikiem odpowiedzi, której następnie używa do wysłania danych z powrotem do użytkownika. To zmiana sposobu myślenia.
Napisałem bibliotekę, która pobiera dane Torrenta z twojego seedboxa. Używasz nieblokującej się pętli zdarzeń, aby uruchomić tę bibliotekę i uzyskać dane, a następnie zwrócić je użytkownikowi (powiedzmy w kontekście websocket). Wyobraź sobie, że masz 5 osób połączonych w tej pętli zdarzeń i jedna z próśb o czyjąś utratę danych. To zablokuje całą pętlę. Musisz więc myśleć asynchronicznie i używać wywołań zwrotnych - pętla nadal działa, a „oddawanie danych użytkownikowi” działa tylko wtedy, gdy funkcja zakończy wykonywanie, więc nie trzeba na nią czekać. Ogień i zapomnij.
źródło
to nie jest zła rzecz. W rzeczywistości jest to bardzo dobra rzecz.
Przekazywanie funkcji do funkcji jest tak ważne w programowaniu, że wymyśliliśmy funkcje lambda jako skrót. Na przykład, można użyć lambdas z algorytmami C ++ do napisania bardzo zwartego, ale ekspresyjnego kodu, który pozwala ogólnemu algorytmowi na użycie zmiennych lokalnych i innych stanów do takich rzeczy jak wyszukiwanie i sortowanie.
Biblioteki obiektowe mogą również zawierać wywołania zwrotne, które są zasadniczo interfejsami określającymi niewielką liczbę funkcji (najlepiej jedną, ale nie zawsze). Następnie można utworzyć prostą klasę, która implementuje ten interfejs i przekazać obiekt tej klasy do funkcji. Jest to podstawa programowania sterowanego zdarzeniami , w którym kod na poziomie frameworku (być może nawet w innym wątku) musi wywoływać obiekt, aby zmienić stan w odpowiedzi na akcję użytkownika. Interfejs ActionListener w Javie jest tego dobrym przykładem.
Z technicznego punktu widzenia funktor C ++ jest także rodzajem obiektu zwrotnego, który wykorzystuje cukier składniowy
operator()()
, aby zrobić to samo.Wreszcie, istnieją wskaźniki funkcji w stylu C, które powinny być używane tylko w C. Nie będę wchodził w szczegóły, po prostu wymieniam je dla kompletności. Pozostałe abstrakcje wymienione powyżej są znacznie lepsze i powinny być używane w językach, które je mają.
Inni wspominali o programowaniu funkcjonalnym i tym, jak przekazywanie funkcji jest bardzo naturalne w tych językach. Lambdas i callbacki to sposób, w jaki naśladują je języki proceduralne i OOP, i są bardzo wydajne i użyteczne.
źródło
Jak już powiedziano, nie jest to zła praktyka. To tylko sposób na oddzielenie i oddzielenie odpowiedzialności. Na przykład w OOP zrobiłbyś coś takiego:
Metoda ogólna polega na delegowaniu określonego zadania - o którym nic nie wie - na inny obiekt, który implementuje interfejs. Metoda ogólna zna tylko ten interfejs. W twoim przypadku ten interfejs byłby funkcją do wywołania.
źródło
Ogólnie rzecz biorąc, nie ma nic złego w przekazywaniu funkcji do innych funkcji. Jeśli wykonujesz połączenia asynchroniczne i chcesz zrobić coś z wynikiem, potrzebujesz jakiegoś mechanizmu oddzwaniania.
Istnieje jednak kilka potencjalnych wad prostych wywołań zwrotnych:
Dzięki prostym usługom internetowym sposób, w jaki to robisz, działa dobrze, ale staje się niewygodny, jeśli potrzebujesz bardziej złożonego sekwencjonowania połączeń. Istnieje jednak kilka alternatyw. Na przykład w JavaScript nastąpiło przesunięcie w kierunku korzystania z obietnic ( co jest takiego wspaniałego w obietnicach javascript ).
Wciąż wiążą się z przekazywaniem funkcji do innych funkcji, ale wywołania asynchroniczne zwracają wartość, która odbiera wywołanie zwrotne zamiast odbierać je bezpośrednio. Daje to większą elastyczność w łączeniu tych połączeń. Coś takiego można dość łatwo zaimplementować w ActionScript.
źródło