Úvod do ArchUnit

1. Prehľad

V tomto článku si ukážeme, ako skontrolovať architektúru systému pomocou ArchUnit.

2. Čo je ArchUnit?

Väzba medzi vlastnosťami architektúry a udržiavateľnosťou je v softvérovom priemysle dobre študovanou témou. Definovanie zvukovej architektúry pre naše systémy však nestačí. Musíme si overiť, či implementovaný kód dodržiava toto.

Jednoducho povedané, ArchUnit je testovacia knižnica, ktorá nám umožňuje overiť, či aplikácia dodržiava daný súbor architektonických pravidiel. Čo je to však architektonické pravidlo? A čo viac, čo tým myslíme architektúry v tomto kontexte?

Začnime tým druhým. Tu používame výraz architektúry odvolávať sa naspôsob, akým organizujeme rôzne triedy v našej aplikácii do balíkov.

Architektúra systému tiež definuje, ako balíky alebo skupiny balíkov - známe tiež ako vrstiev - komunikovať. Praktickejšie to definuje, či kód v danom balíku môže volať metódu v triede patriacej inej. Predpokladajme napríklad, že architektúra našej aplikácie obsahuje tri vrstvy: prezentácia, službya vytrvalosť.

Jedným zo spôsobov, ako vizualizovať, ako tieto vrstvy interagujú, je použitie diagramu balíkov UML s balíkom predstavujúcim každú vrstvu:

Už pri pohľade na tento diagram môžeme zistiť niektoré pravidlá:

  • Prezentačné triedy by mali závisieť iba od servisných tried
  • Triedy služieb by mali závisieť iba od tried vytrvalosti
  • Triedy vytrvalosti by nemali závisieť od nikoho iného

Pri pohľade na tieto pravidlá sa teraz môžeme vrátiť späť a odpovedať na našu pôvodnú otázku. V tejto súvislosti je architektonické pravidlo tvrdením o spôsobe vzájomnej interakcie našich tried aplikácií.

Ako teda teraz môžeme skontrolovať, či naša implementácia dodržiava tieto pravidlá? Tu je miesto ArchUnit vchádza dovnútra. Umožňuje nám to vyjadriť naše architektonické obmedzenia pomocou a plynulé API a overiť ich popri iných testoch počas bežného zostavovania.

3. ArchUnit Nastavenie projektu

ArchUnit sa pekne integruje do JUnit testovací rámec, a tak sa zvyčajne používajú spoločne. Všetko, čo musíme urobiť, je pridať archunit-junit4 závislosť zodpovedať našej JUnit verzia:

 com.tngtech.archunit archunit-junit4 0.14.1 test 

Ako jeho artifactId znamená, že táto závislosť je špecifická pre JUnit 4 rámec.

K dispozícii je tiež archunit-junit5 závislosť, ak používame JUnit 5:

 com.tngtech.archunit archunit-junit5 0.14.1 test 

4. Písanie ArchUnit Skúšky

Po pridaní príslušnej závislosti do nášho projektu začnime písať naše testy architektúry. Našou testovacou aplikáciou bude jednoduchá aplikácia SpringBoot REST, ktorá zadáva dotazy na Šmolkovia. Pre zjednodušenie táto testovacia aplikácia obsahuje iba Kontrolór, Služba, a Úložisko triedy.

Chceme overiť, či je táto aplikácia v súlade s pravidlami, ktoré sme spomenuli predtým. Začnime teda jednoduchým testom pre pravidlo „prezentačné triedy by mali závisieť iba od servisných tried“.

4.1. Náš prvý test

Prvým krokom je vytvorenie sady tried Java, ktoré budú kontrolované na porušenie pravidiel. Robíme to tak, že vytvoríme inštanciu ClassFileImporter triedy a potom použije jednu z nich importXXX () metódy:

JavaClasses jc = new ClassFileImporter () .importPackages ("com.baeldung.archunit.smurfs");

V takom prípade JavaClasses inštancia obsahuje všetky triedy z nášho hlavného aplikačného balíka a jeho čiastkových balíkov. Tento objekt si môžeme myslieť ako analogický s typickým testovaným subjektom používaným v bežných testoch jednotiek, pretože bude cieľom pre hodnotenie pravidiel.

Architektonické pravidlá používajú jednu zo statických metód z ArchRuleDefinition triedy ako východiskový bod pre svoju plynulé API hovory. Pokúsme sa implementovať prvé pravidlo definované vyššie pomocou tohto API. Použijeme triedy () metóda ako naša kotva a odtiaľ pridajte ďalšie obmedzenia:

ArchRule r1 = classes () .that (). ResideInAPackage (".. prezentácia .."). By mal (). OnlyDependOnClassesThat () .resideInAPackage (".. služba .."); r1.check (jc);

Všimnite si, že musíme zavolať na šek () metódu pravidla, ktoré sme vytvorili na vykonanie kontroly. Táto metóda vyžaduje a JavaClasses objekt a hodí výnimku, ak dôjde k porušeniu.

Všetko to vyzerá dobre, ale ak sa pokúsime spustiť tento kód proti nášmu kódu, dostaneme zoznam chýb:

