Uvod u ArchUnit

1. Pregled

U ovom ćemo članku pokazati kako provjeriti arhitekturu sustava pomoću ArchUnit.

2. Što je ArchUnit?

Veza između osobina arhitekture i održivosti dobro je proučavana tema u softverskoj industriji. Međutim, definiranje zvučne arhitekture za naše sustave nije dovoljno. Moramo provjeriti pridržava li se implementirani kôd.

Jednostavno rečeno, ArchUnit je testna knjižnica koja nam omogućuje da potvrdimo da li se aplikacija pridržava određenog niza arhitektonskih pravila. Ali, što je arhitektonsko pravilo? Čak i više, što podrazumijevamo arhitektura u ovom kontekstu?

Krenimo od potonjeg. Ovdje koristimo izraz arhitektura pozivati ​​se nanačin na koji organiziramo različite razrede u našoj aplikaciji u pakete.

Arhitektura sustava također definira kako paketi ili skupine paketa - također poznati kao slojevi - komunicirati. Praktičnije rečeno, definira može li kod u danom paketu pozvati metodu u klasi koja pripada drugoj. Na primjer, pretpostavimo da arhitektura naše aplikacije sadrži tri sloja: prezentacija, servis, i upornost.

Jedan od načina da vizualizirate kako ti slojevi međusobno djeluju je upotreba UML dijagrama paketa s paketom koji predstavlja svaki sloj:

Samo gledanjem ovog dijagrama možemo dokučiti neka pravila:

  • Prezentacijski tečajevi trebali bi ovisiti samo o uslužnim klasama
  • Servisni tečajevi trebaju ovisiti samo o tečajevima trajnosti
  • Nastava ustrajnosti ne bi trebala ovisiti ni o kome drugom

Gledajući ta pravila, sada se možemo vratiti i odgovoriti na svoje izvorno pitanje. U tom kontekstu, arhitektonsko pravilo je tvrdnja o načinu interakcije naših klasa aplikacija.

Dakle, kako provjeriti poštuje li naša provedba ta pravila? Evo gdje ArchUnit ulazi. Omogućuje nam da izrazimo svoja arhitektonska ograničenja pomoću a tečni API i potvrditi ih zajedno s ostalim testovima tijekom redovite gradnje.

3. ArchUnit Postavljanje projekta

ArchUnit lijepo se integrira s JUNIT testni okvir, i tako se obično koriste zajedno. Sve što moramo učiniti je dodati nadjedinica-junit4 ovisnost koja odgovara našoj JUNIT verzija:

 com.tngtech.archunit archunit-junit4 0.14.1 test 

Kao svoje artefaktId implicira, ova je ovisnost specifična za JUNIT 4 okvir.

Tu je i nadjedinica-junit5 ovisnost ako koristimo JUNIT 5:

 com.tngtech.archunit archunit-junit5 0.14.1 test 

4. Pisanje ArchUnit Ispitivanja

Kad dodamo odgovarajuću ovisnost našem projektu, krenimo s pisanjem testova arhitekture. Naša testna aplikacija bit će jednostavna SpringBoot REST aplikacija koja postavlja upit o Štrumpfovima. Radi jednostavnosti, ovaj testni program sadrži samo Kontroler, Servis, i Spremište razreda.

Želimo provjeriti je li ova aplikacija u skladu s pravilima koja smo prije spomenuli. Dakle, krenimo s jednostavnim testom za pravilo "predavanje klasa treba ovisiti samo o tečajevima usluga".

4.1. Naš prvi test

Prvi je korak stvoriti skup Java klasa koji će se provjeravati radi kršenja pravila. To radimo instanciranjem datoteke ClassFileImporter razreda, a zatim pomoću jednog od njegovih importXXX () metode:

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

U ovom slučaju, JavaClasses instanca sadrži sve klase iz našeg glavnog aplikacijskog paketa i njegovih podpaketa. Možemo smatrati da je ovaj objekt analogan tipičnom ispitnom subjektu koji se koristi u redovitim jediničnim testovima, jer će biti cilj za procjenu pravila.

Arhitektonska pravila koriste jednu od statičkih metoda iz ArchRuleDefinition razred kao polazište za njegov tečni API poziva. Pokušajmo implementirati prvo pravilo definirano gore pomoću ovog API-ja. Koristit ćemo satovi () metoda kao naše sidro i odatle dodajte dodatna ograničenja:

ArchRule r1 = classes () .that (). ResideInAPackage (".. prezentacija .."). Treba (). OnlyDependOnClassesThat () .resideInAPackage (".. service .."); r1.provjera (jc);

Primijetite da moramo nazvati ček() metoda pravila koje smo stvorili za pokretanje provjere. Ova metoda zahtijeva JavaClasses objekt i izbacit će iznimku ako postoji kršenje.

