Ok, wiem, że tytuł tego pytania jest prawie identyczny jak Kiedy powinienem używać programowania opartego na zdarzeniach? ale odpowiedzi na to pytanie nie pomogły mi zdecydować, czy powinienem wykorzystać wydarzenia w konkretnym przypadku, w którym się znajduję.
Tworzę małą aplikację. Jest to prosta aplikacja i w większości jej funkcjonalność jest podstawową CRUD.
Po określonych zdarzeniach (podczas modyfikacji niektórych danych) aplikacja musi zapisać lokalną kopię tych danych w pliku. Nie jestem pewien, jaki jest najlepszy sposób na wdrożenie tego. Mogę:
- Uruchom zdarzenia, gdy dane zostaną zmodyfikowane i powiąż odpowiedź (wygeneruj plik) z takimi zdarzeniami. Alternatywnie, zaimplementuj wzorzec obserwatora. To wydaje się niepotrzebną złożonością.
- Wywołaj kod generujący plik bezpośrednio z kodu, który modyfikuje dane. O wiele prostsze, ale wydaje się błędne, że zależność powinna być w ten sposób, to znaczy wydaje się błędne, że podstawowa funkcjonalność aplikacji (kod modyfikujący dane) powinna być połączona z tym dodatkowym profitem (kod, który generuje plik kopii zapasowej). Wiem jednak, że ta aplikacja nie rozwinie się do punktu, w którym to połączenie stanowi problem.
Jakie jest najlepsze podejście w tym przypadku?
Odpowiedzi:
Postępuj zgodnie z zasadą KISS: zachowaj prostotę, głupotę lub zasadę YAGNI: nie będziesz jej potrzebować.
Możesz napisać kod taki jak:
Lub możesz napisać kod taki jak:
W przypadku braku istotnego powodu, aby zrobić inaczej, wybierz prostszą drogę. Techniki takie jak obsługa zdarzeń są potężne, ale zwiększają złożoność kodu. Do działania wymaga więcej kodu i utrudnia śledzenie tego, co dzieje się w kodzie.
Zdarzenia są bardzo krytyczne w odpowiedniej sytuacji (wyobraź sobie próbę programowania interfejsu użytkownika bez zdarzeń!) Ale nie używaj ich, gdy możesz zamiast tego KISS lub YAGNI.
źródło
Przykład opisujący proste dane, w którym modyfikacja wywołuje pewien efekt, można doskonale zaimplementować za pomocą wzorca projektowego obserwatora :
Podejście oparte na zdarzeniach jest warte inwestycji w bardziej złożone scenariusze, w których może wystąpić wiele różnych interakcji, w kontekście wielu do wielu, lub jeśli przewiduje się reakcje łańcuchowe (np. Pacjent informuje obserwatora, który w niektórych przypadkach chce zmodyfikować temat lub inne przedmioty)
źródło
Jak mówisz, wydarzenia są doskonałym narzędziem do zmniejszania sprzężenia między klasami; więc chociaż może wymagać pisania dodatkowego kodu w niektórych językach bez wbudowanej obsługi zdarzeń, zmniejsza złożoność dużego obrazu.
Zdarzenia są prawdopodobnie jednym z najważniejszych narzędzi w OO (według Alana Kay - Obiekty komunikują się poprzez wysyłanie i odbieranie wiadomości ). Jeśli używasz języka, który ma wbudowane wsparcie dla wydarzeń lub traktuje funkcje jak pierwszorzędni obywatele, korzystanie z nich nie stanowi problemu.
Nawet w językach bez wbudowanego wsparcia ilość płyty kotłowej dla czegoś takiego jak wzór Observer jest dość minimalna. Możesz znaleźć gdzieś przyzwoitą bibliotekę zdarzeń ogólnych, której możesz użyć we wszystkich swoich aplikacjach, aby zminimalizować płytę kotłową. (Ogólny agregator zdarzeń lub mediator zdarzeń jest przydatny w prawie każdym rodzaju aplikacji).
Czy warto w małej aplikacji? Powiedziałbym zdecydowanie tak .
Jeśli myślisz „Och, ale to naprawdę bardzo mała aplikacja, to tak naprawdę nie ma tak wielkiego znaczenia” , zastanów się:
Ogólnie rzecz biorąc, rozmiar aplikacji nie powinien decydować o tym, czy klasy powinny być luźno powiązane; Zasady SOLID dotyczą nie tylko dużych aplikacji, ale mają zastosowanie do oprogramowania i baz kodów w dowolnej skali.
W rzeczywistości czas zaoszczędzony na testowaniu jednostek luźno powiązanych klas w oderwaniu powinien równoważyć każdy dodatkowy czas spędzony na oddzieleniu tych klas.
źródło
Wzorzec obserwatora można zaimplementować w znacznie mniejszy sposób niż opisuje go artykuł w Wikipedii (lub książka GOF), zakładając, że języki programowania obsługują coś w rodzaju „oddzwaniania” lub „delegatów”. Po prostu przekaż metodę zwrotną do swojego kodu CRUD (metoda obserwatora, która może być albo ogólną metodą „zapisu do pliku”, albo pustą). Zamiast „odpalenia zdarzenia” wystarczy wywołać to wywołanie zwrotne.
Wynikowy kod będzie tylko minimalnie bardziej skomplikowany niż bezpośrednie wywołanie kodu generującego plik, ale bez wad ścisłego łączenia niepowiązanych ze sobą komponentów.
To przyniesie ci „najlepsze z obu światów”, bez poświęcania oddzielenia dla „YAGNI”.
źródło