Skriver du fortsatt kode uten å tenke heksagonal arkitektur?

Når vi holder kurs i arkitektur, spør vi ofte deltakerne om de er kjent med heksagonal arkitektur. Som regel er det bare noen få som strekker armen i været. Men etter en kort presentasjon, er det alltid flere som innser at de har brukt heksagonal arkitektur uten å være klar over det.

Når vi holder kurs i arkitektur, spør vi ofte deltakerne om de er kjent med heksagonal arkitektur. Som regel er det bare noen få som strekker armen i været. Men etter en kort presentasjon, er det alltid flere som innser at de har brukt heksagonal arkitektur uten å være klar over det.

Som hands-on arkitekter er vi svært avhengige av heksagonal arkitektur. Vi legger imidlertid merke til at fortsatt ikke er kjent med de betydelige fordelene med den.

Hvorfor bør du vurdere å ta i bruk heksagonal arkitektur? I denne artikkelen får du flere gode grunner – men først trenger vi å klargjøre noen begreper som er viktige å ha som bakteppe: 

1.   Applikasjonskode: Dette refererer til forretningslogikk som fokuserer på kjernefunksjonaliteten til programvaren. Dette kan være regler for skatteberegning, en prosess for brukerregistrering og så videre.

2.   Infrastrukturkode: Dette gjelder spesifikke teknologier som støtter applikasjonskoden. I utgangspunktet passer enhver SQL-spørring, en HTTP-forespørsel, et SMTP-kall eller noe annet som er relatert til en spesifikk teknologi inn i denne kategorien.

3.   Separation of concerns: Et etablert prinsipp innen programmering som sier at forskjellige aspekter av et programvaresystem bør være adskilt og modularisert for å fremme vedlikeholdsevne, lesbarhet og gjenbrukbarhet.

   Det å separere applikasjonskoden og infrastrukturkoden er viktig av flere grunner. 

For det første forenkler det testingen. La oss vurdere en applikasjon for skatteberegning. Den må hente data fra databasen for å gi riktig skattesats. Når applikasjons- og infrastrukturkoden er adskilt, blir det mye enklere å opprette enkle automatiserte tester for skatteberegning. Hvis de derimot er koblet sammen, må databasen kjøre sammen med testene, noe som gjør dem betydelig tregere.

For det andre øker det fleksibiliteten. Tenk deg at team må erstatte et meldingssystem med et annet (Apache Artemis -> Apache ActiveMQ). Ved å holde meldingsspesifikk kode adskilt fra applikasjonskoden, kan overgangen ta mye mindre tid og kjernefunksjonaliteten forbli uendret. Hvis meldingssystemet hadde vært tett integrert med applikasjonskoden, ville dette ha vært en mye mer utfordrende oppgave.

For det tredje fremmer det gjenbrukbarhet. Tenk på hva som skjer når et utviklingsteam blir bedt om å støtte en ny type klient for applikasjonen. For eksempel at vi vil støtte SOAP i tillegg til HTTP over REST. Hvis applikasjonskoden var blandet med infrastrukturkoden (spesifikk for HTTP over REST), ville det vært vanskelig å tilpasse seg denne endringen. Men hvis vi holder dem adskilt, kan vi legge til ny kode som støtter SOAP – samtidig som vi gjenbruker all eksisterende applikasjonskode.

I tillegg tillater separation of concerns bedre vedlikeholdbarhet. Det blir enklere å identifisere og løse problemer uten at andre deler av systemet blir påvirket.

Konklusjonen er at det å holde applikasjons- og infrastrukturkoden adskilt er avgjørende for effektiv programvareutvikling. Heksagonal arkitektur er en tilnærming som fremmer denne separasjonen, sikrer vedlikeholdbarhet, fleksibilitet, testing og høy kohesjon. Så les videre :)

Hva er heksagonal arkitektur?

Heksagonal arkitektur, også kjent som Porter og Adaptere, er et arkitekturmønster som muliggjør separasjon av forretningslogikk fra infrastrukturrelaterte aspekter som HTTP, databaser, filsystemer og andre.

