Monorepo

Z Wikipedie, otevřené encyklopedie

Monorepositář či monorepo (anglicky monorepo) je speciální případ repozitáře, kdy je více logicky nezávislých projektů vyvíjeno a jejich kód uchováván v rámci jednoho repositáře. Protože tento způsob umožňuje snadné sdílení kódu mezi jednotlivými podprojekty, často se jedná o společný vývoj backendu a frontendu jedné aplikace, případně o vývoj několika frontendových klientů jedné aplikace. Na rozdíl od aplikace, kde jsou jednotlivé moduly rozděleny mezi více repositářů a kde může být například testování více modulů napříč repositáři komplikované, je testování aplikace v rámci jednoho repositáře jednodušší.

Nicméně sdílení kódu není nutná podmínka k použití monorepa, vyvíjené podprojekty nemusí spolu kód sdílet vůbec.

Pojem monorepo se často spojuje se jmény největších technologických firem na světě, jako jsou Google, Facebook, Microsoft, Airbnb. V těchto případech se monorepo vyznačuje velkým objemem kódu a vysokým počtem změn. Například monorepo Googlu obsahovalo v roce 2015 86TB dat[1]. Konceptuálně se nejedná o nový způsob držení kódu v repositářích, ale byl teprve nedávno pojmenován právě pojmem monorepo.

Pojem monorepo se liší od pojmu monolitická aplikace, která označuje vnitřní architekturu aplikace. Aplikace vyvíjené v rámci monorepa nejsou architektonicky omezeny na monolické aplikace, může se jednat i o jakoukoli jinou architekturu.

Charakteristika[editovat | editovat zdroj]

Monorepo se vyznačuje následujícími vlastnosti a atributy[2]:

  • Repositář obsahuje více logických projektů, například iOS aplikaci a webového klienta
  • Počet jednotlivých projektů není omezen, ale se zvyšujícím počtem se objevují problémy se škálováním
  • Projekty strukturované uvnitř monorepa jsou většinou pouze úzce propojeny
  • Často se jedná o velmi rozsáhlý repositář – ať už počtem souborů, počtem commitů nebo celkovou diskovou velikostí repositáře

Výhody[editovat | editovat zdroj]

Monorepa se mohou vyznačovat těmito výhodami:

  • Snadné sdílení kódu – sdílení je umožněno bez použití dependency management nástrojů. Toto je velmi výhodné, pokud v repositáři existuje několik backendových služeb a několik frontendových klientů, tyto projekty mohou například sdílet logickou vrstvu aplikace
  • Atomické změny – pokud jsou projekty oddělené ve vlastních repositářích, dochází při přidání určité funkcionality k vytvoření commitu a verze v každém z projektů a je nutné uchovávat jejich kompatibilitu. Naopak v monorepu může tato změna být reprezentována jedním commitem obsahujícím změny pro všechny projekty.
  • Refaktorování kódu – díky tomu, že má vývojář přístup ke všem projektům a částem kódu, tak je snadnější zajistit, aby byly po refaktoringu všechny části aplikace funkční.
  • Spolupráce členů týmu – všichni členové týmu vidí všechny projekty organizace a mohou navrhovat změny k jednotlivým projektů. Toto vede ke spoluvlastnění kódu, k snížení duplicit a ke znovu používání již vyvinutého kódu.
  • Zmenšení velikosti projektu – pokud jsou dva moduly aplikace závislé na stejném externím modulu, tak ho můžeme v rámci monorepa uchovávat jenom jednou a z každého závislého modulu se pouze odkázat na tuto společný modul

Nevýhody[editovat | editovat zdroj]

Monorepa mohou přinést potencionální problémy, jejich výskyt není nutností a závisí na konkrétní implementaci monorepositáře:

  • Ztráta informace o verzi projektu – některé implementace monorepa verzují celý repozitář jako celek, dojde tedy ke ztrátě verze u jednotlivých projektů. Například změna v jedné části aplikace zapříčiní navýšení verze všech podprojektů. Toto chování však může být v některých případech žádoucí.
  • Spoluvlastnění kódu – často se přichází o kontrolu přístupu členů organizace k jednotlivým projektům a souborům a všichni členové organizace mohou číst všechny soubory. Toto sdílení kódu zároveň přináší potencionální problémy, například že někteří programátoři mohou upravit kód, kterému nerozumějí, a tím do něj zanést chyby. Tomuto lze zamezit pomocí code reviews či podobných procesů.
  • Náročnost konfigurace – ačkoli existuje množství nástrojů, které správu a verzování monorepa usnadňují, téměř vždy je nutné počítat s vyšší časovou náročností pro prvotní konfiguraci a se zvýšeným množstvím konfiguračních souborů
  • Vyčlenění projektu z monorepa – potenciální budoucí vyčlenění konkrétního modulu z monorepa do vlastního repositáře, může být komplikované a obtížné

Extrémně velká monorepa[editovat | editovat zdroj]

Příklad: Google monorepo[editovat | editovat zdroj]

Jedním z nejznámějších příkladů monorepa je repositář firmy Google, který obsahoval v roce 2015 2 miliardy řádků kódu[1], přes 85 terabytů dat a dá se tedy považovat za jeden z největších repositářů na světě. Klíčové části kódu, například algoritmus Google Page Rank, byl z důvodu správy přístupu uchováván ve vlastním repositáři. Také zdrojový kód prohlížeče Google Chrome a operačního systému Android je uchováván ve vlastních repositářích. Za den v tomto repositáři vzniká přes 45 000 commitů. Pro správu a verzování tohoto repositáře používá Google vlastní nástroj nazvaný Piper.