java.lang.AssertionError: Architecture Violation [Priorita: STREDNÉ] - Pravidlo 'triedy, ktoré sa nachádzajú v balíku' ..prezentácia .. 'by malo závisieť iba od tried, ktoré sa nachádzajú v balíku' ..service .. '' bol porušený ( 6-krát): ... zoznam chýb je vynechaný 

Prečo? Hlavným problémom tohto pravidla je onlyDependsOnClassesThat (). Napriek tomu, čo sme vložili do diagramu balíka, naša skutočná implementácia má závislosti na JVM a jarných rámcových triedach, teda chyba.

4.2. Prepisovanie nášho prvého testu

Jedným zo spôsobov, ako vyriešiť túto chybu, je pridať klauzulu, ktorá zohľadňuje tieto ďalšie závislosti:

ArchRule r1 = classes () .that (). ResideInAPackage (".. presentation ..") .should (). OnlyDependOnClassesThat () .resideInAPackage (".. service ..", "java ..", "javax .. "," org.springframework .. "); 

Touto zmenou prestane naša kontrola zlyhávať. Tento prístup však trpí problémami s udržiavateľnosťou a je trochu hackovaný. Týmto problémom, ktorým môžeme prepísať naše pravidlo, sa môžeme vyhnúť pomocou noClasses () statická metóda ako náš východiskový bod:

ArchRule r1 = noClasses () .that (). ResideInAPackage (".. prezentácia .."). By mal (). DependOnClassesThat () .resideInAPackage (".. vytrvalosť .."); 

Samozrejme, môžeme tiež poukázať na to, že tento prístup je popierať namiesto povolený taký, aký sme mali predtým. Kritickým bodom je, že nech si zvolíme akýkoľvek prístup, ArchUnit zvyčajne bude dostatočne flexibilný na to, aby vyjadril naše pravidlá.

5. Pomocou KnižnicaAPI

ArchUnit umožňuje vďaka vytvoreniu komplexných architektonických pravidiel ľahkú úlohu. Tie zase možno tiež kombinovať, čo nám umožňuje vytvárať pravidlá pomocou vyššej úrovne abstrakcie. Von z krabice, ArchUnit ponúka Knižnica API, zbierka vopred zabalených pravidiel, ktoré sa zaoberajú obavami o spoločnú architektúru:

  • Architektúry: Podpora vrstiev a cibule (tiež známe ako šesťhranné alebo „porty a adaptéry“) kontroly pravidiel architektúry
  • Plátky: Používa sa na zisťovanie kruhových závislostí alebo „cyklov“
  • Všeobecné: Zbierka pravidiel týkajúcich sa najlepších postupov pri kódovaní, ako sú protokolovanie, použitie výnimiek atď.
  • PlantUML: Skontroluje, či náš kódový základ dodržiava daný model UML
  • Pravidlá zmrazenia oblúka: Uložte porušenia pre ďalšie použitie, aby ste mohli nahlásiť iba nové porušenia. Obzvlášť užitočné pri správe technických dlhov

Pokrytie všetkých týchto pravidiel je mimo rozsahu tohto úvodu, ale poďme sa pozrieť na Architektúra balíček pravidiel. Predovšetkým prepíšeme pravidlá v predchádzajúcej časti pomocou pravidiel vrstvenej architektúry. Používanie týchto pravidiel si vyžaduje dva kroky: najskôr definujeme vrstvy našej aplikácie. Potom definujeme, ktoré prístupy k vrstve sú povolené:

LayeredArchitecture arch = layeredArchitecture () // Definujte vrstvy .layer ("Prezentácia"). DefinedBy (".. prezentácia ..") .layer ("Služba"). DefinedBy (".. služba ..") .layer (" Perzistencia "). DefinedBy (" .. perzistencia .. ") // Pridať obmedzenia .whereLayer (" Prezentácia "). MayNotBeAccessedByAnyLayer () .whereLayer (" Služba "). MayOnlyBeAccessedByLayers (" Prezentácia ") .whereLayer (" Perzistencia ") .mayOnlyBeAccessedByLayers („služba“); arch.check (jc);

Tu, layeredArchitecture () je statická metóda z Architektúry trieda. Po vyvolaní vráti nový LayeredArchitecture objekt, pomocou ktorého potom definujeme názvy vrstiev a tvrdenia týkajúce sa ich závislostí. Tento objekt implementuje ArchRule aby sme ho mohli používať ako každé iné pravidlo.

Na tomto konkrétnom rozhraní API je skvelé to, že nám umožňuje vytvárať iba niekoľko riadkov kódových pravidiel, ktoré by inak vyžadovali kombináciu viacerých jednotlivých pravidiel.

6. Záver

V tomto článku sme preskúmali základy používania ArchUnit v našich projektoch. Prijatie tohto nástroja je pomerne jednoduchá úloha, ktorá môže mať pozitívny vplyv na celkovú kvalitu a z dlhodobého hľadiska znížiť náklady na údržbu.

Ako obvykle je všetok kód k dispozícii na GitHub.


$config[zx-auto] not found$config[zx-overlay] not found