Olen ohittanut soittopyyntöjä tai vain aktivoinut ohjelmieni muiden toimintojen toiminnot, jotta asiat tapahtuvat, kun tehtävät on suoritettu. Kun jokin päättyy, käynnistän toiminnon suoraan:
var ground = "clean"; function shovelSnow(){ console.log("Cleaning Snow"); ground = "clean"; } function makeItSnow(){ console.log("It"s snowing"); ground = "snowy"; shovelSnow(); }
Mutta minä ”ve lukea monista erilaisista ohjelmointistrategioista, ja yksi, jonka ymmärrän olevan tehokas, mutta jota en ole vielä harjoittanut, on tapahtumapohjainen (luulemani menetelmää, josta luin, kutsutaan nimellä ”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);
Haluan ymmärtää tapahtuman objektiiviset vahvuudet ja heikkoudet -pohjainen ohjelmointi, toisin sanoen vain kaikkien toimintojesi kutsuminen muista toiminnoista. Missä ohjelmointitilanteissa tapahtumaperusteista ohjelmointia on järkevää käyttää?
Kommentit
Vastaa
tapahtuma on ilmoitus, joka kuvaa lähimenneisyyden tapahtumaa.
Tyypillinen tapahtumavetoisen järjestelmän toteutus käyttää tapahtumien lähettäjää ja käsittelijän toimintoja (tai tilaajat ). Välittäjä tarjoaa API: n langankäsittelijöille aina tapahtumiin saakka (jQuery ”s bind
) ja menetelmän tapahtuman julkaisemiseksi tilaajille (trigger
Kun puhut IO- tai UI-tapahtumista, siellä on yleensä myös tapahtumasilmukka , joka havaitsee uudet tapahtumat, kuten hiiren napsautukset, ja välittää ne lähettäjälle. JS-land, lähettäjät ja tapahtumasilmukat tarjoaa selain.
Koodille, joka on suoraan käyttäjän kanssa vuorovaikutuksessa – reagoi näppäinten painalluksiin ja napsautuksiin – tapahtumavetoinen ohjelmointi (tai sen muunnelma, kuten toiminnallinen reaktiivinen ohjelmointi ) on melkein väistämätöntä. Sinulla, ohjelmoijalla, ei ole aavistustakaan milloin ja missä käyttäjä napsauttaa, joten se on GUI-kehyksen alla tai selain havaitsee käyttäjän toiminnan tapahtumasilmukassaan ja ilmoittaa koodistasi. Tämän tyyppistä infrastruktuuria käytetään myös verkkosovelluksissa (vrt. NodeJS).
Esimerkkisi, jossa nostat tapahtuman sisään yo UR-koodilla pikemminkin kuin kutsua funktiota suoraan, on mielenkiintoisempia kompromisseja, joista keskustelen alla. Tärkein ero on, että tapahtuman julkaisija (makeItSnow
) ei määritä puhelun vastaanotinta; joka on kytketty muualle (esimerkissäsi kutsussa bind
). Tätä kutsutaan tuli ja unohda : makeItSnow
ilmoittaa maailmalle, että sataa lunta, mutta sillä ei ole väliä kuka kuuntelee, mitä tapahtuu seuraavaksi tai milloin se tapahtuu – se yksinkertaisesti lähettää viestin ja pölyttää kätensä.
Joten tapahtumapohjainen lähestymistapa irrottaa viestin lähettäjän vastaanottimesta. Yksi tämän tarjoama etu on, että tietyllä tapahtumalla voi olla useita käsittelijöitä. Voit sitoa gritRoads
-toiminnon lumitapahtumaan vaikuttamatta nykyiseen shovelSnow
-käsittelijään. Sinulla on joustavuus sovelluksesi johdotuksessa; Jos haluat poistaa käytöstä käytöstä, sinun tarvitsee vain poistaa bind
-kutsu sen sijaan, että etsiä koodia läpi löytääksesi kaikki käyttäytymisen esiintymät.
Toinen etu tapahtumavetoinen ohjelmointi on, että se antaa sinulle jonnekin asettaa monialaisia huolenaiheita. Tapahtuman lähettäjällä on välittäjän rooli, ja jotkut kirjastot (kuten Brighter ) käyttävät putkilinjan, jotta voit helposti liittää yleisiä vaatimuksia, kuten puunkorjuu tai palvelun laatu.
Täysi kuvaus: Brighter on kehitetty Huddlessa, jossa työskentelen.
Kolmas etu tapahtuman lähettäjän irrotuksessa vastaanottimesta on, että se antaa sinulle joustavuutta kun käsittelet tapahtumaa. Voit käsitellä kutakin tapahtumatyyppiä omalla ketjullaan (jos tapahtumiedustajasi tukee sitä) tai voit laittaa korotetut tapahtumat viestivälittäjälle, kuten RabbitMQ ja käsitellä niitä asynkronisella prosessilla tai jopa käsitellä niitä irtotavarana yön yli. Tapahtuman vastaanotin voi olla erillisessä prosessissa tai erillisessä koneessa. Sinun ei tarvitse muuttaa koodia, joka herättää tapahtuman, tekemään tämän! Tämä on iso idea ”mikropalvelu” -arkkitehtuurien takana: itsenäiset palvelut kommunikoivat tapahtumien avulla, sovelluksen selkärangana on välitysohjelmisto.
Jos haluat melko erilaisen esimerkin tapahtumaperusteisesta tyylistä, etsi verkkotunnuspohjainen suunnittelu, jossa toimialueen tapahtumat käytetään pitämään aggregaatit erillään. Harkitse esimerkiksi verkkokauppaa, joka suosittelee tuotteita ostohistoriasi perusteella. Customer
-ostohistoria on päivitettävä, kun ShoppingCart
-maksu maksetaan. ShoppingCart
aggregaatti saattaa ilmoittaa Customer
nostamalla CheckoutCompleted
-tapahtuman; Customer
päivitetään erillisenä tapahtumana vastauksena tapahtumaan.
Tämän tapahtumapohjaisen mallin tärkein haittapuoli on epäsuora suuntaus. Tapahtumaa käsittelevän koodin löytäminen on nyt vaikeampaa, koska et voi vain navigoida siihen IDE: lläsi; sinun on selvitettävä, mihin tapahtuma on sidottu kokoonpanossa, ja toivoa, että olet löytänyt kaikki käsittelijät. Siellä on enemmän juttuja, joita voit pitää päähäsi kerrallaan. Koodityylin käytäntöistä voi olla apua tässä (esimerkiksi kaikkien puheluiden sijoittaminen bind
yhteen tiedostoon). Järkevyytesi vuoksi on tärkeää käyttää vain yhtä tapahtuman lähettäjää ja käyttää sitä jatkuvasti.
Toinen haittapuoli on se, että tapahtumia on vaikea refraktoida. Jos haluat muuttaa tapahtuman muotoa, sinun on vaihdettava myös kaikki vastaanottimet. Tämä pahentuu, kun tapahtuman tilaajat ovat eri koneilla, koska sinun on nyt synkronoitava ohjelmistojulkaisut!
Tietyissä olosuhteissa suorituskyky saattaa olla huolestuttava. Käsitellessään viestiä työnvälittäjän on:
- etsittävä oikeita käsittelijöitä joistakin tietorakenteista.
- Rakennettava viestinkäsittelyputki kullekin käsittelijälle. Tähän voi liittyä joukko muistia.
- Kutsu käsittelijöitä dynaamisesti (mahdollisesti käyttämällä heijastusta, jos kieli sitä vaatii).
Tämä on varmasti hitaampaa kuin tavallinen toiminto. kutsu, johon kuuluu vain uuden kehyksen työntäminen pinoon. Tapahtumapohjaisen arkkitehtuurin tarjoama joustavuus tekee kuitenkin hitaan koodin eristämisen ja optimoinnin paljon helpommaksi. Mahdollisuus lähettää työ asynkroniselle prosessorille on tässä suuri voitto, koska sen avulla voit palvella pyyntöä välittömästi, kun kovaa työtä käsitellään taustalla. Joka tapauksessa, jos olet vuorovaikutuksessa tietokannan kanssa tai piirtää tavaraa ruudulle, IO: n kustannukset sietävät kokonaan viestin käsittelykustannukset. Näin vältetään ennenaikaista optimointia.
Yhteenvetona voidaan todeta, että tapahtumat ovat loistava tapa rakentaa löyhästi kytkettyjä ohjelmistoja, mutta ne eivät ole ilman kustannuksia. Olisi esimerkiksi virhe korvata sovelluksen jokainen funktiokutsu tapahtumalla. Tee tapahtumista merkityksellisiä arkkitehtonisia jakoja.
Kommentit
- Tämä vastaus sanoo saman kuin 5377 ’ vastauksen, jonka valitsin oikeaksi; ’ Muutan valintani merkitsemään tämän, koska se kehittyy edelleen.
- Onko nopeus merkittävä haitta tapahtumavetoiselle koodille? Näyttää siltä, että se voisi olla, mutta en ’ tiedä sitä.
- @ raptortech97 se varmasti voi olla. Jos koodi on erityisen nopea, sinun kannattaa välttää tapahtumien lähettämistä sisäiseen silmukkaan; onneksi tällaisissa tilanteissa se on yleensä hyvin määritelty, mitä sinun on tehtävä, joten et ’ et tarvitse ylimääräistä joustavasti tapahtumia (tai julkaise / tilaa tai tarkkailijoita, jotka ovat vastaavia mekanismeja eri terminologia).
- Huomaa myös, että näyttelijämallin ympärille on rakennettu joitain kieliä (esim. Erlang), jossa kaikki on viestejä (tapahtumia). Tällöin kääntäjä voi päättää, toteutetaanko viestit / tapahtumat suorina funktiokutsuina vai viestinä.
- ” -suorituskyky ” Mielestäni meidän on tehtävä ero yksisäikeisen suorituskyvyn ja skaalautuvuuden välillä. Viestit / tapahtumat voivat olla huonompia yksisäikeisen suorituskyvyn kannalta (mutta ne voidaan muuntaa toimintokutsuiksi ilman lisäkustannuksia eikä olla huonompia), ja skaalautuvuuden kannalta se on ’ parempi käytännöllisesti katsoen kaikissa tavalla (esim. todennäköisesti johtaa massiivisiin suorituskyvyn parannuksiin nykyaikaisella monisuorittimella ja tulevilla ” moni-CPU ” -järjestelmillä).
Vastaus
Tapahtumapohjaista ohjelmointia käytetään, kun ohjelma ei hallitse suorittamiensa tapahtumien järjestystä. Sen sijaan ohjelmavirtaa ohjaa ulkopuolinen prosessi, kuten käyttäjä (esim. GUI), toinen järjestelmä (esim. Asiakas / palvelin) tai jokin muu prosessi (esim. RPC).
Esimerkiksi komentojonon komentosarja tietää mitä sen on tehtävä, joten se vain tekee sen. Se ei ole ei tapahtumapohjainen.
Siellä istuu tekstinkäsittelyohjelma ja odottaa, että käyttäjä alkaa kirjoittaa.Näppäinpainallukset ovat tapahtumia, jotka käynnistävät toiminnon sisäisen asiakirjapuskurin päivittämiseksi. Ohjelma ei voi tietää, mitä haluat kirjoittaa, joten sen on oltava tapahtumapohjainen.
Useimmat käyttöliittymäohjelmat ovat tapahtumapohjaisia, koska ne on rakennettu käyttäjän vuorovaikutuksen ympärille. Tapahtumapohjaiset ohjelmat eivät kuitenkaan rajoitu käyttöliittymiin, se on yksinkertaisesti kaikkein tuttu esimerkki useimmille ihmisille. Verkkopalvelimet odottavat asiakkaiden muodostavan yhteyden ja seuraavat samanlaista idioomaa. Tietokoneesi taustaprosessit voivat myös reagoida tapahtumiin. Esimerkiksi on-demand-virustarkistus voi vastaanottaa käyttöjärjestelmältä tapahtuman, joka koskee äskettäin luotua tai päivitettyä tiedostoa, ja skannata sitten tiedoston virusten varalta.
Vastaa
Tapahtumapohjaisessa sovelluksessa Tapahtumakuuntelijat -konsepti antaa sinulle mahdollisuuden kirjoittaa vielä enemmän Löysästi yhdistetyt sovellukset.
Esimerkiksi kolmannen osapuolen moduuli tai laajennus voi poistaa tietueen tietokannasta ja käynnistää sitten receordDeleted
tapahtuma ja jätä loput tapahtuman kuuntelijoille tekemään työnsä. Kaikki toimii hyvin, vaikka laukaisumoduuli ei edes tiedä kuka kuuntelee tätä tapahtumaa tai mitä pitäisi tapahtua seuraavaksi.
Vastaa
Halusin lisätä yksinkertaisen analogian, joka auttoi minua:
Ajattele sovelluksesi komponentteja (tai esineitä) suurena Facebook-ystävien ryhmänä.
Kun joku ystävistäsi haluaa kertoa sinulle jotain, hän voi joko soittaa sinulle suoraan tai lähettää sen Facebook-seinälle. Kun he lähettävät sen Facebookiinsa, kuka tahansa voisi nähdä sen ja reagoida siihen, mutta monet ihmiset eivät ”t. Joskus se on jotain tärkeää, että ihmisten on todennäköisesti reagoitava siihen, kuten” Meillä on vauva! ”tai” So-and-so-bändi tekee yllätyskonsertin Drunkinissa ”Simpukkabaari!”. Viimeisessä tapauksessa muiden ystävien on todennäköisesti reagoitava siihen, varsinkin jos he ovat kiinnostuneita bändistä.
Jos ystäväsi haluaa pitää salaisuuden sinun ja heidän välillä, he todennäköisesti ei lähettäisi sitä Facebook-seinälleen, he soittavat sinulle suoraan ja kertoisivat sinulle. Kuvaa skenaario, jossa kerrot tykkäävälle tytölle, että haluat tavata hänet ravintolassa treffeille. Sen sijaan, että soittaisit hänelle suoraan ja kysyisit hän, lähetät sen Facebook-seinällesi kaikkien ystäviesi nähtäväksi. Tämä toimii, mutta jos sinulla on kateellinen entinen, hän voisi nähdä sen ja ilmestyä ravintolaan pilata päiväsi.
Milloin Ajattele tätä analogiaa päättääkö rakentaa tapahtumakuuntelijoita jonkin toteuttamiseksi, mieti tätä analogiaa. Pitäisikö tämän komponentin laittaa liiketoimintansa sinne kenenkään nähtäväksi? Vai pitääkö heidän soittaa suoraan jollekulle? Asiat voivat sotkea melko helposti, joten ole varovainen.
Vastaa
Tämä seuraava analogia voi auttaa sinua u ymmärtää tapahtumavetoista I / O-ohjelmointia vetämällä rinnakkain odotuslinjan kanssa lääkärin vastaanotossa.
I / O: n estäminen on kuin jos seisot jonossa, vastaanottovirkailija pyytää edessäsi olevaa kaveria täyttämään lomakkeen ja hän odottaa, kunnes hän lopettaa. Sinun on odotettava vuoroasi, kunnes kaveri viimeistelee lomakkeensa, tämä estää.
Jos yhden miehen täyttäminen kestää 3 minuuttia, 10. kaverin on odotettava 30 minuuttia. Nyt tämän kymmenennen kaveri-odotusajan lyhentämiseksi ratkaisu olisi lisätä vastaanottovirkailijoiden määrää, mikä on kallista. Näin tapahtuu perinteisissä verkkopalvelimissa. Jos pyydät käyttäjätietoja, muiden käyttäjien myöhempien pyyntöjen pitäisi odottaa nykyinen operaatio, nouto tietokannasta, on suoritettu. Tämä pidentää 10. pyynnön ”vastausaikaa” ja kasvaa eksponentiaalisesti n. käyttäjälle. Tämän välttämiseksi perinteiset verkkopalvelimet luovat ketjun (vastaa yhä enemmän vastaanottovirkailijoita) jokaiselle pyynnölle eli se pohjimmiltaan luo kopion palvelimesta kutakin pyyntöä varten, mikä on kallista suorittimen kulutusta, koska jokainen pyyntö tarvitsee käyttöjärjestelmän ketjun. Sovelluksen laajentamiseksi sinun on heitettävä paljon laskentatehoa sovellukseen .
Tapahtumaohjattu : Toinen tapa lisätä jonon vasteaikaa on Siirry tapahtumavetoiseen lähestymistapaan, jossa jonossa olevat kaverit luovutetaan lomake, pyydetään täyttämään ja palaamaan sen jälkeen. Siksi vastaanottovirkailija voi aina ottaa vastaan pyynnön. Juuri tätä javascript on tehnyt alusta asti. Selaimessa javascript vastaisi käyttäjän napsautustapahtumaan, vieritykseen, pyyhkäisemiseen tai tietokannan hakemiseen ja niin edelleen. Tämä on mahdollista Javascriptissa luonnostaan, koska javascript käsittelee toimintoja ensimmäisen luokan objektit ja ne voidaan välittää parametreina muihin toimintoihin (kutsutaan soittopyynnöiksi), ja ne voidaan kutsua tietyn tehtävän suorittamisen jälkeen.Tämä on tarkalleen mitä node.js tekee palvelimella.Löydät lisätietoja tapahtumavetoisesta ohjelmoinnista ja i / o: n estämisestä solmun yhteydessä täältä
$(document).bind('snow', shovelShow)
. Sinun ei tarvitse kääriä sitä nimettömään toimintoon.