Czy zdarzenia są używane tylko do programowania GUI?

57

Czy zdarzenia są używane tylko do programowania GUI?

Jak sobie radzisz w normalnym programowaniu zaplecza, gdy coś dzieje się z tą inną rzeczą?

użytkownik3093620
źródło
6
Nawiasem mówiąc, Event Source to całkowicie ortogonalna koncepcja programowania zdarzeń. Podstawową koncepcją Event Sourcing jest przechowywanie „zdarzeń” lub „zmian” w systemie zamiast przechowywania „stanu” systemu. Na przykład możesz modelować swoje konto bankowe jako a) Twoje saldo (STAN) lub b) Seria transakcji (EVENTSOURCE).
ArTs,
4
W zależności od użycia „zdarzenie” jest zwykle tylko rodzajem wywołania zwrotnego owiniętego cukrem. Połączenia zwrotne są używane wszędzie - jeśli jesteś zainteresowany, to prawdopodobnie dobre słowo kluczowe, aby rozpocząć wyszukiwanie.
J ...
10
Zwrócę też uwagę, że nawet jeśli przejdziesz na tak niski poziom jak mikrokontroler, przekonasz się, że sprzęt zakłóca użyteczną i dyskusyjnie istotną funkcję. Doskonały do ​​systemów sterowania lub podstawowych operacji we / wy, takich jak ekspres do kawy. Te przerwania sprzętowe tak naprawdę nie różnią się zasadniczo od zdarzeń.
Dan
Nie! Praktyczny przykład: wydarzenia
Nodejsa
2
Czy korzystasz z systemu Windows? Sprawdź Podgląd zdarzeń. Baw się dobrze.
Marc.2377,

Odpowiedzi:

106

Nie. Są naprawdę przydatne do wdrażania obserwatorów i upewnienia się, że klasy są zamknięte na modyfikacje.

Powiedzmy, że mamy metodę rejestrującą nowych użytkowników.

public void Register(user) {
    db.Save(user);
}

Następnie ktoś decyduje, że należy wysłać wiadomość e-mail. Możemy to zrobić:

public void Register(user) {
    db.Save(user);
    emailClient.Send(new RegistrationEmail(user));
}

Ale właśnie zmodyfikowaliśmy klasę, która powinna być zamknięta na modyfikacje. Prawdopodobnie w porządku dla tego prostego pseudokodu, ale prawdopodobnie droga do szaleństwa w kodzie produkcyjnym. Ile czasu zajmuje ta metoda do 30 wierszy kodu, które ledwo związane są z pierwotnym celem stworzenia nowego użytkownika?

O wiele przyjemniej jest pozwolić klasie na wykonanie swojej podstawowej funkcji i wywołać zdarzenie informujące każdego, kto nasłuchuje, że użytkownik jest zarejestrowany, i że może podjąć wszelkie niezbędne działania (na przykład wysłać wiadomość e-mail).

public void Register(user) {
    db.Save(user);

    RaiseUserRegisteredEvent(user);
}

Dzięki temu nasz kod jest czysty i elastyczny. Jednym z często pomijanych elementów OOP jest to, że klasy wysyłają do siebie wiadomości . Wydarzenia to te wiadomości.

Gumowa kaczuszka
źródło
37
Czytam to i myślę o naszym kodzie „Stwórz rezerwację” i płaczę przez chwilę i tęsknię za lepszym miejscem: '(
sara,
1
+1, świetna odpowiedź. Tylko styczne pytanie (trochę mnie to niepokoiło): czy istnieje jakiś szczególny powód, dla którego zacząłeś nazwy metod (Zarejestruj, Zapisz i Wyślij) dużymi literami? Oczywiście nie wpływa to jednak na użyteczność tej odpowiedzi.
Pedro A
14
@Hamsteriffic Jestem głównie deweloperem C # i to jest ogólnie przyjęta konwencja. Nie ma innego powodu.
RubberDuck,
6
@Hamster to dodatek, który nazywasz lowerCase, ale zawiera duże litery na środku, często nazywa się camelCase, ponieważ ma garby na środku. To odróżnia go od snake_case, gdzie małe litery są oddzielone podkreślnikami, które są znane z Pythona i większości języków powłoki, aby wymienić tylko kilka.
Aaron,
5
Zdarzenia są jednym z tych komunikatów, powiedziałbym. Wywołania metod należy również traktować jako przekazywanie wiadomości.
jpmc26,
53

Nie.

Klasycznym przykładem zdarzeń wykorzystywanych w logice innej niż GUI są wyzwalacze bazy danych.

Wyzwalacze to kod, który jest wykonywany, gdy zdarzenie ma miejsce (WSTAW, USUŃ itp.). Wydaje mi się wydarzeniem.

Oto definicja wydarzenia z Wikipedii:

W informatyce zdarzenie to czynność lub zdarzenie rozpoznawane przez oprogramowanie, które może być obsługiwane przez oprogramowanie. Zdarzenia komputerowe mogą być generowane lub wyzwalane przez system, przez użytkownika lub w inny sposób. Zazwyczaj zdarzenia są obsługiwane synchronicznie z przebiegiem programu, co oznacza, że ​​oprogramowanie może mieć jedno lub więcej dedykowanych miejsc, w których zdarzenia są obsługiwane, często pętla zdarzeń. Źródłem zdarzeń jest użytkownik, który może wchodzić w interakcje z oprogramowaniem, na przykład naciskając klawisze na klawiaturze. Innym źródłem jest urządzenie sprzętowe, takie jak zegar. Oprogramowanie może również wyzwalać własny zestaw zdarzeń w pętli zdarzeń, np. W celu zakomunikowania zakończenia zadania. Mówi się, że oprogramowanie, które zmienia swoje zachowanie w odpowiedzi na zdarzenia, jest sterowane zdarzeniem, często w celu interaktywności.

Nie wszystkie zdarzenia są generowane przez użytkowników. Niektóre są generowane przez licznik czasu, taki jak crontab, z bazy danych INSERT, jak wspomniałem wcześniej.

Definicja stwierdza również, że niektóre programy lub systemy są „sterowane zdarzeniami, często w celu interaktywności” , z czego można wywnioskować, że celem lub użytecznością zdarzeń nie jest wyłącznie, ale raczej często zapewnienie interaktywności (jak GUI chociaż niekoniecznie GUI, ponieważ programy CLI mogą być również interaktywne).

Tulains Córdova
źródło
2
Zawsze o tym myślę, gdy słyszę o wyzwalaczach bazy danych: thecodelesscode.com/case/42
Almo
Jako były programista DBA teraz kulę się za każdym razem, gdy słyszę, jak ludzie mówią o używaniu wyzwalaczy, nie biorąc pod uwagę szerszej wydajności DB.
Three Value Logic
28

Programowanie oparte na zdarzeniach jest również używane do bardzo wydajnego programowania serwerów.

Przy typowym obciążeniu serwera większość czasu przetwarzania wyniku pochodzi w rzeczywistości z operacji we / wy. Na przykład ściąganie danych z dysku twardego (7200 obr./min) może potrwać do 8,3 ms. W przypadku nowoczesnego procesora GHz byłoby to około 1 miliona cykli zegara. Gdyby CPU za każdym razem czekał na dane (nic nie robiąc), stracilibyśmy DUŻO cykli zegara.

Tradycyjne techniki programowania omijają ten problem, wprowadzając wiele wątków . Procesor próbuje uruchomić setki wątków jednocześnie. Problem polega jednak na tym, że za każdym razem, gdy procesor przełącza wątek, do przełączenia kontekstu potrzeba setek cykli zegara . Zmiana kontekstu ma miejsce, gdy CPU kopiuje lokalną pamięć wątków do rejestrów CPU, a także zapisuje rejestr / stan starego wątku w pamięci RAM.

Dodatkowo każdy wątek musi zużywać pewną ilość pamięci do przechowywania swojego stanu.

Dzisiaj nastąpił nacisk na serwery, które mają jeden wątek, który działa w pętli. Następnie prace są przekazywane do pompy komunikatów , która działa jak kolejka dla pojedynczego wątku (podobnie jak w wątku interfejsu użytkownika). Zamiast czekać na zakończenie pracy, CPU ustawia zdarzenie wywołania zwrotnego, na przykład na dostęp do dysku twardego. Co zmniejsza przełączanie kontekstu.

Najlepszym przykładem takiego serwera jest Node.js , który, jak wykazano, jest w stanie obsłużyć 1 milion jednoczesnych połączeń przy użyciu skromnego sprzętu, podczas gdy serwer Java / Tomcat miałby problemy z kilkoma tysiącami.

ArTs
źródło
2
„Skromny sprzęt” jest trochę mylący. Będziesz potrzebował 8 GB + na Węzeł, oprócz tego, czego używa system operacyjny. A jeśli masz tyle pamięci, Tomcat może z łatwością obsłużyć kilka tysięcy połączeń. To prawda, istnieje duża różnica, ale nie jest to 1000x.
Paul Draper,
@PaulDraper nie, nie może. I nie, nie ma. Potrzebujesz 8 GB + tylko na stos dla 8000 wątków. To jest duża różnica.
ArTs,
3
@PaulDraper poza 8 GB jest bardzo skromny jak na standardy serwerów. Pracowałem na maszynach z 128 GB pamięci RAM, a te nie są nawet w pełni załadowane. Tyczki ramowe kosztują więcej niż cała maszyna.
ArTs,
zależy to od twojego rozmiaru stosu. Oracle / OpenJDK domyślnie wynosi 1 MB na większości platform dla wersji 64-bitowej i 512 KB dla wersji 32-bitowej. Jeśli po prostu weźmiesz wartości domyślne, będziesz poprawny. Ale domyślnie nie chodzi o to, jak dostać się do połączeń z węzłem 1M;) W każdym razie 128K to dużo; możesz uciec jeszcze mniej. To byłoby 1 GB miejsca na stosie na 8000 wątków.
Paul Draper,
6
Jesteś błędny. Nawet przy domyślnym rozmiarze stosu potrzebujesz tylko 8 GiB pamięci wirtualnej . W razie potrzeby pamięć jest przydzielana w locie. Zwykle potrzebujesz tylko jednej strony na stos, chyba że faktycznie używasz dodatkowej pamięci. I w praktyce większość wątków w takim systemie ma tylko te (zwykle) stosy 64-kiB. Wykorzystanie pamięci wirtualnej to wielka sprawa w 32-bitowym systemie operacyjnym, ale nie tak bardzo w 64-bitowym systemie. Szybciej napotykasz inne ograniczenia - na przykład wyczerpanie portu TCP :) A jak myślisz, gdzie są przechowywane te „pseudo-stosy” węzła? Zgadza się.
Luaan
10

