Spletité závislosti a Apache Ivy

Java má veľa spoločného so svetom open source (možno by sa dala považovať za jeho súčasť). A ako taká má jednu vlastnosť charakteristickú pre open source – modularitu knižníc. Pod týmto pojmom myslím to, že svet knižníc tretích strán, ktoré v Jave viete použiť, je tvorený obrovským množstvom malých knižníc. Aby ste mohli spustiť svoju aplikáciu, potrebujete (fyzicky dostať na svoj počítač) aj niekoľko desiatok takýchto knižníc, a čo je horšie, tieto knižnice majú tiež svoje závislosti, ktoré musíte nájsť. Aj keď je táto modularita ohromný nástroj, je to zároveň neuveriteľne komplexný problém. A ako taký je ručne ťažko riešiteľný, a preto vznikli nástroje, ktoré ho pomáhajú riešiť. Jedným z nich je aj Apache Ivy.

Ako som povedal, príprava všetkých knižníc tretích strán vie byť v Jave značne komplikovaný problém. A preto aj nástroj, ktorý ho rieši, je značne komplikovaný. A preto ani tento článok nebude úplne jednoduché čítanie. Ak ale hľadáte podobný nástroj, alebo už ste o Apache Ivy počuli a chcete sa dozvedieť viac, mohol by vám byť v niečom užitočný. Apache Ivy je podprojekt projektu Apache Ant, ktorého hlavnou úlohou je automatizácia procesov. Ivy (z angličtiny „brečtan“) sa špecializuje na úlohu získavania súborov na základe ich závislostí medzi sebou. Dôležité je si uvedomiť samotnú podstatu problému, ktorú Ivy rieši, pretože potom vám jednotlivé jeho funkčnosti začnú dávať väčší zmysel. Tá podstata je, že máte systém, ktorý pozostáva zo súborov zoskupených do malých podmnožín (súbory, ktoré spolu veľmi úzko súvisia, napríklad zdrojové kódy, a tie isté zdrojové kódy preložené do binárnej podoby). Okrem toho sú v systéme definované závislosti medzi týmito podmnožinami (ak sú podmnožiny body, tak spolu so závislosťami vytvárajú štruktúru grafu). Takže máte súbory a závislosti medzi nimi. Takto vyzerá systém a teraz je podstatné, čo s ním chcete robiť. Chcete z neho vytiahnuť jeden súbor z nejakej podmnožiny a všetky súbory na ktorých práve tento jeden súbor závisí (napríklad ich potrebuje na to, aby ste ho mohli spustiť a on bude korektne fungovať). To je celé. To je základná myšlienka. Ivy sa oficiálne označuje ako tranzitívny manažér závislostí. To tranzitívny je tam preto, lebo nerobí len jeden prechod od aktuálneho súboru k ďalšiemu, ale je schopný vytiahnuť závislosti do ľubovoľnej hĺbky.

Obrázok

Na čo je to dobré? No, jedným z príkladov sú balíky v Jave. V jednom z predchádzajúcich článkov som písal, že Java očakáva, že všetky potrebné triedy (často zabalené v knižniciach – jar súboroch) nájde vo svojej Java Class Path. Váš program môže závisieť na nejakých balíkoch, ktoré môžu závisieť na ďalších a tak ďalej. Výsledok môže byť, že hľadať ručne a pripravovať ich môže byť komplikovaná a pracná robota. Ivy sa snaží riešiť obe tieto problémy. Ten prvý pomocou systému popisných súborov, pomocou ktorých sa orientuje, ktoré závislosti daný balík potrebuje a ten druhý pomocou Ivy knižnice, ktorá dokáže vykonávať príkazy Ivy, a ktorá vykoná tranzitívne stiahnutie potrebných závislostí.

Ivy potrebuje tieto balíky odniekiaľ stiahnuť. A tu sa dostávame k pojmu repozitár. To je miesto, kde Ivy dokáže vyhľadávať balíky a získavať ich. Nenachádzajú sa tam len samotné súbory, ale aj popisy ich závislostí, takže Ivy vie z takého zoznamu získať súbor aj so všetkými jeho závislosťami (ak sú všetky v repozitári prítomné). Aby to Ivy nemuselo robiť pre každý prípad, existuje niečo, čo sa nazýva cache. Je to lokálna kópia repozitára, kde sa Ivy pozerá v prvom rade a ak tam nenájde to, čo je potreba, tak pristúpi k repozitáru. Aby sme si to pekne utriedili, poďme si zrekapitulovať pojmy Ivy sveta:

  • Modul – skupina súborov (predtým som to označoval ako podmnožinu), ktoré spolu úzko súvisia. Modul je základná väzobná jednotka pre Ivy, čo znamená, že väzby sú vytvárané medzi modulmi a nie súbormi. Modul je tiež definovaný Ivy popisným súborom, ktorý hovorí, čo je to za modul (názov, verzia, stav vývoja atď), aké súbory poskytuje a čo sú jeho závislosti. Repozitár je potom ako sieť modulov, ktoré sa medzi sebou odkazujú – graf.
  • Artefakt – jeden súbor, ktorý je súčasťou niektorého modulu. Modul môže mať ľubovoľný počet súborov, ale ako som písal, mali by to byť súbory, ktoré medzi sebou úzko súvisia. Artefakt predstavuje najmenšiu jednotku (ďalej nedeliteľnú) v Ivy systéme. A tiež, ako som už písal, je hlavnou úlohou Ivy vyhodnocovať, ktoré súbory – artefakty sú potrebné a poskytnúť ich.
  • Dependency – väzba medzi modulmi. V rámci väzby definujeme hlavne názov modulu, ale môžem uviesť verziu, stav vývoja alebo branche.
  • Repository – miesto s pripravenými modulmi a ich súbormi. Fyzická realizácia môže byť napríklad FTP server, alebo zdieľaný priečinok na počítači v lokálnej sieti. Podstatné je zvoliť si štruktúru (tá sa dá prispôsobovať) a nahrať tam všetky moduly (popisné súbory) aj s ich artefaktmi.
  • Cache – lokálna kópia repozitára. Ide hlavne o optimalizáciu, kedy je repozitár dostupný len cez internet.