S takto velkými repositáři přichází nutnost myslet na škálovatelnost verzovacích a sestavovacích nástrojů.

Škálování verzovacího nástroje[editovat | editovat zdroj]

Stávající verzovací nástroje nedostačovaly požadavkům technologických firem na takto velké repositáře. Firmy jako Facebook a Microsoft se vydaly cestou stávajících nástrojů, případně si vytvořily vlastní verze těchto nástrojů. Facebook zvolil Merkurial, Microsoft se na druhou straně rozhodl využít Git. Obě firmy jsou zároveň aktivními přispěvateli do těchto nástrojů a zasloužily se o vylepšení některých funkcí, například Facebook násobně zvýšil výkon operací v Merkurialu[3].

Škálování build (sestavovacího) nástroje[editovat | editovat zdroj]

S držením několika projektů přichází otázka, jak při sestavování aplikace sestavit pouze části, ve kterých došlo ke změnám, případně sestavit pouze ty části, které na těchto změněných částech závisejí. K tomu se využívá závislostní graf, ze kterého víme, který projekt na jakém závisí. Je nutné myslet na to, že všechny standardní sestavovací nástroje nemusí v monorepou fungovat správně. Výběr konkrétního nástroje na sestavování projektů z monorepa závisí na potřebách daného projektu, zejména na použitých programovacích jazycích.

  • Buck – nástroj vyvinutý firmou Facebook pro sestavování malých modulů uvnitř monorepa[2] s podporou jazyků C++, Java (Kotlin, Groovy), Python, Rust, Go a další. Buck vyžaduje explicitní deklarování závislostí jednotlivých modulů, tím vzniká stromová struktura a Buck při změně sestaví jen danou větev stromu. Buck předpokládá, že jednotlivé moduly jsou deterministicky závislé na svých závislostech a může tedy tyto jednotlivé výsledky cachovat a případně i sdílet mezi jednotlivými vývojáři. Airbnb díky nástroji Buck zrychlilo sestavování svým aplikací o 50%[4].
  • Bazel – nástroj pro testování a sestavování aplikace který podporuje platformy Java, C++, Android, iOS a Go. Byl vyvinutý firmou Google a následně v roce 2015 zveřejněn pod open-source licencí. Zaměřuje se na rychlost, správnost a reprodukovatelnost sestavovaných aplikací[3].
  • Pants – nástroj pro testování a sestavování aplikací v monorepu. Současné verze v2 zatím podporuje pouze jazyk Python, minulá verze v1 podporovala i jiné jazyky jako Node.js, Go, Java a Scala. Tento nástroj byl vyvinutý a používaný firmou Twitter v době, kdy jiné nástroje jako Buck a Bazel nebyly veřejné. Následně byl v roce 2012 zveřejněn pod licencí Apache 2.0 Licence[5]
  • Lerna – nástroj pro správu více JavaScript projektů uvnitř jednoho repositáře
  • NX – nástroj pro návrh, sestavování, testování JavaScript aplikací (React, Angular, Node.js). Jeho hlavním cílem je umožnit škálování, čehož dociluje identifikací změněných míst. Umožňuje také využít distribuovanou cache pro rychlejší testování a sestavování aplikací.

Mezi další nástroje, které se v monorepu využívají, patří například Rush, Bolt, Oao, Please.

Podpora ze strany dependecy management nástrojů[editovat | editovat zdroj]

Některé nástroje pro správu závislostí nabízí podporu monorepa:

  • Yarn workspaces – Yarn jako deklarativní správce závislostí pro JavaScript nabízí od verze 1.0 přímou podporu více projektů uvnitř jednoho monorepa. Zajišťuje například to, že jsou externí závislosti staženy pouze jednou a následně prolinkovány a znovupoužity mezi více balíčky. Také nabízí možnost se odkázat se na jiné podprojekty v monorepu a použít je jako závislosti[6]
  • NPM workspaces – od verze 7.x nabízí velmi podobnou funkcionalitu jako Yarn[7]

Reference[editovat | editovat zdroj]

  1. a b Google Is 2 Billion Lines of Code—And It's All in One Place. Wired. Dostupné online [cit. 2020-12-21]. ISSN 1059-1028. (anglicky) 
  2. a b Key concepts. Buck: a build tool [online]. [cit. 2020-12-21]. Dostupné online. 
  3. a b Bazel overview. docs.bazel.build [online]. [cit. 2020-12-21]. Dostupné online. (anglicky) 
  4. ZHANG, Brian. Building Mixed-Language iOS Project with Buck. Medium [online]. 2017-07-18 [cit. 2020-12-22]. Dostupné online. (anglicky) 
  5. The release of Pants 1.0. blog.twitter.com [online]. [cit. 2020-12-21]. Dostupné online. (anglicky) 
  6. Yarn. Yarn [online]. [cit. 2020-12-22]. Dostupné online. (anglicky) 
  7. workspaces | npm Docs. docs.npmjs.com [online]. [cit. 2020-12-22]. Dostupné online.