Klávesové zkratky na tomto webu - rozšířené Na obsah stránky

Transducers

| Moje práce

Transducery. O co jde? To je zas nějaká super cool novinka, co za pár měsíců přejde v zapomnění? Proč bych se o to měl jako zajímat? Pomůžeme mi to nějak?

Otázky. Spousta otázek.

Buďte v klidu. O nic velkýho nejde. V podstatě to nás uživatele může nechat chladnými. Zase další map, filter, reduce bla bla bla.

A nebo taky ne.

Transducery na první pohled nepřináší nic nového. Máme tu další řadu standardních dataflow kombinátorů, které má každý moderní jazyk a Clojure jakbysmet. Od samého začátku. Samozřejmě. Na druhý pohled, to je vlastně to samé jako před dvěma lety představené reducery. Skoro.

Zpátky do minulosti

Začněme pěkně od začátku. Clojure obsahuje sadu standardních kombinátorů pro definici dataflow na kolekcemi dat. Jak asi takové kombinátory fungují, jsem si už ukázali v článku Funkcionální přístup ke kolekcím. Implementace v Clojure se moc neliší. Co je důležíté vědět je, že implementace vědí s jakou datovou strukturou mají co dočinění. Nebo to aspoň tuší a podle toho se chovají. Dále je dobré vědět, že když vytváříme dataflow pipeline, máme dvě tři možnosti jak toho dosáhnout:

  1. standardní kompozice
    (reduce + (filter odd? (map #(+ 2 %) (range 0 10))))
  2. funkcionální kompozice
    (def xform
      (comp
        (partial reduce +)
        (partial filter odd?)
        (partial map #(+ 2 %))))
    (xform (range 0 10))
  3. threading macro
    (->> (range 0 10)
         (map #(+ 2 %))
         (filter odd?)
         (reduce +))

První příklad musíme číst zevnitř, abychom pochopili, co se děje. Tj. vytvoříme posloupnost 0..9, ke každéme prvku přičteme 2 a vybereme jen ta lichá, která nakonec sečteme. V druhém případě složíme funkci z částečných aplikací kombinátorů a pak ji zavoláme nad požadovanou kolekcí. Kombinátory skládáme opět odzadu. Třetí zápis otáčí posloupnost instrukcí tak, jak je náš mozek vnímá, že by opravdu měly jít za sebou.

V roce 2012 Rich představil reducery. Cílem reducerů je vyřešit některé problémy, které klasicke kombinátory mají. Tak zaprvé je tu problém s alokací dočasných kolekcí. Každý kombinátor si zpravidla vytváří svou vlastní nad kterou pracuje následující v řadě. Reducery ve vnitř nevytváří své kolekce, ale přispívají do redukčního procesu. Vytváří tak recepty, jak se mají kolekce zredukovat.

(require '[clojure.core.reducers :as r])
(def xform
  (comp
    (r/filter odd?)
    (r/map #(+ 2 %))))
(reduce + (xform (range 0 10)))

Reducery si musíme vyžádat z jejich vlastního prostoru názvů. Můžeme je komponovat bez nutnosti částečné aplikace. Kouzelné macro vytváří unární variantu funkce bez kolekce a částečnou aplikaci doplní za nás. Ale kód se o něco lépe čte a je potenciálně paralelizovatelný. Každopádně tok funkcí je pořád od zadu.

core.async

V roce 2013 Rich představil cose.async implemantaci CSP. Záhy začali s implementací dataflow kombinátorů nad asynchronními kanály. Až najednou zase všechny zmizely…

Tím se dostáváme ke vzniku transducerů. V jeden okamžik už toho měl Rich dost a řekl: “To jako budeme pro každý typ datových kolekcí vytvářet nové a nové kombinátory? Nešlo by to jinak?” Hammock time!odpověď jsou Transducery!

Transducers

Transducery se snaží oprostit podstatu dataflow kombinátorů od implementačních detailů kolekce. Vytváříme tak obecné recepty, co máme s daty dělat, ale už nám chybí popis jak.

(def xform
  (comp
    (map #(+ 2 %))
    (filter odd?)))
(transduce xform + (range 0 10))

Všimněte si dvou lehkých rozdílů oproti příkladu s reducery. Ten první je, že transducery funkcionálně komponujeme v pořadí, jaké předpokládá mozek. Ten druhý je, že transducery nevoláme přímo, ale předáváme je funkci vyššího řádu. Oproti klasickým kombinátorům nejsou potřeba žádné mezivýsledky v podobě kolekce, protože jde o aplikaci jediné funkce, která kompozicí vznikne.

Ten samý recept teď můžu vzít a použít ho na data procházející kanálem:

(chan 1 xform)

Fajne je, že recept nemusím nijak parametrizovat. Je to hotová konkrétní věc a to, jak budou vykonány, záleží na funkci, která je dostane.

Záměrně jsem se nepouštěl do rozborů, jak jsou jednotlivé kombinátory implementovány. To máte jak s monádama – je lepší věděť, jak je použít, než jak jsou implementovaný.

Autor: Aleš Roubíček |

Proč je [programovací jazyk X] rozhodně lepší než [programovací jazyk Y]

| Jen tak

Poslední dobou můžete najít spoustu srovnání, proč je [X] lepší než [Y], často ale může být pozorný čtenář ještě víc zmaten. Nakonec, vždyť oba jazyky jsou [pardigma] orientované, které běží na [platforma] a usnadňují programovat [styl] stylem, zatímco ponechávají dostatek flexibility, abyste mohli psát [sračkoidní kód].

Jelikož jsem napsal [jednoduchý CRUD backend] v obou jazycích, cítím se být dostatečně kvalifikovaný na to, aboch některé věci vyjasnil. Představte si [jednoduchý problém, který byste zadali páťákovi, který se učí programovat]. Implementace v [Y] by mohla vypdat nějak tak:

[Opravdu špatný kód v Y ]

Naproti tomu v [X] by to mohlo vypadat jen takhle:

[Vyleštěný kód v X, který předvádí syntaktický cukr]

Je celkem jasné, že druhá ukázka je mnohem snažší na pochopení a odolnější vůči chybám.

Teď zvažmě typové systémy. [Přesvědčení o tom, jaké relativní výhody a nevýhosy přináší statické/dynamické typování.] Jistě, [Y] nám dává [výhody Y typového systému nebo naopak jeho absence], ale vyváží to [nevýhody Y typového systému nebo jeho absence]? Jistě, že ne!

Dále se musíme podívat na buildovací nástroje. Zatímco [Y] používá [nástroj, kerý jsem se neobtěžoval pochopit], [X] používá mnohem vychytanější [nástroj, který jsem trošku pochopil]. To je dostatečný důvod na switch!

Podívejme se na to obšírněji. [X] má úžasnou [featura specifická pro X IDE, která je stále v alpha verzi] a také má skvělou integraci do [asi 50 let starý textový editor, jehož klávesové zkratky vycházejí z klingonštiny] a [IDE, které všichni používají a z hlouby duše nenávidí]. Jistě, [Y] taky můžete psát v některém z nich, ale je to mnohem složitější a bolestivější.

Nakonec, ikdyž je tu místo pro vícejazyčnost na platformě [platform], bylo by lepší, kdyby se šli [Y] programátoři někam zahrabat, nebo switchli na [X] a soupeřili s náma o hrstku [X] pracovních míst. Počkat, beru zpět. [Y] je úžasný!

Volný překlad článku od Joela Gruse – Why [Programming Language X] Is Unambiguously Better than [Programming Language Y]

Autor: Aleš Roubíček |

Velká pyramida

| Jen tak

Programátoři dostali na starost projekt na zelené louce: „Postavte pyramidu.“

Úkolu se chopili svědomitě. Architekturu rozdělili do tří vrstev, protože tak se to vždycky osvědčilo. Nejprve začali návrhem databázového modelu. Po dlouhosáhlých debatách, jestli použít Oracle nebo zkusit nějaké NoSQL řešení (třeba Mongo), zjistili, že pyramida žádnou databázi nepotřebuje.

Pro jistotu naimplementovali doménovou vrstvu. „Ta tam být musí!“ Byla to krásná velká koule z bláta. Nic na plat, že koule ani zdaleka pyramidu nepřipomíná, ale takhle to prostě dělají. Několik borců přišlo s návrhem elegantního řešení: „Uděláme novou verzi, která bude hranatější! Tady kluci už mají prototyp postavený na kolejích.“ Nutno dodat, že to byl velice krásný dodekahedron.

Pak přišla na řadu vrstva servisní, kde se použilo WCF, protože v něm lze prát RESTový i SOAP služby vpodstatě najednou. A tak se stalo, že nová vrstva okolo koule z bláta vypadala úplně jako, když si vytáhnete sluchátka po týdnu z kapsy – klubíčko neštěstí.

Blížil se šibeniční termín a nikomu ta změt stále pyramidu nepřipomínala. Pozvali si tedy ostřílené konzultanty, kteří už měli za sebou zkušenosti se stavbou zemljanek a dětských hřišť. Po dlouhých debatách přišli s geniálním řešením: Потёмкин.

Kouli z bláta obalenou změtí kabelů schovali za krásnou kulisu vyrobenou z fotky z Gízy. Detailu, že fotky z webu nejsou v dostatečným rozlišení pro tak velkou kulisu, si nevšímejte. Stačí nechodit moc blízko.

Autor: Aleš Roubíček |

Reaktivní programování

| Moje práce

V uplynulém roce se začaly hejbat ledy okolo rektivních extenzí a reaktivního programování vůbec. A já byl u toho. :)

Reaktivní manifest

Byl publikován Reaktivní manifest, který se snaží definovat, jak mají reaktivní aplikace vypadat a proč.

  1. Mají reagovat na události
  2. Mají reagovat na zátěž
  3. Mají reagovat na selhání
  4. Mají reagovat na uživatele

Manifest vyjadřuje moje snažení v uplynulých letech, takže jsem ho samozřejmě signoval.

CZPodcast

Již potřetí jsem byl pozván do CZPodcastu, abychom se pobavili o reaktivním programování, reaktivním manifestu a reaktivních extenzích.

CZ Podcast 92 – Reaktivní programování by Aleš Roubíček on Mixcloud

DevFest Pardubice

Na DevFestu jsem měl přednášku o Reaktivním programování a reaktivních extenzích.

Autor: Aleš Roubíček |

Mikroslužby

| Moje práce

Máme tu jedinečnou příležitost definovat si Mikroslužby ne v tom, co nejsou, ale v tom co jsou.

Tohle je má definice.

Definice

Mikroslužba je oddělený izolovaný a pojmenovaný kus logiky, který konzumuje 0..N vstupů a produkuje 0..N výstupů, který je vykonaný za účelem přinést konzumentovi nějakou výhodu. Toto je poskytováno jako služba.

Oddělená

Důvodem, proč to nazýváme Mikroslužbou a ne Službou, není počet řádek, který je menší než N, nebo velikost nasazované služby, která je maximálně N kilobajtů nebo žádná jiná libovolná metrika. Tím důvodem je nízký počet zodpovědností: jedna. Dělá to jen jednu věc a tu dělá skvěle.

Izolovaná

Izolovaná znamená, že funguje odděleně od ostatních věcí, což z ní dělá distribuovanou entitu. Nezáleží na tom, kde konkrétně leží fyzický hardware nebo na jakém OS to běží. Pokud to spadne, zůstává to v izolaci. Předchází se tak kaskádovému šíření chyby. Navíc nám to umožňuje snadno vyvíjet a aktualizovat službu samostatně.

Pojmenovaná

Jelikož jsou Mikroslužby izolované, potřebujeme na ně nějakým způsobem odkazovat. Jméno v kombinaci se vstupy a výstupy Mikroslužby nám definují signaturu nebo identifikátor Mikroslužby.

Vstupy a výstupy

Pokud máme jazyk, který podporuje typové informace, vstupy a výstupy mohou být typové. Tyto typy by měly být reflektovány při manipulaci. Což znamená, že konzument služby by měl znát, co služba přijímá a co poskytuje.

Vykonání

Protože konzument není ten, kdo vykonává logiku Mikroslužby, a Mikroslužby jsou přirozeně distribuované, volání nesmí konzumenta blokovat ve vykonávání jiných operací po dobu výkonu mikroslužby. Konzument nesmí být držen jako rukojmí, dokud mikroslužba nevyprodukuje svůj výstup. To znamená, že musejí být vytvořeny takové abstrakce, které nám umožní Mikroslužby konzumovat asynchronně.

Překlad článku Microservices od Viktora Klanga

Autor: Aleš Roubíček |