Hlavní navigace

Názory k článku Knihovny pro Go umožňující naplánování a spouštění periodických úloh

Článek je starý, nové názory již nelze přidávat.

  • 16. 4. 2019 1:38

    ivoszz

    Osobně si myslím, že v posledních pokračováních jdete proti duchu jazyka Go. Go má poměrně pokročilou standardní knihovnu time, které se dotknete ve dvou kapitolách a pak přecházíte na knihovny, které se snaží do Go naimplementovat používané API z Pythonu a Ruby. Ale jednou z filozofií Go je mít co nejméně závislostí mimo standardní knihovnu (výhody a nevýhody jsou mimo rámec takhle krátkého příspěvku). Takže místo idiomatického

    c := time.Tick(4 * time.Second)
    for now := range c {
        go task()
    }

    napíšete

    scheduler := clockwork.NewScheduler()
    scheduler.Schedule().Every(4).Seconds().Do(task)
    scheduler.Run()

    což není ani jasnější, ani na méně řádků, přináší to závislost, kterou musím spravovat, a skrývá to jakési API, které si musím nastudovat. Ze zápisu není jasné, jakým způsobem se task volá, takže to potřebuji ověřit ve zdrojovém kódu. Oproti tomu původní zápis je krystalický čistý a obsahuje nejelementárnější konstrukty jazyka.

    Pro pokročilé: Výše uvedený Go kód neumožňuje při případném ukončení cyklu (třeba přes select) uvolnit čítač (data leak). Takže je vhodná jen pro opravdu nekonečné smyčky. Pokud je potřeba cyklus někdy ukončit a čítač uvolnit, je potřeba explicitně vytvořit time.Ticker a ten poté uvolnit:

    ticker := time.NewTicker(4 * time.Second)
    defer ticker.Stop()
    
    done := make(chan bool)
    func AfterFunc(time.Minute, func() {
        done <- true
    })
    
    OuterLoop:
    for {
        select {
        case <-done:
            break OuterLoop
        case t := <-ticker.C:
            go task()
        }
    }
    ...
  • 16. 4. 2019 1:49

    ivoszz

    Omlouvám se za chybu, když jsem to psal, zapomněl jsem doeditovat zkopírovanou funkci AfterFunc, takže ta část má vypadat:

    ...
    done := make(chan bool)
    time.AfterFunc(time.Minute, func() {
        done <- true
    })
    ...

    Tato část ale slouží jen k tomu, že se nekonečný cyklus ukončí.

  • 16. 4. 2019 9:53

    Pavel Tišnovský

    Dobrý den,

    když jsem se nad tím zamyslel, tak máte určitě pravdu v tom, že existuje nějaká hranice (pro každého asi jiná) v tom, jaká funkcionalita má být ve standardních knihovnách a jaká se má nechat na knihovnách externích (a já mnohdy dávám na výběr z více možností).

    Go je poměrně mladý jazyk a jeho standardní knihovny obsahují hodně funkcionality z poměrně úzkého spektra (což je dobře, lepší než mít větší záběr, ovšem v menší kvalitě), které se velmi pravděpodobně nebude rozšiřovat dál mimo původní niku Go - https://golang.org/doc/faq#x_in_std. Současně Go zpočátku ve standardním toolingu moc neřešilo práci s externími knihovnami ve smyslu sémantického verzování apod., což si myslím zbrzdilo razantnější nástup jazyka do širší praxe.

    Na druhou stranu zrovna v oblasti plánování úloh možná není nutné stále dokola vymýšlet kolo a použít namísto toho existující knihovnu, podle konkrétních požadavků - někdy je vhodnější go-cron, protože se dají intervaly zapsat čísly načtenými například z nějakého texťáku, někdy je naopak lepší clockwork s jeho sémanticky čitelným zápisem, který navíc bude blízký lidem z Python a Ruby komunity. A zrovna vývojáři, kteří používají Python, na Go relativně často přechází popř. používají kombinaci Python+Go (což vůbec nemusí být špatné řešení).

    (PS: ten příklad není popravdě moc férový, protože pro jednu úlohu vypadá dlouhý - celé tři řádky, ale s každou další úlohou naroste o jediný řádek. Takže skutečně záleží na tom, co kdo implementuje. Pokud jedinou periodickou úlohu, taky bych asi použil stdlib, pokud něco složitějšího, kde se dá předpokládat, že zadavatel bude mít "divné" požadavky, šel bych do specializované knihovny, kde je přesně jasné, že zrovna teď dělám scheduling a tato jiná gorutina s tím vůbec nesouvisí).

  • 16. 4. 2019 13:01

    ivoszz

    Dobrý den,

    rozhodně nechci tvrdit, že je nutné vše psát jen se standardní knihovnou a jakákoliv závislost je zlo. To by opravdu zavánělo znovuvynalézáním kola. :) Ale taky nejsem přítelem toho, co vidíme ve světě javascriptu a co pak vede ke kauzám typu "leftpad". :(

    Pokud mi standardní knihovna něco umožňuje, měl bych to znát a kvalifikovaně se umět rozhodnout, kde je ta hranice, kdy ji použiji, a kdy už se mi vyplatí použít nějakou závislost. Žádná závislost není zadarmo a to platí pro jakýkoliv jazyk. Proverb "A little copying is better than a little dependency" je prověřeno léty zkušeností. Jinak se stávám pouhým lepičem kódu druhých. Osobně jsem se naučil v důležitých projektech vytvářet meziinterface pro všechny závislosti tak, abych je mohl kdykoliv nahradit jinou. Samozřejmě mohou existovat závislosti, které nahradit nelze. Pokud se v Javě rozhodnu, že použíji Spring, tak můžu říct, že bez něj nejede vlak.

    A to je jádro toho, co mi na posledních dílech jinak vynikajícího a záslužného seriálu trochu vadilo. Že se přeskočily elementární prvky, které by měl každý programátor v Go znát (ať už se jedná o knihovnu "time" nebo třeba "testing") a hned se skočilo na relativně malé a "nezajímavé" knihovny bez toho, že by se ukázalo jaký je jejich přínos. Navíc jejich použití sice demonstruje použití jejich API, ale čtenáři se toho příliš nedozví z oblati jak psát Go kód.

  • 16. 4. 2019 18:28

    Pavel Tišnovský

    Jj. souhlas, jsou dva extrémy - jazyk bez řešení externích knihoven na jedné straně (to Go není) a ekosystém JavaScriptu na straně druhé, kde to dovedli až do absurdna (to docela vím, protože ten ekosystém analyzujeme a ten graf - ne strom - závislostí je někdy šílenej).

    Ovšem jde to i jinak, například Rust to má pěkně vyřešené, a to docela do podrobností, včetně explicitních požadavků, jak řešit CVE atd. V Go se na to možná prozatím nenarazilo, protože oblasti, kde se nejvíc používá, jsou relativně dobře pokryty standardní knihovnou, jak správně píšete. Pro další oblasti, než je řekněme networking, Docker/Kuberne­tes/OpenShift a s ním související věci (crypto, ...) už budou potřeba externí knihovny a docela si dovedu dobře představit, že by to vedlo k větší popularitě tohoto jazyka.

    S tou základní knihovnou máte pravdu (až na "testing", ten měl vyhrazeno cca 30kB textu a ještě se k němu vrátím u web appek). Popravdě jsem to nechtěl moc probírat, protože tady padaly názory, že je to jen přepis "Tour of Go", ale dobře - zkusím dát dohromady seznam "must go" nebo spíš "must Go" pro každého kdo chce v Go skutečně programovat. Takže díky!

  • 16. 4. 2019 11:38

    atarist

    "Ale jednou z filozofií Go je mít co nejméně závislostí mimo standardní knihovnu"

    Výhody tohoto přístupu chápu, i když třeba v Javě se to IMHO dost nepovedlo, ale nenašel jsem nikde, kde tu filozofii takto explicitně někdo napsal. Hledal jsem na oficiálním blogu i na
    https://golang.org/doc/effective_go.html ale takto to tam napsáno nikde není. Z čeho prosím vycházíš (jak říkám nejsem asi proti, ale třeba v mé oblasti stdlib nemá moc co nabídnout)

  • 16. 4. 2019 15:48

    ivoszz

    Když se to takhle vytrhne, tak to zní skoro až hloupě. Asi jsem už v tu hodinu nebyl zcela čerstvý... :)

    Obecně se Go komunita staví poměrně silně proti zbytečným závislostem. Podle mého názoru někdy až přehnaně, což občas špatně chápou příchozí z jiných "jazykových světů". Stačí si přečíst pár threadu z /r/golang, ale je to i v přednáškách Roba Pika. Podle mne je důležité to slovo "zbytečným" a jeho výklad.

    Když to zúžím na testování, on sám je třeba hlasitým zastáncem nepoužívání žádných testovacích frameworků nad rámec "testing". Já osobně s ním souhlasím jen do určité míry, pro unit testy ale také nepoužívám žádný framework. Ale rozumím tomu, že v korporaci pro BDD testování použijí třeba Ginkgo a Gomegu. Na druhou stranu před takovým rozhodnutím bych pečlivě prověřil dané knihovny, jejich stabilitu a kdo za nimi stojí. A pokud to dává smysl, vytvořím si vlastní interface a mezivrstvu, abych tu knihovnu mohl případně nahradit.

    Co se týče nějakého odkazu, nejlépe to vystihuje ten v jiném příspěvku zmiňovaný proverb. Ten pochází z přednášky Roba Pika (cca 9:25). Ta přednáška je vůbec celá zajímavá a dává nahlédnout na filozofii při návrhu jazyka. Osvětluje některá rozhodnutí, která nemálo odpůrců tohoto jazyka (dá-li se to takto říct) na jazyku bytostně nesnáší. :) A když se tak nad tím zamýšlím, možná jeden z důvodů, proč mi jazyk Go tak vyhovuje je ten, že jsem hrával a stále ještě na docela slušné úrovní hraju hru Go. Ty výchozí principy jsou překvapivě dost podobné.

  • 17. 4. 2019 7:44

    atarist

    Na tu přednášku jsem se díval, moc pěkně připravená a vtipná - díky za odkaz! Mě se Go líbí, sice také pár věcí nemusím, ale to platí pro všechny jazyky, takže to je ok :-)