Komentáře k článku

Potřebujeme Flux?

Flux je návrhový vzor spojený hlavně s knihovnou React. Je vždy potřeba s Reactem tento vzor používat? Existují i jiné přístupy, která nám práci s Reactem usnadní? Co když používám Angular? Na tyto otázky bychom měli najít odpověď v tomto článku.

Zpět na článek

40 komentářů k článku Potřebujeme Flux?:

  1. steida

    Vynikající článek Aleši, bravo.
    Vynikající článek Aleši, bravo. Jen pár poznámek.

    Ad „Problém první: distribuovaný mutabilní stav“
    Flux vznikl ještě před tím, než byli immutabilní struktury v JavaScriptu dostupné. Ano vím Mori, ale stejně. Protože jsem nové Este vyhodil nedávno, už jsem mohl využít immutable.js, a stav ze storů odstranit. Princip Fluxu ale není v ukládání stavu ve storech, to byla spíše znouzecnost. V Este jsem Flux upravil tak, aby zůstal zásadní princip, ale stav byl na jednom místě. A to bez použití vlastní implementace, čistě jen úpravou designu. Props se používají stále, ale jen pro potomky kompozitních component, aby bylo možné jednoduše využít PureRenderMixin. Samotné kompozitní komponenty čtou ale ze storů, ale tam nevidím rozdíl mezi předáním prop, a načtením pomocí ze storu pomocí get metody. Story jsou readonly, takže je nelze z komponent měnit. Výhodou je, že komponenta je v UI nezávislá, tedy že její rodiče neznají její props. Samozřejmě že to lze i jinak, ale i tak by každý měl Flux znát. Vědět, k čemu jsou akce a dispatcher, a proč jde o násobně čistší řešení, než Backbone nebo event observing. Pak se samozřejmě může posunout dále. Takže říct, nepotřebujeme Flux… no chápu, taky bych ten titulek takhle napsal :-), ale pravda je taková, že koncepty Fluxu: Akce, unidirectional data flow a story jako reduce, svět znát sakra potřebuje.

    Ad „Problém druhý: natvrdo zadrátované posílání zpráv“
    „polymorfní zpracování zpráv“, tim myslíš, že zprávy jsou instance? Tomu jsem se snažil vyhnout, dle mého se takové zprávy špatně auditují, mapují na event sourcing, a hlavně pokud uděláš instanci, někdo jiný ji může změnit, a jsme tam, kde jsme byli – muttable hell. Možné řešení by mohl být http://facebook.github.io/immutable-js/docs/#/Record, ale než si budu jist, je imho Este.js řešení, akce je akce (jak tautologické!) nejlepší.

    Ad „uděláme z pohledu Fluxu prasárničku a spojíme Store a Dispatcher“
    Tohle imho dělá i ještě nepublikovaný Relay, ale i tak je dobré znát Flux, jinak lidi nebudou chápat, proč je tak nevržen.

    V novém Este jsem se snažil o maximální čistotu návrhu, aniž bych musel implementovat vlastní Flux, nebo použít cokoliv jiného než základní dispatcher. Jde především o patterny. I tak je aplikace mnohem čistější, než cokoliv co jsem kdy před Fluxem viděl, nepočítám-li ClojureScript, Elm, a podobné. A samozřejmě, každý může vzít Este.js, a upravit ho dále podle tvého článku, nebo místo dispatcheru použít csp-js, nebo si počkat na Relay.

    Ad stores. Speciálně v Este nedrží stav, ale poskytují jen různé pohledy, filtery, reduce, sort atd. nad global app state, tohle je dobré mít v aplikaci dělené podle features, takže by si programátor stejně musel nějaké „story“ vytvořit.

    Ad immutable.js contrib/cursor. Ten jsem zvažoval, ale nějak jsem nepochopil, v čem je lepší než mé řešení, které se bez nej obejde. Navíc contrib/cursor má dost issues. Přehlédl jsem něco?

    Ad kefir, jak řeší unidirectional flow, tedy že můžeš prstem (dobře, pomocí console.log) ukázat na místo app, skrze které tečou všechny události? Skládáním streamů? Hnaním všechno přes jeden stream? Jinak?
    A ještě jedna otázka, Sebastian naznačuje, že Rx model jde proti Om modelu. Mrkni na diskuzi. Koukal jsem na odkaz, ale příklad se zná nekompletní. Nechtěl bys předělat Este TodoMVC tak, aby šlo porovnat s Kefírem?

    A poslední otázka, přemýšlel jsi nad csp-js s transducers versus Rx ala Kefír? Mne se zdá csp-js ještě o trochu lepší, než Rx, ale tady se přiznám nemám silný názor.

    Ještě toho mám v hlavě více, ale to si nechám na jindy. Ještě jednou díky za skvělý článek.

    1. Aleš RoubíčekAutor příspěvku

      Re: Vynikající článek Aleši, bravo.
      Díky Dane.

      Jsem dalek toho tvrdit, že Flux je k ničemu. Mám sice k němu své výhrady, ale když někomu vyhovuje proč ne? Chtěl jsem ukázat, že na některé typy aplikací se dají použít i jednodušší vzory. Vím o tom, že existují aplikace, které by asi z tohoto vzoru moc užitku neměly. A to je zcela v pořádku, nehledám žádnou panaceu a jeden jediný vzor na všechno. Každá aplikace má svá specifika a rozdílné požadavky a rozsah, s kterým je potřeba se vypořádat individuálně. :)

      Polymorfní zpracování zpráv vůbec neznamená, že jde o nějaké instance. Naopak. Když se podíváš na ukázku jsou tu dva typy zpráv. Interně jsou reprezentovány jako Immutable.List parametrů a přistupuje se k nim pozičně. Polymorfismus se skrývá v tom, že nikde nemám natvrdo switch, který zná konkrétní typy zpráv a z každým novým typem je potřeba ho upravovat. Naopak je emitace a subscribce observerů zcela otevřená pomocí metod on/emit, kde funguje velice primitivní pattern matching na první parametr zprávy (lehká inspirace z Elixiru).

      Rrozdíl reaktivní stramy vs. CSP je v non-blocking vs. blocking zpracování a Rx mají aktuálně mnohem bohatší sadu užitečných operátorů a kombinátorů. Rx můžeš používat i ES3, kdežto na na CSP potřebuješ ES6. Generátory se teprve před týdnem objevili v Io.js a ve stable Chrome. Použití Kefíru se ukázalo i jako výhodná cesta jak zkrotit jednu komponentu, která byla silně postavená na událostním modelu a díky reaktivnímu přístupu jsem mohl mnohem jednodušeji řešit věci jako drag’n’drop aniž bych musel řešit sdílený mutable stav. Navíc Kefír si rozumí s transducery. Pro mě win-win situace.

      Ačkoli nepopírám, že Omem jsem se inspiroval, neznamená to, že nemám svoje názory jak strukturovat aplikace a že se vším v Omu souhlasím. Ani David netvrdí, že je to jediná správná cesta, ale PoC, který se ukázal jako celkem zajímavou alternativou. Navíc CLJS a JS mají svá specifika a nejde úplně bezhlavě věci z jedno cpát do druhýho. Rx může jít proti Omu, ale neznamená to, že Rx+React jsou něco špatnýho. Je to dobrá alternativa k Fluxu, ale musíš vědět proč a na co to potřebuješ. Věřím, že ty víš. :)

      Ad Cursor. Contrib implementaci jsem zvolil pouze protože mi na daný problém přišla good enough a nemusel jsem ji z něčeho vysekávat. Kdybych si myslel, že este.js přístup je špatný, ani bych ho neodkazoval. :)

      Ještě jednou díky za zajímavé postřehy!

      1. steida

        Re: Vynikající článek Aleši, bravo.
        Díky za vysvětlení polymorfního zpracování zpráv. Některé Flux implementace to tak dělají, ale já chtěl zachovat čistý Flux. Samozřejmě, šlo by to implementovat i s eventy nebo pattern matchingem, ale ani switch není nijak zlý, pokud se porovnávají pouze konstanty.

        CSP má blocking zpracování? Zde na přednášce to tak nevypadá, transducery jsou tam demonstrovány také. Nicméně ano, máš pravdu, bez transpileru by to v současných prohlížečích nešlo. Avšak babeljs a csp-js jedou. Souhlasím, kefir je použitelný teď, kdežto csp-js s ES7 ještě potřebuje usadit.

        Ad struktura aplikací, souhlasím a od Davida jsem to taky někde slyšel. Škoda, že nemám času si hrát s ClojureScriptem a jeho ekosystémem více.

        Ad Cursor, díky :-)

        1. Aleš RoubíčekAutor příspěvku

          Re: Vynikající článek Aleši, bravo.
          CSP vyžaduje, aby zapisovaná data do kanálu někdo z druhé strany četl, pokud je nemá kdo číst, tak je proces blokovaný, dokud k přečtení nedojde. Aby nedocházelo k blokacím může se použít kanál s bufferem, který nám dovoluje umožňuje non-blocking zpracování, ale záleží na velikosti bufferu a rychlosti konzumentů kanálu.

          Pokud používáš nad kanálem transducery, tak buffer musíš použít, takže to v tomto případě není vyloženě blocking, proto to tak na té přednášce nevypadá. :) Ale musíš tyhle detaily znát. Každopádně transducery řeší jen jednu část problému, která jde modelovat redukcí procházejících dat.

          Práce s více kanály je mnohem méně příjemná než kombinace reaktivních streamů pomocí standardních kombinátorů. To není zrovna problém, který bys měl u messagingu nahrazujícím Dispatcher, ale jak už jsem psal jinde, Kefír jsem v aplikaci používal i na práci s async voláními na server a práci s eventama v komponentách, kde už jsem tyto věci využil.

          1. AltmanO

            Re: Vynikající článek Aleši, bravo.

            CSP vyžaduje, aby zapisovaná data do kanálu někdo z druhé strany četl, pokud je nemá kdo číst, tak je proces blokovaný, dokud k přečtení nedojde.

            Neni uplně pravda, CSP má asynchronní verze operací put a take. Kde se nemusí používat buffer a operace vložení neni blokující (nemusí být ani v go blocku). Když se použijí transducery, musí se použít bufferSize == 1 a tohle neblokující chování funguje pořád stejně.

            příklad:

            var myChan = csp.chan(1, transducers.map((n) => n*2));
            
            csp.putAsync(myChan, 1);
            csp.putAsync(myChan, 2);
            csp.putAsync(myChan, 3);
            csp.putAsync(myChan, 4);
            csp.putAsync(myChan, 5);
            
            csp.go(function* () {
                yield csp.timeout(10000);
                while(true) {
                    console.log(yield myChan);
                }
            });
            

            Osobně myslím že CSP je flexibilnější než reaktivní streamy a dá se pohodlně použít na větší množství problémů.

            1. Aleš RoubíčekAutor příspěvku

              Re: Vynikající článek Aleši, bravo.
              Z dokumentace:

              If no argument is passed, the channel is unbuffered. This means that putters will „wait“ for takers and viceversa (synchronization).
              If a number is passed, the channel is backed by a fixed buffer of that size (bounded asynchronization).

              1. AltmanO

                Re: Vynikající článek Aleši, bravo.
                Ten text z dokumentace hned potom pokračuje:

                We can put and take values asynchronously from a channel:

                var ch = csp.chan();
                
                csp.takeAsync(ch, function(value) { return console.log("Got ", value); });
                
                // After the put, the pending take will happen
                csp.putAsync(ch, 42);
                //=> "Got 42"
                

                kdyby to opravdu nešlo a bylo blokující tak by ten příklad co jsem postnul o komentář výš nefungoval.
                Pořád si myslím že reaktivní streamy oproti CSP nemají co nabídnout.

  2. steida

    oprava
    Blbě jsem se vyjádřil, samozřejmě jsem myslel napsat vlastní implementaci TodoMVC tak, aby byla funkčně paritní s Este TodoMVC.

  3. AltmanO

    Om.js ?
    Pěkně napsané :)

    Přijde mi že jak článek tak i Este se ve velké míře inspirovali ClojureScriptem (immutable hodnoty) a zejména Om knihovnou (globální stav, ref-cursory). V ClojureScriptu je pořád ještě spoustu myšlenek, který ve světě JS nejsou, je dobře že se dobrý nápady se šíří mezi jazykama.

    1. Aleš RoubíčekAutor příspěvku

      Re: Om.js ?
      Díky

      Ano, oba jsme se v CLJS inspirovali a každý jsme pro messaging zvolili jiný přístup, který se nám líbí/vyhovuje. U mně ta inspirace pochází z toho, že prototyp aplikace, ze které tento článek vychází, byl psán v Om/CLJS.

  4. tobik

    Pár poznámek
    Na přednášce jsem byl a už tehdy mě napadlo pár připomínek, a po přečtení článku jich mám ještě více.

    Dispatcher musí často koordinovat změny na několika místech

    Jak toto může nastat? Nemá Dispatcher fungovat tak, že přijme akci a rozešle ji na všechny Story?A Story si pak samy rozhodnou, jestli akci zpracují či ne. Aspoň tak to Facebook nadefinoval, když uvedl Flux. O jakou koordinaci se jedná?

    React komponenty se rázem stanou mapovací funkcí, kterou aplikujeme na stav a dostaneme aktuální zobrazení.

    Jaktože toto neplatí už v „klasickém“ Fluxu? Veškerý stav je uložený ve Storech a je zpřístupněn přes read-only rozhraní. Obsah Storů přesně definuje stav uživatelského rozhraní. Už samotné slovo „uniderctional“ jednoznačně implikuje souvislost s funkcemi. A s tím souvisí toto:

    Problém první: distribuovaný mutabilní stav

    Dále má komponenta jen svůj vnitřní stav, který je aktualizován při změně v úložištích. A pak si vemte, že v běžné aplikaci máte úložišť víc než dvě. Věci se začnou komplikovat.

    Jakým způsobem se věci začnou komplikovat? Změní se stav nějakého Storu, komponenta je na něj subscribnutá, tak se překreslí. Samozřejmě problém může být, když každý Store bude říkat něco jiného. Ale to je chyba konkrétní implementace, nikoliv architektury. A jak říká přímo Facebook: Single source of truth. Na to stačí dávat pozor.

    Tj. problém s mutabilním distribuovaným stavem vyřešil už čistý Flux sám o sobě tím, že zavedl jednosměrný proud informací. Není mi jasné, jak použití immutable objektu na tom cokoliv mění.

    No a pak je tu ten globální stav. Globální stav je fuj a vůbec nejde jen o mutace (i když ty jsou to nejhorší, samozřejmě). I když z globální stavu pouze čtu, tak to vytváří závislost (která nemusí být vždy hned patrná) a především se určitě se shodneme na tom, že v čím menším scopu/kontextu se programátor pohybuje, tím pro něj lépe.

    To mě na JavaScriptových programech pořád překvapuje, jak běžně se používají globální instance objektů a služeb. Chápu, že prostředí okna prohlížeče k tomu tak trochu vybízí, nicméně i u PHP (kde rovněž pro každý request vzniká/zaniká celá samostatná instance prostředí) se už přišlo na to, že to není úplně dobrá praktika a běžně se používají DI kontejnery apod. U JavaScriptu a potažmo Reactu a Fluxu mě to překvapuje o to více, že díky node.js se to dá používat i na serveru, kde se nicméně kontext sdílí pro všechny příchozí requesty. Jak jsem se díky @steida poučil, lze používat singletonové Story i na serveru, ale osobně mi to pořád přijde více jako trik než ta správná cesta.

    Ta databáze je pěkné přirovnání (rozvedu dále), ale ani s databází nepracuji jako s celkem. Databáze je rozdrobená na jednotlivé tabulky, přičemž nad každou skupinou tabulek jsou typicky 2-3 vrstvy abstrakce a v konečném důsledku s databází pracuji skrz nějaké čtivé unifikované rozhraní a měním data v omezeném rozsahu. Cursory toto suplují jen částečně. Čímž se dostávám k:

    Takže teď uděláme z pohledu Fluxu prasárničku a spojíme Store a Dispatcher do jednoho objektu.

    Důležitou součástí každého (klasického) Storu je i to veřejné API, skrz které čtou data komponenty, a pokud je to API navržené dobře, tak i ten kód komponenty je lépe čitelný (rozhodně lépe, než za přímého použití kurzorů). Z této perspektivy se mi líbí prezentované TodoMVC od @steida a jeho *state-less“ Story. Centrální immutable objekt stavu tady funguje jako databáze a jednotlivé Story jako repozitáře, přičemž skrz cesty v immutable objektu přistupujeme k jednotlivým „tabulkám“.

    Nicméně se nemůžu zbavit pocitu, že z hlediska Fluxu se v konečném důsledku nezměnilo téměř vůbec nic. Vyměnili jsme úložiště, vyměnili jsme databázi, a to nám přineslo pár cool fičurek navíc:

    • Máme podporu pro historii (což je upřímně opravdu cool, ale v kolika projektech je to skutečně potřeba?)
    • Můžeme snadno serializovat/deserializovat stav celé aplikace (to šlo už předtím, jen to bylo o něco méně elegantní)
    • Je to rychlejší (nebyl React už sám o sobě hodně rychlý?)

    Já tyto výhody samozřejmě nechci nějak zlehčovat, ale z hlediska Fluxu mi to přijde pouze jako incrementální zlepšení, tj. mnoho povyku pro nic.

    1. Aleš RoubíčekAutor příspěvku

      Re: Pár poznámek
      Ahoj, díky za super postřehy.

      S Dispatcherem jsem trochu přestřelil. Od Kefírového emmiteru se moc neliší. Pokud někdo nepotřebuje výhody reaktivních streamů pak mu asi Dispatcher bude stačit. Každopádně nás to nezbavuje nutnosti switchů ve Storech. Osobně se mi ta i implementace hrubě nelíbí z důvodů, který jsem už popsal v článku.

      S tím jednosměrným proudem ve Fluxu to zas tak slavný není, protože povzbuzuje k používání lokálního stavu komponent, který nám v tom jednosměrným proudu dělá pěkné víry. :)

      Co se týče role úložišť jako „Repository„, tak to se mi osobně příčí. Zbytečné abstrakce nad databází už prokázaly svojí života neschopnost. Osobně preferuju QueryObjecty a vzhledem k tomu, že v JS objektů nutně netřeba, tak ideálním nástrojem jsou v tomto případě transducery, které tento koncept reprezentují pouhou funkcí. Nic nebrání tomu, mít místo abstraktních vrstev v podobě úložišť, mít sadu transducerů, které můžu aplikovat jak na immutabilní data tak na reaktivní streamy.

      Rozhodně nechci dělat nějaký povyk, chtěl jsem jen ukázat, že existují i jiné cesty a proč je považuju za lepší. Když se někomu některý z konceptů bude hodit má o to líp. Neprodávám jediný možný přístup a jak jsem psal výše Danovi ani nejsem přesvědčen o to, že by tento vzor byl vhodný na všechno. Mně to spoustu věcí ulehčilo v rámci projektu, který nebyl nikterak velký. Drobení konceptů a vytváření abstrakcí pro abstrakce se mi za mou dosavadní praxi neosvědčili.

      Ad rychlost. React je opravdu rychlejší než většina aktuálních JS frameworků, ale 2-3x zvýšený rychlosti jednoduchou změnou přístupu ke správě stavu je něco, co nám dá málo kdo. Proč zbytečně plýtvat omezenými zdroji mobilních zařízení? A jak jsem psal v článku tento efekt se projeví i u ostatních frameworků. U Angularu ten rozdíl může být i mnohem větší.

      Ještě jednou díky za postřehy a připomínky, určitě mám o čem přemýšlet.

      1. tobik

        Re: Pár poznámek
        Díky za odpověď.

        Ad Repozitáře: mně v zásadě jde jen o ten koncept „pojmenovávání dotazů“. Což může být klidně ta sada transducerů. Stejně tématicky blízké transducery budou v jednom modulu, odkud naimportované se budou používat podobně jak ten repozitář. A tomu modulu můžeme říkat („state-less“) Store, tj. je skoro zase jen slovíčkaření :)

        K tomu výkonu Immutable objektu: Jak doopravydy je to to výkonné? Teď by se mi to třeba hodilo nasadit do jednoho projektu, jen je problém, že ze serveru proudí JSONy v řádu megabajtů. Můžu si dovolit něco takového verzovat? A vůbec, je možné immutable global store nasadit na něco jako je třeba Gmail, což je rozsáhlá aplikace a především má v prohlížeči uptime v řádech hodin i klidně desítek hodin. Během té doby bude ten immutable objekt bobtnat a bobtnat…

        1. Aleš RoubíčekAutor příspěvku

          Re: Pár poznámek
          K slovíčkaření. To je strašně důležitá věc neříkat modulu, který nic neukládá, úložiště. Naše záměry musíme vyjadřovat jasně, aby se v tom vyznal každý. V

          K tomu výkonu. Zvýšení výkonu při renderování je až side efekt používání immutable struktur na dirty checking. Immutable struktury samy o sobě jsou pomalejší než čistá JS pole a objekty! Stejně tak mají větší paměťovou náročnost. To je potřeba brát v úvahu. Pokud máš převádět megabajty JSONu do immutable struktur, může to mít dopady na výkon jinde. Pokud chceš dělat větší změny nad immutable-js je dobré použít transientní struktury pomocí metody withMutations a mutace tu izolovaně nabatchovat.

          Jak už jsem tu několikrát psal, každá aplikace má své specifické požadavky a vždy je potřeba konkrétní přístup řešit individuálně.

          1. tobik

            Re: Pár poznámek
            No uznávám, že říkat „Store“ něčemu, co v sobě žádná data neobsahuje, je trochu na hlavu. :)

            Každopádně díky za článek. Určitě uvítám další takové. Do budoucna bych bral nějaký příklad trochu větší aplikace napsané v Reactu/Fluxu, která bude komunikovat se serverem (což je stejně v praxi alfou i omegou každé takové aplikace). Ono v okamžiku, kdy člověk začne řešit přechody mezi URL, formuláře, stránkování atd, tak zjistí, že cest, jak to řešit, je mnoho, ale málokterá vede do cíle.

  5. steida

    Ad rychlejší: Tam jde spíše o to, že když to děláme „správně“, není třeba nic optimalizovat, vůbec. Prostě je to nejrychlejší jak to může být :-)

    Ad singletonové: Singleton je instance, Este.js nepoužívá ve Fluxu třídy ani instance, jsou to jen funkce a funkce není singleton.

    Ad jen čtu z globálního bez závislosti. Kdyby to bylo někde schované uvnitř kódu, pak ano. Pokud je závislost explicitně na začátku souboru vyjádřená pomocí import, je to ok.

    Jinak s ostatními poznámkami souhlasím.

    1. tobik

      Re:
      Čistě formálně označení singleton v tomto případě není úplně ideální, nicméně ta myšlenka za tím souhlasí. Datově ten Store (ať už samostatně či součástí globálního immutable objektu state) existuje v celé aplikaci nejvýše jednou. Což na straně serveru, který má vyřizovat množství oddělených požadavků, je prostě trochu zvláštní přístup (byť samozřejmě řešení, jak se s tím vyrovnat, existuje a funguje).

      S tím globálním stavem je to vtipné. Se slavně zavedl globální stav jakožto porušení starých pořádků, což kdyby byla skutečně pravda, tak by to byl průšvih, nicméně skutečnost je taková, že se pouze a jenom zavedlo oddělené úložiště pro Story na principu databáze, se kterým se dál pracuje (či mělo pracovat) jako s databází, tj. skrz další vrstvy abstrakce, které „globální stav“ zpět rozsekávají na drobnější oblasti, se kterými programátor pracuje.

      Když se ale vrátím zpět k prvnímu odstavci, tak ve všech ostatních (webových) programech se běžně počítá s tím, že lze jednu databázi vyměnit za jinou či dokonce udržovat více paralelních spojení (tj. připojení k databázi není globální). Tady ale ten global state je skutečně jen jeden…

      1. tacoberu

        Re:
        ad globální stav: Nebyl problém s globálním stavem jako zlem pouze v těch případech, kdy si funkce šahala na proměnné, které nedostala jako argument? To je určitě zlo, ale IMHO to není to, o čem autor hovořil.

        1. Aleš RoubíčekAutor příspěvku

          Re:
          Om tento přístup umožňuje a autor článku z něj vychází. Tato konkrétní aplikace globální stav jakoby nemá, ale instance application nejspíš bude dostupná globálně a pak transitivně application.state je globální stav na který si může kdokoliv šáhnout. Ne, že bych to nějak doporučoval, ale možné to je.

  6. steida

    lze jednu databázi vyměnit za jinou či dokonce udržovat více
    paralelních spojení

    Je jen jeden a tak to má být, protože máš v prohlížeči jen jednu instanci aplikace. Avšak můžeš ho kdykoliv celý změnit, jak ukazuje video v readme, můžeš ho ukládat a číst do localStorage, můžeš ze serveru dostat nový, to vše je už pouhý implementační detail.

    1. tobik

      Re:
      To určitě. Ale je tu paradoxní ten trend. V prostředí Apache/PHP se pro každý request také vytvoří jedna instance aplikace. Máme jeden globální prostor pevně svázaný s jedním requestem, tj. stejná situace. Ale stejné všechny moderní frameworky se odklánějí od statických tříd, singletonů atd. Celá aplikace funguje jako jeden instancovaný kontejner (tj. klidně v jednom requestu můžu pustit dvě instance Nette…).

      Chtěl bych v Reactu/Fluxu vidět napsaný nějaký Drupal či WordPress. A ideálně s isomorfním frontendem. Všechno, co zatím vidím, jsou spíše jen technologická dema. Existuje už něco takového?

      1. Aleš RoubíčekAutor příspěvku

        Re:
        Otázka je proč to borci v PHP dělají? Protože to viděli tak dělat borce v Javě? :) To jsem taky nikdy nepochopil. To jsou přesně ty abstrakce pro abstrakce aniž by dávaly jakýkoliv smysl.

        Proč se do toho pořád snažíš tlačit isomorfní pojetí? Na frotendu máš většinou jiný potřeby než na backendu. Pokud ne, tak můžeš použít služby jako Strongloop Loopback nebo Facebook Parse a zase to není třeba řešit…

        1. tobik

          Re:
          Mno, není to tak dávno, co isomorfismus byl #1 buzzword :) Ale teď se to nějak ztrácí.

          Každopádně tam strašně záleží, co za aplikace chceme psát. Kupř. když jsem poprvé viděl React, tak jsem si říkal, super, konečně se zbavíme všech šablonovacích jazyků a kódění v HTML. Místo toho bude mít skutečné komponenty, budeme rozhraní „stavět“ a ne splácávat z kousků HTML kódů. Krásně se to vykreslí na serveru a na klientu se bude pokračovat rychle JavaScriptově. Tj. nakombinují se výhody SPA a běžných webových aplikací. Napsat v něčem takovém WordPress se mi tehdy zdálo jako super nápad…

        2. Jenda

          Re:
          Proč to borci v PHP dělají? To je jednoduché, za svoji kariéru jsem už několikrát migroval aplikaci z jednoho frameworku do druhého. To je věc, která se dělá dost často a může jít i o migraci z jedné verze frameworku na jinou. Třeba Zend 1 na Zend 2. No a každé statické volání, každý singleton a každá skrytá závislost na globálním prostoru tuto migraci ztěžuje. Naposledy (bavíme se o roku 2014) jsem pracoval na aplikaci s desítkami tisíc řádků zdrojového kódu a tam už taková migrace nezabere několik odpolední, tam to trvá týmu programátorů měsíce. A každý je rád za každou abstrakci, protože to takový proces velmi zjednoduší.

        3. Jiří Knesl (autor)

          Re:
          Já bych řekl, že to dělají proto, že to dnes už není vůbec těžké (autowiring) a dává to při testování všemožné výhody. Dnes bych řekl, že není už potřeba nahrazovat pomocí DI úplně všechno, ale to většinou ani kontejner ani nijak nevynucuje.

          1. Jiří Knesl

            Re:
            sorry za to (autor), zdroják si to nějak pamatuje z článku, co jsem kdysi napsal a dal pod něj komentář a teď mi to sype všude, snad to touhle změnou zase zapomene :)

  7. Skalimil Vuk

    ES 6
    Díky za skvělý článek,

    na Kefir jsem narazil nedávno, streamy používám dlouho, eventy v pdosttaě také, ale takhle jednoduché propojení všeho do jednoho celku, to je vynikajicí myšlenka.

    Jen mám dotaz (obecnější). ES6 lze nějak přímo spustit ? V čem? Podle tohoto https://kangax.github.io/compat-table/es6/ jestli tomu dobře rozumím, tak nejlepší je asi to prohnat to přes Traceur, nebo Babel (ten používá i estejs), ale to změní zdrojový kód a je to pak méně přehledné (jasně, nevýhoda starého ES5).

    Takže do prohlížeče přes Babel?

    Aha, v konzoli mohu použít babel-node ./App.js. Jsem ze staré školy a používám debugger, ačkoliv všichni kolem jen testují :-) Je možné debuggovat přímo ES6 ?

    1. Aleš RoubíčekAutor příspěvku

      Re: ES 6
      Ahoj a díky!

      Některé featury ES6 už je možné používat v Io.js a poslední verzi Chrome. Ale třeba třídy mezi ně nepatří. Takže potřebuješ nějaký transpiler. V Reactu je přímo JSX, které s parametrem --harmony umí většinu potřebných ES6 vlastností. V ukázce je také dědičnost z React.Component, která je možná až od verze 0.13. Pokud chceš debugovat v browseru kód, který jsi psal, tak je potřeba zapnout emitování sourcemaps pomocí --enable-source-map. Další transpilery by sourcemapy měly umět také.

      1. Skalimil Vuk

        Re: ES 6
        Dík.

        Tu dědičnost z React.Component právě teď řeším. Starý způsob je předat cursorFor jako mixin přes React.createClass ?

        A nový způsob tvorby komponent dle té ukázky by se použil jako vytváření dalších potomků z té třídy ApplicationView, kde by byla jen jiná metoda render?

        class NejakaKomponenta extends ApplicationView

        A když budu chtít použít nějaké cizí komponenty, tak do nich také budu muset nějak dostat podporu kurzoru, nebo ne?

        1. Aleš RoubíčekAutor příspěvku

          Re: ES 6
          Mixiny nejsou ješte v class syntaxi podporovány. Stejně tak bych nikdy nedědil vlastní React komponenty.

          1. Skalimil Vuk

            Re: ES 6
            Možná něco dělám blbě, ale snažím se ten příklad zprovoznit a zatímco Application.js je bez problémů, propojení s react ApplicationView mi činí potíže.

            Došel jsem teda k tomu, že ES6 ApplicationVidew.js přeložím třeba takto:

            browserify --debug --transform  [ reactify --es6 ]  ApplicationView.jsx > bundle.js
            

            což ale samo o sobě nefunguje, protože ES6 syntakci import reactify neumí (a jsx také ne). Takže nejdříve potřeba změnit v ApplicationView.js:

            // import Cursor from 'immutable/contrib/cursor';
            var Cursor = require('immutable/contrib/cursor');
            
            // import {Component} from 'react';
            var Component = require('react').Component;
            
          2. Skalimil Vuk

            Re: ES 6
            zdravím,

            nechci obtěžovat, ale chtěl bych poprosit ještě o jednu radu.

            Jak propojím Application a ApplicationView?

            var Application = require("./Application");
            
            var ApplicationView = require("./ApplicationView");
            
            // aplikace vyžaduje dva parametry
            // initialData - to je jasné
            // view - to si myslím že je instance AppView, respektive React.Component
            
            var appView = new ApplicationView();
            
            var app = new Application(initialData, appView);
            
            // a ted vyrenderovat, jenže jak?
            // Normálně by bylo takto, ale tím vytvořím další instanci ApplicationView, která není propojená s instancí Application
            
            React.render(
                <ApplicationView />,
                document.getElementById('container')
              );
            
            // toto vrací chybu Invalid component element
            
             React.render(
                   appView,
                    document.getElementById('container')
                  );
            
            // a někde bych měl také volat, ne?
            app.render()
            

            Jak tedy vyrenderovat AppView?

            díky moc

            1. Aleš RoubíčekAutor příspěvku

              Re: ES 6
              Může to být trochu matoucí, ale view musí být už namountovaná komponenta:

              let view = React.render(
                  <ApplicationView />,
                  document.getElementById('container'));
              let app = new Application(initialData, view);
              app.render();
              

              Rootová komponenta se tak musí umět poprat s tím, že se má vyrenderovat bez počátečních dat, které mohou dorazit třeba asynchronně. Toho dá vyřešit třeba pomocí metody getDefaultProps.

  8. petr

    kolik streamu pouzivat v aplikaci?
    Ahoj,

    chtel bych se zeptat, kolik streamu pouzivate v aplikaci. Jestli jeden jediny na uplne vse (vcetne zadosti o data ze serveru), nebo vice streamu podle ucelu.

    Dik za odpoved.
    P.

    1. Aleš RoubíčekAutor příspěvku

      Re: kolik streamu pouzivat v aplikaci?
      Více, podle účelu. Jeden jako náhrada Dispatcheru.

  9. Petr

    Akce v akci
    Ahoj,

    chtel jsem se jeste zeptat, jak se ve FLUX resi, kdyz bych chtel v akci chce zavolat jinou akci?

Napsat komentář

Tato diskuse je již příliš stará, pravděpodobně již vám nikdo neodpoví. Pokud se chcete na něco zeptat, použijte diskusní server Devel.cz

Zdroj: https://www.zdrojak.cz/?p=14532