Kiedy haki są właściwym wyborem?

10

Pracowałem nad dużą aplikacją Rails, w której korzystanie z funkcji zwrotnych ActiveRecord było powszechne i wstrząsające. Zapisanie rekordu często miało nieoczekiwane skutki uboczne i uzasadnienie systemu było wyzwaniem.

Jednocześnie widziałem, jak haczyki przynoszą dobre efekty w ramach dziedziczenia (np. Klasa nadrzędna używa metody szablonowej, aby umożliwić podklasom dodawanie wyspecjalizowanych zachowań bez konieczności znajomości wewnętrznych elementów nadrzędnych) oraz wtyczek (np. tryb emacs uruchamiający hak, gdy jest aktywowany, umożliwiając użytkownikom dodawanie niestandardowych zachowań wokół tego trybu).

Zdaję sobie sprawę, że aplikacja Rails i interpreter Lisp to bardzo różne systemy, ale jestem ciekawy, czy istnieją jakieś dobrze znane kryteria, na które ludzie zwracają uwagę przy podejmowaniu decyzji, czy haki są właściwym wyborem projektowym dla napotkanego problemu.

Wyskakuje na mnie temat przewidywalności. Niewłaściwe użycie haków wydaje się prowadzić do upiornej akcji na odległość i zaskakującego zachowania, podczas gdy dobre użycie może prowadzić do struktury, która jest przewidywalna bez ścisłego połączenia.

Ponieważ jestem jeszcze zaledwie kilka lat w mojej karierze programistycznej, pod wieloma względami uważam się za nooba i podejrzewam, że ludzie w tym temacie poświęcili wiele uwagi. Jakie wytyczne mogą pokierować tą decyzją?

ivan
źródło

Odpowiedzi:

5

Haki są dobrym wyborem projektowym, jeśli chcesz oddzielić szczegóły implementacji abstrakcji od jej konsumentów, przenosząc kontrolę na odbiorniki haka.

Możesz to zrobić przez anonimową transmisję (jak zdarzenia lub anonimowe wywołania zwrotne) lub za pomocą wpisanych abstrakcji (takich jak interfejsy lub klasy nadrzędne).

Powinieneś używać anonimowej transmisji, gdy:

  • Wywołanie haka jest opcjonalne
  • Dzwoniącego nie obchodzi, kto odbiera połączenie.
  • Kolejność wykonania odbiorników jest nieistotna.
  • Chcesz rozgłaszać stan obiektu do wszystkich subskrybentów zaczepu.

Powinieneś użyć wpisanej abstrakcji, gdy:

  • Wywołanie haka jest obowiązkowe.
  • Obiekt wywołujący musi zidentyfikować odbiornik haka.
  • Kolejność wykonania odbiorników jest odpowiednia dla twojego obiektu.

Przykładem haka rozgłoszeniowego jest KeyPressedEvent. Klasa odpalająca zdarzenie nie dba o to, kto je odbierze, i nadaje status klawiatury każdemu, kto subskrybuje to wydarzenie. Kolejność wykonania odbiorników nie ma wpływu na stan obiektu klasy odpalającej zdarzenie.

Przykładem typowanego haczyka abstrakcyjnego jest wspomniana metoda szablonu. W tym przypadku klasa nadrzędna wymaga implementacji metod szablonów, wie, że odbiorcy będą jej potomkami, i ma określoną kolejność wykonywania metod szablonów, zgodnie z definicją klasy nadrzędnej.

Cesar Hernandez
źródło
7

Większość języków i większość platform używa zaczepiania, nawet jeśli jest przebrana za coś innego. Ilekroć słyszysz termin „zdarzenie”, „komunikat”, „wyzwalacz”, „sygnał” lub inne tego rodzaju określenia, prawdopodobnie masz do czynienia z przechwytywaniem, chociaż istnieją wyjątki od reguły, które prawdopodobnie nie ważne dla tej dyskusji.

Korzystasz z nich, ponieważ platforma udostępnia je tobie, a może nawet wymaga ich użycia ze względu na wydajność. Korzystanie z haków często zmniejsza złożoność kodu, pomaga egzekwować wymagania biznesowe oraz zmniejsza zużycie procesora, wydłużając żywotność baterii i sprzętu. Powinieneś ich używać, gdy chcesz uzyskać najlepszą wydajność kodu.

Nawet twoje wstrząsające doświadczenie z Railsami w dużej mierze wskazuje na typowy przypadek użycia haków: reguły biznesowe muszą być egzekwowane, a haki są powszechnie stosowane do egzekwowania reguł biznesowych. Niestety, nie wszystkie reguły mają sens i, jak można powiedzieć, utrudnia to programistom, gdy są arbitralne, ale dlatego dokumentacja systemu jest tak samo ważna jak sam kod.

Zasadniczo używaj haków, ponieważ są one funkcjami wydajności i sprawią, że Twój kod będzie działał wydajniej niż alternatywa (która nazywa się „odpytywaniem”, gdzie czekasz w zajętej pętli, aby sprawdzić zdarzenia). Jednak upewnij się również, że używasz odpowiedniej dokumentacji i aktualizujesz ją. Haki są używane w praktycznie każdym języku, z którym się spotkasz, i ważne jest, aby wiedzieć, dlaczego one istnieją.

phyrfox
źródło
1

Wcześniej pracowałem nad programem, który moim zdaniem dobrze wykorzystał haki. W mojej książce prawdziwym hakiem jest wywołanie (publikacja) do listy oddzwaniania (subskrybentów). Jest potężny, znęcanie się jest łatwe. Najlepszym pytaniem, które należy zadać w przypadku użycia, jest: czy chcę włączyć lub wyłączyć zachowanie w czasie wykonywania? Na przykład możesz zezwolić użytkownikom na dostarczanie skryptów uruchamianych przy określonych zdarzeniach lub stworzyć ogólny program złożony z mniejszych wtyczek. Wtedy odpowiednie są połączenia przechwytujące. Ogólnie rzecz biorąc, masz niewiele innych opcji.

Jeśli nie, powinieneś uciec od dobrego łuku swoich modułów. Metody szablonów działają dobrze z przeciążonymi funkcjami, do tego nie jest potrzebna logika działania. Pomyśl, że wymusiłoby to luźne połączenie jest iluzją: istnieje taki sam poziom zależności między czymś, co dzwonisz bezpośrednio lub chwytasz, odbiorca i tak musi wypełnić swój kontrakt.

Zauważ, że być może niektórzy ludzie nazywają metodę szablonów z przeciążonymi funkcjami, ale to różni się od powyższego: tutaj masz statyczne powiązanie, z mniejszym ryzykiem dostania się w koszmar konserwacji.

Arthur Havlicek
źródło