Du vil snart oppdage at heksagonal arkitektur ikke er en revolusjonerende ny idé, men snarere et veletablert prinsipp som er tett knyttet til andre mønstre som Clean Architecture, Dependency Inversion Prunciple (kode skal avhenge av abstraksjoner i stedet for implementeringer) og generelle prinsipper for objektorientert programmering (OOP).

Det følgende bildet (blant mange tilgjengelige på internett) illustrerer hovedideen:

Bilde1.png

Illustrasjonen viser en tydelig separasjon mellom Porter og Adaptere, der Applikasjonskoden bare er klar over Portene.

En Port er et teknologi-agnostisk grensesnitt i koden din. Driving Porten tillater inndata (for eksempel et HTTP-kall) å komme til Applikasjonskoden, mens Driven Porten gjør at Applikasjonskoden kan arbeide med utdataene (for eksempel lagre data i en database eller sende en melding til Kafka).

En Adapter er en teknologispesifikk implementering som tillater interaksjon med virkelige enheter som databaser, meldingskøer, nettlesere, SMTP-servere og så videre. Adaptere avhenger av Portene og har ingen direkte relasjon til Applikasjonskoden i systemet ditt. For øvrig er REST-kontrollere et eksempel på et HTTP-adapter, derfor bør de aldri inneholde forretningslogikk.

I neste avsnitt vil vi undersøke det samme bildet sammen med et kodeeksempel.

Eksempel

Det følgende bildet ligner på illustrasjonen over, men det viser spesifikke implementeringseksempler for Porter og Adaptere:

Bilde2.png

BookController er en HTTP Adapter.
CreateBookHandler er en Driving Port.
BookRepository er en Driven Port.
JPABookRepository er en Persistence Adapter (JPA betyr Java Persistence API).

Nå skal vi se på en mulig mappestruktur:

Bilde3.png

Bildet ovenfor fokuserer på modulstrukturen og avhengighetene mellom komponentene. Som du kan se, er klassene innenfor mappene Application og Domain uvitende om adaptere og er kun ansvarlige for forretningsbrukstilfeller.

En viktig merknad: adaptere av forskjellige typer bør ikke være avhengige av hverandre! Ellers, hvis du bestemmer deg for å erstatte for eksempel persistence-adapteren, må du også endre HTTP-adapteren.

Til slutt, la oss se på en mulig implementasjon.

BookController-adapteren aksepterer en HTTP-forespørsel og finner en driving port (CreateBookHandler) som kan håndtere forespørselen:

Blide4.png

CreateBookHandler håndterer forretningsbrukstilfellet ved å opprette en ny bok og lagre den ved hjelp av en driven port (BookRepository):

Bilde5.png
Bilde6.png

BookRepository er bare en interface:

Bilde7.png

Dens database-spesifikke implementasjon (JpaBookRepository) befinner seg under mappen «infrastructure/persistence», helt separat fra applikasjonskoden:

Bilde8.png

Eksempelet skalerer veldig bra i de fleste prosjekter og hjelper til med å oppnå kode av høy kvalitet som er testbar og utskiftbar.

Skal vi bruke heksagonal arkitektur overalt? 

Som med de fleste programvareutviklingsmønstre eller -metodologier, er det umulig å si at én kan brukes universelt, da det alltid er forbehold og unntak. Så når er heksagonal arkitektur et godt valg?

Som en tommelfingerregel er heksagonal arkitektur et godt valg for:
●   langvarige applikasjoner som må vedlikeholdes over en lengre periode. Vedlikeholdskostnadene pleier å øke over tid i ikke-heksagonale systemer.
●   prosjekter som krever fleksibilitet for å teste nye teknologier (for eksempel databaser, meldingssystemer eller skytjenesteleverandører).
●   større og mer komplekse prosjekter, som er mer sannsynlig å dra nytte av heksagonal arkitektur.
●   prosjekter der testing er avgjørende, og du vil teste applikasjons- og domenelogikk separat fra infrastrukturkoden.

