V mých programech předávám zpětná volání nebo jen spouštím funkce z jiných funkcí, aby se věci staly po dokončení úkolů. Když něco skončí, spustím funkci přímo:
var ground = "clean"; function shovelSnow(){ console.log("Cleaning Snow"); ground = "clean"; } function makeItSnow(){ console.log("It"s snowing"); ground = "snowy"; shovelSnow(); }
Ale já jsem četl jsem o mnoha různých strategiích v programování a ten, který chápu jako mocný, ale dosud jsem jej nepraktikoval, je založen na událostech (myslím, že metoda, o které jsem četl, se jmenovala „pub-sub“ ) :
var ground = "clean"; function shovelSnow(){ console.log("Cleaning Snow"); ground = "clean"; } function makeItSnow(){ console.log("It"s snowing"); ground = "snowy"; $(document).trigger("snow"); } $(document).bind("snow", shovelSnow);
Chtěl bych pochopit objektivní silné a slabé stránky události – programování na základě, oproti pouhému volání všech vašich funkcí z jiných funkcí. Ve kterých programovacích situacích má smysl programování založené na událostech?
Komentáře
Odpověď
Událost je oznámení popisující výskyt z nedávné minulosti.
Typická implementace systému řízeného událostmi využívá dispečer událostí a funkce obslužné rutiny (nebo předplatitelé ). Dispečer poskytuje API pro obsluhu kabelů k událostem (jQuery „s bind
) a metodu pro publikování události svým předplatitelům (trigger
v jQuery). Když mluvíte o událostech IO nebo UI, obvykle také existuje smyčka událostí , která detekuje nové události, například kliknutí myší, a předává je dispečerovi. JS-land, dispečer a smyčku událostí poskytuje prohlížeč.
U kódu, který interaguje přímo s uživatelem – reaguje na stisknutí kláves a kliknutí – programování řízené událostmi (nebo jeho variace, například funkční reaktivní programování ) je téměř nevyhnutelné. Vy, programátor, nemáte tušení, kdy nebo kde uživatel klikne, takže je to na rozhraní GUI nebo prohlížeč k detekci akce uživatele v jeho smyčce událostí a upozornění vašeho kódu. Tento typ infrastruktury se také používá v síťových aplikacích (srov NodeJS).
Váš příklad, při kterém vyvoláte událost yo ur code místo přímého volání funkce má několik zajímavějších kompromisů, o kterých budu diskutovat níže. Hlavní rozdíl spočívá v tom, že vydavatel události (makeItSnow
) neurčí příjemce hovoru; které jsou připojeny jinde (ve volání příkladu bind
). Tomu se říká fire-and-forget : oznamuje světu, že sněží, ale je mu jedno, kdo poslouchá, co se bude dít dál nebo kdy se to stane – jednoduše vysílá zprávu a opráší si ruce.
Takže přístup založený na událostech odděluje odesílatele zprávy od příjemce. Jedna výhoda, kterou vám poskytuje, je, že daná událost může mít více obslužných programů. Funkci gritRoads
můžete svázat s vaší sněhovou událostí, aniž by to ovlivnilo stávající shovelSnow
obsluhu. Způsob, jakým je vaše aplikace připojena, máte flexibilitu; Chcete-li vypnout chování, stačí odstranit volání bind
, než hledat kód, abyste našli všechny instance tohoto chování.
Další výhoda programování řízené událostmi spočívá v tom, že vám dává místo, kde můžete položit průřezové obavy. Dispečer událostí hraje roli Mediator a některé knihovny (například Brighter ) využívají potrubí, takže můžete snadno připojit obecné požadavky, jako je protokolování nebo kvalita služeb.
Úplné zveřejnění: Brighter je vyvinut v Huddle, kde pracuji.
Třetí výhodou oddělení oddělení odesílatele události od přijímače je, že vám dává flexibilitu při zpracování události. Každý typ události můžete zpracovat na svém vlastním vlákně (pokud to váš dispečer událostí podporuje), nebo můžete zvýšené události umístit na brokera zpráv, jako je RabbitMQ zpracovat je asynchronním procesem nebo je dokonce zpracovat hromadně přes noc. Přijímač události může být v samostatném procesu nebo na samostatném stroji. K tomu nemusíte měnit kód, který událost vyvolává! Toto je velká myšlenka za architekturami „mikroslužeb“: autonomní služby komunikují pomocí událostí, přičemž páteří aplikace je middleware pro zasílání zpráv.
Poněkud odlišný příklad stylu založeného na událostech najdete v designu založeném na doménách, kde události domény slouží k udržení agregátů oddělených. Zvažte například internetový obchod, který doporučuje produkty na základě vaší historie nákupů. Když je Customer
platba za ShoppingCart
, je třeba aktualizovat historii nákupů. Agregát ShoppingCart
může upozornit Customer
vyvoláním události CheckoutCompleted
; Customer
by se v reakci na událost aktualizoval v samostatné transakci.
Hlavní nevýhodou tohoto modelu založeného na událostech je nepřímost. Nyní je těžší najít kód, který událost zpracovává, protože k ní nemůžete jednoduše přejít pomocí svého IDE; musíte přijít na to, kde je událost svázána v konfiguraci a doufat, že jste našli všechny obslužné rutiny. Je tu více věcí, které můžete mít v hlavě najednou. Zde mohou pomoci konvence stylů kódu (například uvedení všech hovorů na bind
do jednoho souboru). V zájmu vašeho rozumu je důležité používat pouze jednoho dispečera událostí a používat jej důsledně.
Další nevýhodou je, že je obtížné refaktorovat události. Pokud potřebujete změnit formát události, musíte také změnit všechny přijímače. To se zhoršuje, když jsou předplatitelé události na různých počítačích, protože nyní musíte synchronizovat vydání softwaru!
Za určitých okolností může být výkon důležitý. Při zpracování zprávy musí dispečer:
- Vyhledat správné obslužné rutiny v nějaké datové struktuře.
- Vytvoření kanálu pro zpracování zpráv pro každou obslužnou rutinu. To může zahrnovat spoustu alokací paměti.
- Dynamicky zavolat obslužné rutiny (případně použití reflexe, pokud to jazyk vyžaduje).
To je určitě pomalejší než běžná funkce volání, které zahrnuje pouze vložení nového rámce do zásobníku. Flexibilita, kterou vám poskytuje architektura založená na událostech, však umožňuje mnohem jednodušší izolovat a optimalizovat pomalý kód. Možnost odeslat práci do asynchronního procesoru je zde velkou výhrou, protože vám umožňuje okamžitě obsloužit požadavek, zatímco s těžkou prací se pracuje na pozadí. V každém případě, pokud provádíte interakci s databází nebo s kreslením na obrazovce, náklady na vstup / výstup zcela zaplaví náklady na zpracování zprávy. Jde o to, abyste se vyhnuli předčasné optimalizaci.
tručně řečeno, události jsou skvělým způsobem, jak vytvořit volně spojený software, ale nejsou bez nákladů. Bylo by chybou například nahradit každé volání funkce ve vaší aplikaci událostí. Pomocí událostí vytvářejte smysluplné architektonické dělení.
Komentáře
- Tato odpověď říká totéž jako 5377 ‚ s odpověď, kterou jsem vybral jako správnou; ‚ Změním svůj výběr tak, aby se označil tento, protože se dále rozvíjí.
- Je rychlost významnou nevýhodou kódu řízeného událostmi? Vypadá to, že by to mohlo být, ale ‚ to docela nevím.
- @ raptortech97 to určitě může být. U kódu, který musí být obzvláště rychlý, byste pravděpodobně chtěli vyhnout se odesílání událostí ve vnitřní smyčce; naštěstí v takových situacích je obvykle dobře definováno, co musíte udělat, takže nepotřebujete ‚ extra pružně události (nebo publikovat / odebírat nebo pozorovatele, což jsou ekvivalentní mechanismy s odlišná terminologie).
- Všimněte si také, že existují některé jazyky (např. Erlang) postavené na hereckém modelu, kde jsou všechno zprávy (události). V tomto případě může kompilátor rozhodnout, zda zprávy / události implementovat jako přímé volání funkcí nebo jako komunikaci.
- Pro “ performance “ Myslím, že musíme rozlišovat mezi výkonem s jedním vláknem a škálovatelností. Zprávy / události mohou být pro výkon s jedním podprocesem horší (ale lze je převést na volání funkcí za nulové dodatečné náklady a nesmí být o nic horší) a kvůli škálovatelnosti je ‚ lepší prakticky ve způsobem (např. pravděpodobně povede k masivnímu zlepšení výkonu na moderních více CPU a budoucích “ many-CPU “ systémech).
Odpověď
Programování založené na událostech se používá, když program nekontroluje sled událostí, které provádí. Tok programu je místo toho směrován vnějším procesem, jako je uživatel (např. GUI), jiný systém (např. Klient / server) nebo jiný proces (např. RPC).
Například skript pro dávkové zpracování ví, co musí udělat, prostě to dělá. Není založeno na událostech.
Sedí tam textový procesor a čeká, až uživatel začne psát.Klávesové zkratky jsou události, které aktivují funkce pro aktualizaci interní vyrovnávací paměti dokumentu. Program nemůže vědět, co chcete psát, takže musí být řízen událostmi.
Většina programů GUI je řízena událostmi, protože jsou postaveny na interakci uživatele. Programy založené na událostech se však neomezují pouze na GUI, což je pro většinu lidí jednoduše nejznámější příklad. Webové servery čekají na připojení klientů a sledují podobný idiom. Procesy na pozadí ve vašem počítači mohou také reagovat na události. Například antivirový program na vyžádání může z operačního systému obdržet událost týkající se nově vytvořeného nebo aktualizovaného souboru a poté tento soubor zkontrolovat, zda neobsahuje viry.
Odpovědět
V aplikaci založené na událostech vám koncept posluchačů událostí umožní psát ještě více Volně spojené aplikace .
Například modul nebo zásuvný modul jiného výrobce může odstranit záznam z databáze a poté spustit receordDeleted
událost a zbytek přenechejte posluchačům událostí, aby udělali svou práci. Všechno bude fungovat dobře, i když spouštěcí modul ani neví, kdo poslouchá tuto konkrétní událost nebo co by se mělo stát dál.
Odpovědět
Chtěl jsem přidat jednoduchou analogii, která mi pomohla:
Představte si komponenty (nebo objekty) vaší aplikace jako velkou skupinu přátel z Facebooku.
Když vám některý z vašich přátel chce něco říct, může vám buď přímo zavolat, nebo jej odeslat na zeď na Facebooku. Když to zveřejní na svém Facebooku, kdokoli to může vidět a reagovat na to, ale spousta lidí to nedělá. Někdy je něco důležitého, na co lidé pravděpodobně budou muset reagovat, například „Máme dítě!“ nebo „Skupina Tak a tak dělá překvapivý koncert v Drunkinu „Clam bar!“. V posledním případě bude na to pravděpodobně muset reagovat zbytek přátel, zvláště pokud se o tuto kapelu zajímají.
Pokud si váš přítel chce mezi vámi a nimi ponechat tajemství, pravděpodobně nechtěli byste to zveřejnit na zeď na Facebooku, zavolali by vám přímo a řekli vám to. Představte si scénář, kdy řeknete dívce, která se vám líbí, že byste ji chtěli potkat v restauraci na rande. Místo toho, abyste jí zavolali přímo a zeptali se ji, pošlete ji na zeď na Facebooku, aby ji viděli všichni vaši přátelé. Funguje to, ale pokud máte žárlivého ex, mohla by to vidět a objevit se v restauraci, aby vám zničila den.
Když při rozhodování, zda vybudovat posluchače událostí pro implementaci něčeho, přemýšlejte o této analogii. Musí tato součást dát své podnikání tam, aby to někdo viděl? Nebo musí někomu zavolat přímo? Věci se mohou snadno zkazit, takže se opatrně.
Odpovědět
Tato analogie vám může pomoci u pochopit událostmi řízené I / O programování nakreslením rovnoběžky s čekací linkou na recepci doktora.
Blokování I / O je jako, pokud stojíte ve frontě, recepční požádá člověka před vámi, aby vyplnil formulář a ona počká, dokud nedokončí. Musíte počkat, až na vás přijde řada, dokud chlap nedokončí svoji formu, toto blokuje.
Pokud svobodnému muži trvá vyplnění 3 minuty, 10. muž musí počkat do 30 minut. Nyní, abychom zkrátili tuto desátou dobu čekání, řešením by bylo zvýšení počtu pracovníků recepce, což je nákladné. To se děje na tradičních webových serverech. Pokud požadujete informace o uživateli, následný požadavek ostatních uživatelů by měl počkat, až aktuální operace, načítání z databáze, je dokončena. Tím se zvyšuje „čas do odezvy“ 10. požadavku a zvyšuje se exponenciálně pro n-tého uživatele. Aby se tomu zabránilo, vytvoří tradiční webové servery vlákno (ekvivalentní rostoucímu počtu recepčních) pro každý jednotlivý požadavek , tj. v zásadě vytváří kopii serveru pro každý požadavek, což je nákladné období spotřeby procesoru, protože každý požadavek bude vyžadovat vlákno operačního systému. Chcete-li aplikaci rozšířit, budete muset aplikaci hodit spoustu výpočetního výkonu .
Událost řízena : Druhým přístupem ke zvětšení „doby odezvy“ fronty je jděte na přístup řízený událostmi, kde bude předán chlap ve frontě formulář, požádal o vyplnění a po dokončení se vrátil. Proto může recepční vždy přijmout žádost. To je přesně to, co javascript od té doby dělá. V prohlížeči by javascript reagoval na událost kliknutí uživatele, posouvání, přejetí prstem nebo načtení databáze atd. To je možné v javascriptu inherentně, protože javascript považuje funkce za první třídu objekty a lze je předat jako parametry dalším funkcím (tzv. zpětná volání) a lze je volat po dokončení konkrétního úkolu. To přesně dělá node.js na serveru.Další informace o programování řízeném událostmi a blokování I / O najdete v kontextu uzlu zde
$(document).bind('snow', shovelShow)
. Není třeba jej zabalit do anonymní funkce.