Zdarzenia są również intensywnie wykorzystywane w programowaniu sieciowym (np. Nginx), aby uniknąć kosztownych pętli zajętości i zamiast tego zapewniają przejrzysty interfejs, aby dokładnie wiedzieć , kiedy dostępna jest określona operacja (operacje we / wy, pilne dane itp.). Jest to również rozwiązanie problemu C10k .

Podstawową ideą jest zapewnienie systemowi operacyjnemu zestawu gniazd (tj. Połączeń sieciowych) do monitorowania zdarzeń, wszystkich lub tylko niektórych, które są szczególnie zainteresowane (na przykład dane dostępne do odczytu); po wykryciu takiej aktywności przez system operacyjny na jednym z gniazd na liście otrzymasz powiadomienie o zdarzeniu, którego szukałeś przez interfejs API, a następnie będziesz musiał ustalić, skąd pochodzi i odpowiednio działać .

Teraz jest to abstrakcyjny widok niskiego poziomu, a ponadto trudno jest go dobrze skalować. Jednak istnieje wiele platform wyższego poziomu, które radzą sobie z tym w sposób nawet wieloplatformowy: Twisted for Python, Boost.Asio dla C ++ lub libevent dla C przychodzą mi na myśl.

edmz
źródło
+1 „drogie pętle zajętości”: innymi słowy, jest użyteczny we wszystkich równoległych procesach, które wymagają pewnej bezczynności (oczekiwania), a także synchronizacji między takimi procesami (wiadomościami lub zdarzeniami). Tak jak działa prawdziwy świat.
fr13d
Interesujące jest odkrycie, że gniazda zostały pierwotnie zaprojektowane jako forma IPC na pojedynczym komputerze, zanim istniała sieć.
5

Systemy wbudowane prawie zawsze są z natury sterowane zdarzeniami, nawet jeśli nie są wyraźnie zaprogramowane jako takie.

Te zdarzenia pochodzą z przerwań sprzętowych, naciśnięć przycisków, okresowych odczytów analogowo-cyfrowych, upływu czasu itp.

Wbudowane systemy o niskiej mocy są jeszcze bardziej podatne na zdarzenia; spędzają większość czasu na spaniu (procesor śpi w trybie niskiego poboru mocy), czekając, aż coś się wydarzy (to „coś” jest zdarzeniem).

Jednym z najbardziej popularnych i popularnych platform dla systemów osadzonych sterowanych zdarzeniami jest platforma kwantowa (QP) (QP działa również w systemie Linux, Windows i dowolnym systemie operacyjnym uniksopodobnym). Maszyny stanowe w naturalny sposób nadają się do programowania sterowanego zdarzeniami, ponieważ program nie jest „sekwencyjny” w typowym znaczeniu, jest to raczej zestaw „wywołań zwrotnych”, które są wywoływane w zależności od stanu systemu i bieżącego zdarzenia.

Radian
źródło
3

Wiadomości o wydarzeniach Gregor Hohpe.

Architektury napędzane wydarzeniami Gregor Hohpe.

Architektura SEDA , walijski, Culler, Brewer.

jak sobie radzisz w normalnym programowaniu backendowym, gdy coś się dzieje, czy to coś innego?

Maszyna stanów skończonych jest jednym powszechnym podejściem

Given(State.A)
When(Event.B)
Then(State.C)
    .and(Consequences.D)
VoiceOfUnreason
źródło
2
1, to nie jest tak naprawdę spójna odpowiedź, a 2, FSM nie są dobrym przykładem użycia zdarzenia.
whatsisname
1
FSM. Jestem pewien, że religia pastafariańska obserwuje wiele wydarzeń ;-)
fr13d
0

W systemach wbudowanych zdarzenia występują podczas przerwań. Istnieje wiele źródeł przerwań, od timerów po I / O.

Również RTOS może mieć zdarzenia. Jeden przykład czeka na wiadomość z innego zadania.

Thomas Matthews
źródło
0

Dla systemu niewbudowanego, ale czymś, co robiłem w C #, był system SCADA. Było wiele zdarzeń związanych z tym, co działo się w magazynie, gdy rozładowano ładunek część zdarzenia generowanego przez system, a inna część zapisywała nowy stan do bazy danych. Oczywiście mieliśmy klienta GUI, ale miał on tylko pokazać stan bazy danych, który odzwierciedlał stan magazynu. Było to oprogramowanie serwera zaplecza oparte na zdarzeniach i wątkach. Trudne do opracowania.

https://en.wikipedia.org/wiki/SCADA

Mateusz
źródło