flux in depth. store and network communication

14

Upload: andres-tuells-jansson

Post on 07-Sep-2015

10 views

Category:

Documents


0 download

DESCRIPTION

flux

TRANSCRIPT

  • 7/19/2015 Flux in Depth. Store and Network Communication. Minko Gechev's blog

    http://blog.mgechev.com/2015/07/18/flux-in-depth-store-network-communication-services/ 1/14

    Flux in Depth. Store and NetworkCommunication.Edit

    Thisisthesecond,andprobablybethelast,blogpostoftheseries"FluxinDepth".Inthefirstpostwedidaquickoverviewofflux,tookalookatthestateless,purecomponents,immutabledatastructuresandcomponentcommunication.Thistime,we'regoingtointroducethestoreandhowwecancommunicatewithservicesthroughthenetworkviaHTTP,WebSocketorWebRTC.Sincethefluxarchitecturedoesn'tdefineawayofcommunicationwithexternalservices,hereyoucanfindmywayofdealingwithnetworkcommunication.Ifyouhaveanysuggestionsoropinions,donothesitatetoleaveacomment.

    StoreAswesaid,theUIinfluxisbuiltwithpurecomponents,whichare(mostly)notholdinganystate.However,ourapplicationcan'tbecompletelystateless.Wehaveatleastbusinessdata,UIstateandanapplicationconfiguration.Thestoreistheplace,whichkeepsthisdata.

    Letspeekatthefluxdataflowonceagain:

    Aswecanseefromthediagramabove,thedataflowstartsintheview,goestoanaction,whichinvokesthedispatcher,afterthatthestorecatchesdispatcher'seventandintheendthedataarrivesintheviewagain.Alright,sothestoreisresponsibleforprovidingthedatatotheview.Sofarsogood.Howwecanmakethestoredelivertherequiredbytheviewdata?Well,itcantriggeranevent!Recentlyobservablesaregettingquitepopular.Forgoodorbad,theyaregoingtobeincludedintheJavaScriptstandard.IfthismakesyouangrybecauseyouhavetolearnnewthingsandJavaScriptisgettingfatter,youcanfindtheguywhostaysbehindallofthishere:

    MINKO GECHEV'S BLOG

    menu

  • 7/19/2015 Flux in Depth. Store and Network Communication. Minko Gechev's blog

    http://blog.mgechev.com/2015/07/18/flux-in-depth-store-network-communication-services/ 2/14

    Observablesaregoodwayofbuildingourstore.Iftheviewisabletoobservethestoreforchanges,itcanupdateitselfoncethestoreupdates.Letstakealookatthefollowingdesignpattern(yeah,myfriendsalreadynoticedI'mtalkingaboutdesignpatternsconstantlyanddidaninterventionformebutdidn'thelp).

    Chain of Responsibility

    Thisisadesignpattern,whichisexclusivelyusedintheeventdrivenprogramming.LetschangethecontextandtalkaboutDOMforawhile.Ibetyouknowthatyoucanlistenforanyeventonthedocument,forexampleonceauserclicksonabuttontheeventwillpropagatetotherootoftheDOMtree(eventually,ifnothingstopit)andbecaughtbyyourlistener:

    document.addEventListener('click',e=>{alert(`Youactuallyclickedonelementwith#${e.target.getAttribute('id'alert(e.currentTarget===document)},false)

  • 7/19/2015 Flux in Depth. Store and Network Communication. Minko Gechev's blog

    http://blog.mgechev.com/2015/07/18/flux-in-depth-store-network-communication-services/ 3/14

    Clickme

    Clickme

    RunwithJSAutorunJS

    HTML CSS ES6/Babel Console Output HelpJSBin Save

    Ifyouclickonthe awesomebutton ,you'llseetwoalertboxes:"Youactuallyclickedonelementwith#awesomebutton,notdirectlyondocument"and"true".Ifyouchangethethirdparameterof addEventListener to true ,theeventwillpropagateintheoppositedirection(i.e.fromtoptobottom,capturingmode).

    WhyIsaidallofthis?Well,thisisthepatternChainofResponsibility:

    Inobjectorienteddesign,thechainofresponsibilitypatternisadesignpatternconsistingofasourceofcommandobjectsandaseriesofprocessingobjects.Eachprocessingobjectcontainslogicthatdefinesthetypesofcommandobjectsthatitcanhandletherestarepassedtothenextprocessingobjectinthechain.Amechanismalsoexistsforaddingnewprocessingobjectstotheendofthischain.

    Orifyou'rehavemoreenterprisetaste,hereistheUMLclassdiagramofthisdesignpattern:

    Client Handler

    +handle()

    ConcreteHandlerA

    +handle()

    ConcreteHandlerB

    +handle()

    successor

    WhydoweneedChainofResponsibility?Well,ourstoreisatreeofobjects,onceapropertyinaninternalnodeinthetreechanges,it'llpropagatethischangetotheroot.Therootcomponentintheviewwilllistenforeventstriggeredbythestoreobject.Onceitdetectsa

  • 7/19/2015 Flux in Depth. Store and Network Communication. Minko Gechev's blog

    http://blog.mgechev.com/2015/07/18/flux-in-depth-store-network-communication-services/ 4/14

    changeit'llsetitsstate.I'msureitsoundsweirdandobfuscated,letstakealookatadiagram,whichillustratesasimplechatapplication:

    From the Store to the View

    Letstakealookatthefollowingdiagram,itillustratestheinitialsetupofourapplication:

    Thetreeonthelefthandsideisthestore,whichserializedintoJSONlooksthefollowingway:

    {"users":[{"name":"foo","id":1},{"name":"bar","id":2}],"messages":[{"text":"Heyfoo","by":2,"timestamp":1437147880686}]}

    Thetreeontherighthandsideisthecomponenttree.Wealreadydescribedthecomponenttreesinthepreviouspart.Hereisasnippet,whichshowstherelationbetweenthe Chat storeandthe ChatBox component:

    importReactfrom'react'importChatfrom'../store/Chat'

    classChatBoxextendsReact.Component{constructor(props){super(props)Chat.on('change',c=>{this.setState(c)})}render(){

  • 7/19/2015 Flux in Depth. Store and Network Communication. Minko Gechev's blog

    http://blog.mgechev.com/2015/07/18/flux-in-depth-store-network-communication-services/ 5/14

    return()}}

    Basically,therootcomponent( ChatBox)issubscribedtothe change eventofthe Chat .Whenthe Chat emitsa change event,the ChatBox setsitsstatetobethecurrentstoreandpassesthestore'scontentdownthecomponenttree.That'sit.

    Whathappensifsomethingchangeourstore?

    Onthediagramabovesomethingchangedthefirstmessageinthe Chat store(letssaythetext propertywaschanged).Onceapropertyina message changes,themessageemitsaneventandpropagatesittotheparent(step 1)whichmeansthattheeventreachesthemessages collection.The messages collectiontriggerschangeeventandpropagatestheeventtothe chat (rootobject,step 2).The chat objectemitsachangeevent,whichisbeingcaughtbythe ChatBox component,whichsetsitsstatetothecontentofthestore.That'sit...

    Inthenextsection,we'regoingtotakealookhowtheviewcanmodifythestoreusingActions.

    From the View to the Store

    Nowletssupposetheuserentersamessageandsendsit.Insideasendhandler,definedinMessageInput weinvoketheaction addMessage(text,user) the MessageActionsobject(step1)(peekatthefluxoverviewdiagramabove).The MessageActions explicitlyinvokesthe Dispatcher (step2),whichthrowsanevent.ThiseventisbeinghandledbytheMessages component(step3),whichaddsthemessagetothelistofmessagesandtriggersa

  • 7/19/2015 Flux in Depth. Store and Network Communication. Minko Gechev's blog

    http://blog.mgechev.com/2015/07/18/flux-in-depth-store-network-communication-services/ 6/14

    change event.Nowwe'regoingtothepreviouscase"StoretoView".Allofthisisbetterillustratedonthefollowingdiagram:

    Model vs UI state

    Mostlikelyyou'rebuildinganapplication,whichworksonbusinessdataovergivendomain.Forexample,inourcasewehad:

    MessagesUsers

    However,inmostcases,thisisnotenough.YourapplicationalsohasaUIstate.Forexample,whethergivendialogisopenedorno,whatisthedialog'sposition,etc.Thedata,whichdefinesnowyourcomponentswillberendered,dependsonbothyourUIstateandthemodel.ThisisthereasonIcreateacombinedstore,whichpresentsboth.Forexample,ifweaddafewdialogstoourchatapplication,theJSONrepresentationofthestoremaylooklike:

    {"users":[{"name":"foo","id":1},{"name":"bar","id":2}],"messages":[{"text":"Heyfoo","by":2,"timestamp":1437147880686}],"dialogsOpenStatus":{"nicknameInput":true,"editMessage":false}}

  • 7/19/2015 Flux in Depth. Store and Network Communication. Minko Gechev's blog

    http://blog.mgechev.com/2015/07/18/flux-in-depth-store-network-communication-services/ 7/14

    IalwaysprefertohaveseparationbetweentheUIstateandthemodelbecausethecommunicationwithexternalservicesusuallyrequiresonlyhandlingchangesinthemodel,soeventsemittedbytheUIstoredoesnotconcernus.

    Quick FAQ:

    Alright,Igotit.SoifIhaveamousemoveevent,whichchangesthestorebyupdatingthemouseposition,weshouldgothroughtheentiredescribeddataflow?Thisdoesn'tseemlikequiteagoodidea.Ifyouhaveabigstoreandhugecomponenttree,rerenderingitonmousemovewillimpacttheperformanceofyourapplicationdramatically!Whatwillbethebiggestslowdown?Well,you'llhavetoserializethestoretoaPOJO(PlainOldJavaScriptObject),lateryouneedtopassittotherootcomponent,whichisresponsibleforpassingitdowntoitschildrenandsoon.Andallofthisbecauseoftwochangednumbers?Itiscompletelyunnecessary.InsuchcasesI'drecommendaddingeventlistenersinthespecificcomponent,whichdependsonthemousepositionandcreatingaseparatestoreforit.

    Forexample,ifyou'reusing reactdnd inyourapplication,thedrag&dropcomponenthasitsownstate,whichdoesn'thavetobemergedwiththerestofthestore.Itcanliveindependently.LetmeshowyouwhatImeanonthefollowingdiagram:

    Inthisexample,whenthestorecontainingthedialogpositionupdatesitdoesnotrequireupdateoftheentirecomponenttree.

    HowshouldImakemystoretriggerevents?Thesamewayyoudidthatinthedispatcheruse EventEmitter .SincewewanttoimplementChainofResponsibility,youwillberequiredtokeepreferencetotheobject'sparentinordertopropagatetheevent.

  • 7/19/2015 Flux in Depth. Store and Network Communication. Minko Gechev's blog

    http://blog.mgechev.com/2015/07/18/flux-in-depth-store-network-communication-services/ 8/14

    Remote ServicesThisisahottopic.Mostofthesinglepageapplicationsrequirecommunicationwithservicesthroughatransportprotocol,inordertofetchandstoredata.However,intheoverviewoffluxthere'snosuchthingas TransportChannel , RemoteService orwhatever.Ifthereareinvolvedalotofdifferentprotocols(forexampleI'mworkingonaapplication,whichcommunicateswithotherapplicationsandservicesthroughHTTP,WebSocketandWebRTCdatachannel)itcouldgetabithairyifyoudon'tcreatetheproperabstractions.

    InthissectionI'lldescribethebasicsofthenetworkcommunicationandlaterwe'regoingtodiscussmoreinterestingdetails.

    Alright,inthediagramwhichshowstheoverviewoffluxthereisa"hanging"action.There'snoincomingarrowtotheleftmostactionbutthere'soutgoingone:

    From the Network to the UI

    Wecanusethis"hanging"actioninordertointegratethecommunicationwiththeexternalservices.Letstakealookatthefollowingpicture,inordertovisualizebasiccommunicationwithexternalservice:

  • 7/19/2015 Flux in Depth. Store and Network Communication. Minko Gechev's blog

    http://blog.mgechev.com/2015/07/18/flux-in-depth-store-network-communication-services/ 9/14

    Initwecantracehowanetworkeventisbeingprocessed.Thecloudisanexternalservice/application.Initiallywegetanewmessage,itisbeingprocessedbythe Serviceobject(itisblackonthediagrambecauseitislikeablackboxforusrightnow,itmaygetquitecomplexdependingonyourapplication),laterthesemanticsbehindthereceivedmessageisfoundandbasedonit, Service invokesa StoreAction .Nowtheflowgoesexactlythewaywedescribeditearlier(FromtheStoretotheView).We'regoodfornow.Butwhathappensifthestorechanges?Nothingsofar.

    From the UI to the Network

    Inordertosendnetworkeventsbasedonchangesofthestorewecanobserveitandperformaspecificactionbasedonthechange.Sinceitextends EventEmitter wecansimplyaddonchange handlerstothestoreinsidethe Service andthiswaywecaneasilyhandleallchangesandprocessthem:

  • 7/19/2015 Flux in Depth. Store and Network Communication. Minko Gechev's blog

    http://blog.mgechev.com/2015/07/18/flux-in-depth-store-network-communication-services/ 10/14

    Butwhythe Service moduleshuldlistenforstorechanges?Can'titlistendirectlyonthedispatcher?Mostlikely,inthestorewe'llhavesomelogicforhandlingtheactionpassedbythedispatcher(forexampleformattherawdatapassedbytheview).Ifthe Service modulelistensforchangesatthedispatcherwewillduplicatethislogictwice.

    Everythinglooksgoodsofar.Butthe Service moduleisstillahugeblackbox.InthenextsectionI'llsuggestasampledesignofthismodule.Ifyoudon'tagreewithsomething,haveanyquestionsorrecommendationsletmeknow.

    The Service ModuleIwaswonderingwhethertouseUMLforshowingthecomponentsbuildingthe Servicemodule,howeverIchoosetomakeacolorfuldiagramliketheonebellow:

  • 7/19/2015 Flux in Depth. Store and Network Communication. Minko Gechev's blog

    http://blog.mgechev.com/2015/07/18/flux-in-depth-store-network-communication-services/ 11/14

    Therearealotofboxeshere.Theyellowonesarepartofthefluxarchitecture.Theblueonesareresponsibleforsendingupdatesfromtheapplicationtotheremoteservice,theredonesareresponsibleforhandlingnetworkeventsandthegreenonesaretheintersectionbetweenthelasttwocategories.Onecomponentcouldbeimplementedwithafewclasses,we'renotrestrictingourselvestothesecomponents.Wecanthinkofthemmorelikecategoriesratherthenspecificclasses.Herewe'lldemonstrateasampledecompositionoftheservicemodule.Letsdescribethemostinterestingcomponentsonebyone.

    Channel

    Abstractchannel.Itcouldbeextendedby HTTPChannel , WebSocketChannel ,WebRTCDataChannel ,etc.

    Package

    The Package componentrepresentsthepackagesusedbyourprotocol.Therecouldbeahierarchyofpackagetypes.Forexample,ifwebuildourprotocolontopofJSONRPC,wemaywanttoextendthebase Package class.

    Command

    ImplementstheCommanddesignpattern.

    CommandDispatcher

    Responsiblefordispatchingcommands.There'sonemorelink,whichisnotrepresentedonthediagramthe CommandDispatcher ownsreferencetothe Channel component.Itcheckswhetherthechannelisopenbeforesendingthecommand,ifitisn'tthe CommandDispatcherretriesafteragiventimeout.Thiscomponentisalsoresponsibleforbufferingcommands,invokingtheirundoactionsincasethecommand'sexecutionfails.The CommandDispatchermayimplementdifferentdispatchingstrategies:

  • 7/19/2015 Flux in Depth. Store and Network Communication. Minko Gechev's blog

    http://blog.mgechev.com/2015/07/18/flux-in-depth-store-network-communication-services/ 12/14

    Request/responseSlidingwindowtechniqueBuildagraphofthedependenciesbetweenthecommands,processatopologicalsortandinvokethecommandsintheappropriateorder

    StoreObserver

    The StoreObserver isresponsibleforhandlingchangeeventsofthestore.Onceitdetectschangeinthestoreitcreatesanewcommandusingthe CommandBuilder andinvokesitthroughthe CommandDispatcher .

    NetworkObserver

    Waitsfornewmessagesemittedbythedata Channel .Thiscomponentisresponsibleforparsingthemessagesandprocessingthem.Oncethemessageisparsed,basedonitscontentthe NetworkObserver invokesspecific Action .

    Third-party ServicesIfyou'reusingathirdpartyservice(Twilioforexample)youcanprocessinasimilarfashion.Youcancreateawrapperoftheservice(inthecaseofTwilio,the Twilio global)andbringitinyourfluxdataflow.

    Quick FAQ:

    Isn't NetworkObserver a"Godclass"?Yep,itis.Youcandecomposeitintoafewsmallerclasses,samefor CommandDispatcherwhereyoucanusethestrategypatternfordispatchingthecommandsintheappropriateorder.

    Whatarethese ProtocolDecorators?Sincewecancreateourprotocolbasedonanother,alreadyexistingprotocol(JSONRPC,BERTRPC,etc.),wecanprocesstheincomingmessagesbyusingachainofdecorators.Forexample,wereceiveabasicstring,nextthe JSONRPCDecorator canparseittoavalidJSONRPC messageandpassittothenextdecorator( YourCustomProtocolDecorator),etc.

    Can'tIgetcascadingupdateswhenupdatethemodel?Can'tIreachaconditioninwhichtheviewupdatesthestore,itemitsachangeevent,whichisbeinghandledbythe Servicemodule,whichemitsanevent...etc.?Thiscanhappen.Therearetwosimplesolutions:emitchangeeventonlywhenthevalueofgivenpropertyisactuallybeingchangedemit uichange eventwhenupdatethemodelfromtheviewandemit serverchange eventwhenchangeitfromtheserver.Therootcomponentcanlistenfor /change/ events(yeah,thisisaregex)andtheservercanlistenfor uichange .

    Ithrowaneventbutafewstoresarehandlingit?!

  • 7/19/2015 Flux in Depth. Store and Network Communication. Minko Gechev's blog

    http://blog.mgechev.com/2015/07/18/flux-in-depth-store-network-communication-services/ 13/14

    Mostlikelyyouhavecollisionintheactiontypes.I'dsuggesttousethefollowingschemafornamingthem: storename:actionname orsomethingsimilar,whichguaranteesuniqness.

    ConclusionThefirstpartofthispostshownhowwecanwirethestorewiththeview.Thesecondpartwasaboutthebasicideaofthenetworkcommunicationwithexternalservices.Thelastsectiondescribedasampleimplementationoftheblackboxresponsibleforhandlingexternalmessages,storechanges,serializationofthestoreandsendingitthroughthenetwork.Althoughthefirsttwopartswererelativelycanonicalandpredefinedbyflux,thelastchapterwascompletelycustomimplementation.WithitIwantedtoimplythatthemicroarchitectureweuse(MVC,MVP,MVVM,flux,whatever)doesnotprovideustheentireprojectdesign.Itonlyputssomerulesonhowweshouldorganizeourapplication,definesthemainbuildingblocksandhowwecanwirethemtogether,however,ifwewanttobuildareallifeapplication,mostlikelywe'llneedtoputsomeadditionaleffortthearchitectureortheframeworkwon'tbeabletosolveallourconcerns.

    Minko GechevJavaScripthacker

    FluxinDepth.StoreandNetworkCommunication.waspublishedonJuly18,2015.

  • 7/19/2015 Flux in Depth. Store and Network Communication. Minko Gechev's blog

    http://blog.mgechev.com/2015/07/18/flux-in-depth-store-network-communication-services/ 14/14

    FluxinDepth.OverviewandComponents.4comments2monthsago

    JavaScript,theweirdparts3commentsayearago

    SingletoninJavaScript2commentsayearago

    AngularJSinPatterns(Part3)1commentayearago

    ALSOONMINKOGECHEV'SBLOG

    0Comments MinkoGechev'sblog Login1Share SortbyBest

    Startthediscussion

    Bethefirsttocomment.

    WHAT'STHIS?

    Subscribe AddDisqustoyoursited Privacy

    Recommend

    (VIEW ALL POSTS)YOU MIGHT ALSO ENJOY

    UsingJSXwithTypeScriptFluxinDepth.OverviewandComponents.EvenFasterAngularJSDataStructures

    2015MinkoGechev.SofiaValley