Sve ovo izgleda dobro, ali dobit ćemo popis pogrešaka ako ga pokušamo pokrenuti prema našem kodu:

java.lang.AssertionError: Kršenje arhitekture [Prioritet: SREDNJA] - Pravilo 'klase koje se nalaze u paketu' ..prezentacija .. 'treba ovisiti samo o klasama koje se nalaze u paketu' ..service .. '' kršeno ( 6 puta): ... izostavljen popis pogrešaka 

Zašto? Glavni problem ovog pravila je onlyDependsOnClassesThat (). Unatoč onome što smo stavili u dijagram paketa, naša stvarna implementacija ovisi o JVM i Spring okvirnim klasama, otuda i pogreška.

4.2. Prepisivanje našeg prvog testa

Jedan od načina rješavanja ove pogreške je dodavanje klauzule koja uzima u obzir te dodatne ovisnosti:

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

Ovom promjenom naš će ček prestati propadati. Međutim, ovaj pristup pati od problema s održavanjem i osjeća se pomalo sretno. Možemo izbjeći te probleme pri prepisivanju našeg pravila pomoću noClasses () statička metoda kao naše polazište:

ArchRule r1 = noClasses () .that (). ResideInAPackage (".. prezentacija .."). Treba (). DependOnClassesThat () .resideInAPackage (".. postojanost .."); 

Naravno, također možemo istaknuti da je takav pristup na osnovi poricanja umjesto na temelju dopuštanja jedan koji smo imali prije. Kritična je točka da kakav god pristup odaberemo, ArchUnit obično bude dovoljno fleksibilan da izrazi naša pravila.

5. Korištenje KnjižnicaAPI

ArchUnit čini stvaranje složenih arhitektonskih pravila laganim zadatkom zahvaljujući svojim ugrađenim pravilima. Oni se, pak, također mogu kombinirati, što nam omogućuje stvaranje pravila koristeći višu razinu apstrakcije. Izvan kutije, ArchUnit nudi API knjižnice, zbirka unaprijed upakiranih pravila koja rješavaju zajedničke probleme arhitekture:

  • Arhitekture: Podrška za provjere pravila za slojevite i luk (tzv. Šesterokutne ili "priključke i adaptere")
  • Kriške: Koristi se za otkrivanje kružnih ovisnosti ili "ciklusa"
  • Općenito: Zbirka pravila koja se odnose na najbolje prakse kodiranja, poput bilježenja, korištenja izuzetaka itd.
  • PlantUML: Provjerava pridržava li se naša baza koda određenog UML modela
  • Pravila zamrzavanja luka: Spremite kršenja za kasniju upotrebu, omogućujući prijavljivanje samo novih. Posebno korisno za upravljanje tehničkim dugovima

Pokrivanje svih tih pravila izvan je opsega ovog uvoda, ali pogledajmo Arhitektura paket pravila. Konkretno, prepišimo pravila u prethodnom odjeljku koristeći pravila slojevite arhitekture. Korištenje ovih pravila zahtijeva dva koraka: prvo definiramo slojeve naše aplikacije. Zatim definiramo koji pristup sloju je dopušten:

LayeredArchitecture arch = layeredArchitecture () // Definirajte slojeve .sloj ("Prezentacija"). DefinedBy (".. prezentacija .."). Sloj ("Usluga"). Perzistentnost "). DefinedBy (" .. postojanost .. ") // Dodajte ograničenja .whereLayer (" Prezentacija "). MayNotBeAccessedByAnyLayer () .whereLayer (" Usluga "). MayOnlyBeAccessedByLayers (" Prezentacija ") .whereLayer (" Upornost ") .mayOnlyBeAccessedByLayers ("Usluga"); arh.provjera (jc);

Ovdje, slojevita arhitektura () je statička metoda iz Arhitekture razred. Kad se pozove, vraća novi Slojevita arhitektura objekt, koji zatim koristimo za definiranje slojeva imena i tvrdnji u vezi s njihovim ovisnostima. Ovaj objekt provodi ArchRule sučelje tako da ga možemo koristiti baš kao i svako drugo pravilo.

Cool stvar kod ovog određenog API-a je što nam omogućuje stvaranje u samo nekoliko redaka pravila koda koja bi inače zahtijevala da kombiniramo više pojedinačnih pravila.

6. Zaključak

U ovom smo članku istražili osnove korištenja ArchUnit u našim projektima. Usvajanje ovog alata relativno je jednostavan zadatak koji može imati pozitivan utjecaj na ukupnu kvalitetu i dugoročno smanjiti troškove održavanja.

Kao i obično, sav je kôd dostupan na GitHub-u.


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