Vyššie som písal, že závislosti sú robené na úrovni modulov, ale že výsledkom je skupina súborov, ktoré sa odvodzujú podľa závislosti. Niekde medzi tým musí byť spojitosť. A tá spojitosť sa nazýva Konfigurácia. Konfigurácie sú asi jednou z najzložitejších tém, čo sa týka Ivy, a preto sa pri nich chvíľu zdržím. Každý modul má v sebe zadefinované súbory (artefakty), ktoré obsahuje. Rovnako má zadefinovanú množinu konfigurácií, kde najpodstatnejší parameter konfigurácie je jej názov. Dôležité je, že v zozname artefaktov má tiež povedané, do ktorých konfigurácií daný artefakt patrí. Táto informácia sa dá potom využiť tak, že ja požiadam modul, aby mi odovzdal jeho artefakty, ale tiež mu definujem konfiguráciu, a tak je dosť možné, že dostanem len tie, ktoré sú pre danú konfiguráciu určené. Tiež sa to dá vyjadriť jednoduchou rovnicou:

modul + konfigurácia = artefakty

Konfigurácia je teda spojivo medzi modulom a súbormi, ktoré obsahuje. Alebo inak povedané hovorí o tom, že pre danú konfiguráciu modulu predstavuje v systéme tieto a tieto súbory. Je tu ale druhý dôležitý fakt a to, že konfigurácia je tiež súčasťou závislosti. Modul totiž nedefinuje len väzbu na iný modul, ale súčasťou tejto väzby je tiež informácia, že konfigurácia modulu A závisí na konfigurácii modulu B. Často sa tak vytvára reťaz, kde moduly medzi sebou závisia na rovnakej konfigurácii, a teda ak začnete vyberať závislosti pre danú konfiguráciu, získate všetky artefakty od všetkých závislých modulov v danej konfigurácii. Ešte inak povedané, viete aktivovať celú sieť závislých modulov stále s inou konfiguráciou a získate tak stále inú skupinu súborov. Chce to nepochybne dosť rozvinuté abstraktné myslenie, aby ste to boli schopní predstaviť si na prvýkrát (mne osobne to robilo pomerne veľké problémy), takže si dajme jeden príklad z praxe. Máte repozitár, v ktorom sú uložené zdrojové kódy a binárne súbory vytvorené z prekladu zdrojových kódov. Zdrojové kódy sú vždy zoskupené spolu s binárkami v Ivy moduloch. A vy chcete raz vytiahnuť všetky zdrojové kódy podľa nejakých závislostí a raz všetky binárky. Takže do každého modulu zadefinujete 2 konfigurácie, napríklad binary a source a navzájom moduly previažete tak, že ak niekto berie z daného modulu artefakty konfigurácie binary automaticky sa získavajú artefakty závislých modulov z ich binary konfigurácie. Výsledok je, že z jedného repozitára potom viete vytiahnuť skupiny súborov rozdielneho typu podľa toho, akú konfiguráciu použijete.

Posledná téma, ktorú ohľadom Ivy nie je možné vynechať, sú dva základné príkazy, ktoré Ivy používa a to je Resolve a Retrieve. Resolve znamená dohľadanie všetkých závislosti pre daný modul a danú konfiguráciu. Znamená to, že Ivy skontroluje všetky repozitáre (môže ich byť viac ako jeden), zistí, či má dostupné všetky potrebné moduly a ich konfigurácie a prípadne všetko potrebné pripraví do cache. Ten druhý krok je, že potrebujete tieto súbory vytiahnuť do jedného priečinku a na to slúži práve Retrieve. Ten využije informácie z cache z Resolve príkazu a všetko potrebné pripraví.

Ivy nie je jednoduchý nástroj, pretože nerieši jednoduchý problém. Moje články mali za úlohu vytvoriť predstavu, čo je to za nástroj, aké sú základné pojmy v Ivy svete. Ak ste očakávali Ivy návod s ukážkami kódu, tak vás sklamem. Z môjho pohľadu je dôležitejšie najprv pochopiť systém ako celok a až potom sa začať zaoberať konkrétnymi detailami. V prípade, že ste pojali základné pojmy, pochopili účel a aj jednotlivé časti systému Ivy a vysporiadali sa s tým, prečo a ako sú postavené konfigurácie, ste na najlepšej ceste začať tento nástroj používať.