Imidlertid kan heksagonal arkitektur frarådes i visse situasjoner:
●   Et relativt enkelt prosjekt (noen ganger referert til som CRUD). I slike tilfeller kan en litt mindre elegant løsning fortsatt gi god verdi for innsatsen brukt på implementering.
●   En rask prototyp trenges for å sikre en klient for å bygge et mer omfattende system (og når klienten er vunnet, kan man vurdere å bruke heksagonal arkitektur).
●   Et rammeverkspesifikk bibliotek blir utviklet, der du vil binde deg til infrastrukturspesifikk kode for å utnytte det fullt ut.

Som du sannsynligvis kan gjette, passer mange prosjekter skrevet i vanlige programmeringsspråk inn i den første listen. Det antyder at du bør vurdere å bruke heksagonal arkitektur.

Et «viktig» spørsmål: Hvorfor har den seks sider?

Det er ingen direkte svar på dette spørsmålet. Her er hva vi tenker:

●   Sirkler, bokser og rektangler blir vanligvis representert i ulike sammenhenger.
●   Å tegne fem sider kan være mer utfordrende.
●   Mer enn fem sider ville bli ansett som «for mye».
●   For å få deg til å stille dette spørsmålet 🙂
●   Til slutt: Det spiller ikke så stor rolle, det er bare et navn.


Hvordan skiller Heksagonal seg fra Clean- og Onion-arkitekturene? 

Heksagonal, Clean og Onion-arkitekturene deler kjernepinsippet om å organisere kode for vedlikeholdbarhet, fleksibilitet og testbarhet. Alle representerer grunnleggende designkonsepter, som Dependency Inversion Principle. Heksagonal arkitektur fokuserer på å separere forretningslogikk fra infrastrukturkode gjennom porter og adaptere, noe som gjør den mindre generisk og enklere å forklare.
I motsetning til dette legger Clean- og Onion-arkitekturene vekt på separasjon av bekymringer gjennom konsentriske sirkler eller lag, med kjerneforretningslogikk i sentrum. Alle tre arkitekturene fremmer de samme grunnleggende OOP-konseptene, inkludert Dependency Inversion, og bør bli den forhåndsvalgte måten å tenke på organisering av kode. Til tross for forskjellene er hver modell et verdifullt verktøy for å skape ren, vedlikeholdbar og fleksibel kode.

Konklusjon

Hvis du etter å ha lest denne artikkelen mener at prinsippet er veldig enkelt og at du forstår det, kan du ha rett. Men du må ikke la deg lure til å tro at det vil være enkelt å følge i virkelige prosjekter.

Selv om teammedlemmene husker regelen, ser vi gang på gang at infrastrukturkoden vår «lekker» inn i applikasjonskoden, noe som gjør testing og vedlikehold mer utfordrende. I tillegg må hele teamet læres opp i heksagonal arkitekturregler og anvende dem konsekvent i sitt daglige arbeid.

Alt i alt bør heksagonal arkitektur bli vår standard måte å tenke på, da den virkelig fremmer fleksibilitet, testbarhet, gjenbruk og enkelt vedlikehold.

Kom på kurs i moderne arkitektur

Som vi nevnte i innledningen, holder vi kurs i moderne arkitektur i regi av Bouvet. På kursene deltar arkitekter, teamledere og seniorutviklere som vil bli oppdatert på fordeler og ulemper ved moderne arkitektur i web- og mobilapplikasjoner. I hvilke prosjekter kan vi heve kvaliteten ved hjelp av med moderne arkitektur – og hvilke fallgruver må vi unngå?

I tillegg til heksagonal arkitektur, dekker kurset temaer som mikrotjenester, CQRS, event sourcing, systemstabilitet og kvalitet i utviklingsprosjekter. 

Her finner du mer info om kursene våre:

Implementing Modern Architecture

Applying DDD & EventStorming in Modern Architecture

From Weeks to Hours: Bridging the Gap between Business and IT

Dette sier tidligere kursdeltakere:

«En veldig god og lærerik opplevelse, kan trygt anbefales videre. Ekstremt profesjonelt levert!”

«The course had a good pace and covered almost only interesting themes.»

«Fenomenalt kurs. Obligatorisk for alle systemarkitekter.”