Kunsten at lave arkitektoniske diagrammer

Nøgleudbytte

  • Design af arkitektoniske diagrammer er måske ikke en nem opgave; det kan være vanskeligt eller fejlbehæftet, selv for de enkleste diagrammer. At skabe konsistente og meningsfulde diagrammer skaber klarhed og konsensus på tværs af forskellige interessenter.
  • I de fleste tilfælde er de virkelige problemer ikke strengt relateret til brugen af et mindre effektivt arkitektonisk beskrivelsessprog (f.eks. UML), men misforståelsen af diagrammernes betydning, afhængighed af ukorrekte eller inkonsekvente retningslinjer eller endog mangel på arkitektonisk uddannelse.
  • I processen med at skabe diagrammer bør man forsøge at blande automatisk genererede diagrammer med manuelt skabte diagrammer for at minimere arbejdet, illustrere forskellige problemstillinger og dække flere abstraktionsniveauer i systemet.
  • Da systemet er under udvikling, kræver det en ekstra indsats at holde diagrammerne ajour. Vi har brug for at vide, hvordan vi effektivt kan gå frem i sådanne tilfælde ved stadig at bevare konsistens og robusthed på tværs af arkitektoniske diagrammer.
  • Moderne arkitekturer medfører ekstra kompleksitet, som afspejles i diagrammerne. Der kan opstå yderligere bekymringer, og de kan let

På et tidspunkt kan der i alle softwareprojekter, som vi er involveret i, være behov for at oprette arkitekturdiagrammer. Uanset om vi følger en formel arkitekturmodel (f.eks. Kruchten 4+1, Rozanski & Woods osv.) eller ej, er der et behov for at dokumentere nogle dele af applikationen ved at oprette diagrammer. I softwarearkitektur oprettes sådanne diagrammer i overensstemmelse med views, som er relateret til et specifikt synspunkt, der kunne være en del af en model, men i den aktuelle artikel foretrækker jeg at holde mig til udtrykket arkitektonisk diagram og ikke være særlig formel; alle de andre aspekter skal ikke dækkes her.

Baseret på min erfaring som softwarearkitekt og teknisk underviser er der mange uoverensstemmelser mellem projekter og inden for projektteamet fra udvikler til udvikler i den måde, hvorpå arkitektoniske diagrammer oprettes. Jeg så en masse problemer med hensyn til inkonsekvens, fragmentering og granularitet af de gengivne oplysninger og diagrammernes udseende. I sammenligning med en arkitekturmodel, som skal være formel og standardiseret, er diagrammerne ikke nødvendigvis formaliserede eller følger en bestemt standard.

Du skal diagrammerne ikke desto mindre være selvbeskrivende, konsistente, præcise nok og forbundet med koden. Derfor er det vigtigt, at enhver arkitekt eller softwareingeniør baserer sig på flere retningslinjer, når han/hun skaber arkitekturdiagrammer, da de er det fælles grundlag for at kommunikere applikationens arkitektur over tid (f.eks. struktur, elementer, relationer, egenskaber, principper) og på tværs af forskellige interessenter med forskellige tekniske baggrunde og bekymringer.

Kontemporære faldgruber ved udformning af arkitekturdiagrammer

Hvor vi går dybere ind i mulige problemer, vil jeg gerne have en analogi til et engelsk idiom, der siger “et billede siger mere end tusind ord”. Ifølge denne wiki-forklaring “henviser det til forestillingen om, at en kompleks idé kan formidles med blot et enkelt stillbillede, eller at et billede af et emne formidler dets betydning eller essens mere effektivt end en beskrivelse”. Det samme koncept gælder for et arkitektonisk diagram: hvis det rejser flere spørgsmål end svar, er diagrammet ikke godt skabt. Et arkitektonisk diagram må ikke kræve tusindvis af ord eller præciseringer!

Eksempel på et ukorrekt arkitektonisk diagram. Det lider under de fleste af de problemer, der er beskrevet nedenfor

Lad os nu gennemgå en liste over faldgruber, der kan hindre processen med at skabe arkitektoniske diagrammer korrekt.

Hvad betyder en kasse eller form?

  • Hvis man bruger en kasse eller form, som ikke er ordentligt dokumenteret, kan det give anledning til flere fortolkninger. Den kan være forbundet med enten et stykke data, en bunke kode eller en proces. Bare en simpel boks i et diagram kan give anledning til flere tvivlsspørgsmål, og det er meget vigtigt at undgå dem ved udtrykkeligt at tilføje detaljer om boksens eller formens betydning i diagramlegenden.

Hvad repræsenterer de forskellige kanter af en form?

  • Hver kant af en form (f.eks. stiplet, stiplet osv.) kan misforstås i tilfælde af et dårligt diagram. Henviser en bestemt kant til en bestemt komponenttype (f.eks. henviser en stiplet linje til en container, en mikroservice, et lag osv.), eller er det bare designerens præference for at have et rigt udseende? Undgå en sådan forvirring ved at give præcise oplysninger i legendediagrammet, når der vælges flere eller ikke-standardiserede kanter.

Hvad betegner en linje eller en pil?

  • En linje eller en pil kan fortolkes enten som en datastrøm (f.eks. data strømmer fra system A til system B) eller som en relation på tværs af elementer (f.eks. komponent A er afhængig af komponent B). I de fleste tilfælde konvergerer de relationer eller datastrømme, der repræsenteres af pile, ikke i samme retning, og det er vigtigt at skrive dette eksplicit i diagramlegenden.

Hvad er den kommunikations-/associationstype, der angives af en linje eller pil?

  • Selv om linjen henviser til et datastrøm eller en relation på tværs af komponenter, skal den kommunikationstype (f.eks. i tilfælde af datastrøm) eller den associationstype (f.eks. i tilfælde af relation), der angives af den pågældende linje eller pil, være detaljeret. Hvis linjen f.eks. repræsenterer en datastrøm, kan kommunikationen være synkron eller asynkron, men hvis linjen henviser til en relation, kan den være repræsenteret ved en afhængighed, arvelighed, implementering osv. Alle disse detaljer skal være til stede i diagramlegenden.

Hvad betyder den farve?

  • Hvis man har et “perrot” policolor-diagram (f.eks. flere farver for bokse, linjer) uden nogen egentlig dokumenteret hensigt, kan det give anledning til flere spørgsmål (f.eks. hvorfor er nogle bokse grønne og andre røde? Hvorfor er nogle linjer sorte og andre blå?). Farveskemaet er mindre vigtigt i et diagram, og brugen af et stort antal farver giver ikke ret meget ekstra indhold eller værdifulde oplysninger. Et diagram kan også være selvforklarende og godt designet blot ved at bruge sorte og hvide farver, medmindre der er et strengt krav om at fremhæve visse dele af diagrammet ved at bruge farver, der kan skelnes fra hinanden. Under alle omstændigheder er det altid bedre at holde sig til enkelheden med hensyn til de anvendte farver, men hvis det ikke er tilfældet, må du ikke glemme at gøre valget detaljeret.

Manglende relationer mellem diagramelementer eller isolerede enheder

  • Manglende relationer mellem elementer eller isolerede enheder i et diagram kan være et fingerpeg om ufuldstændighed. Fra både et strukturelt og adfærdsmæssigt perspektiv bør hvert element eller hver enhed være afhængig af/have en relation (repræsenteret ved en linje eller pil) til en anden del af systemet repræsenteret ved et andet element.

Misvisende/undokumenterede akronymer eller for vage/generiske udtryk

  • Når man bruger en betegnelse for et element i et diagram, anbefales det, at man ikke bruger misvisende eller udokumenterede akronymer, som kan skabe forvirring. Bare en sekvens af bogstaver (f.eks. TFH, RBPM) betyder ikke noget uden en ordentlig forklaring på diagramelementet eller, endnu bedre, i diagramlegenden (f.eks. TFH – ticket feed handler, RBPM – rates business process manager).

  • En anden egenskab ved navngivning af diagramelementer vedrører ekstremt vage eller generiske udtryk (f.eks. forretningslogik, integrationslogik), som ikke giver for mange værdifulde oplysninger, fordi deres navne ikke er ordentligt selvbeskrivende. Dette problem kan også opstå på kodemæssigt niveau, og forslaget vil være, at man altid anvender selvforklarende og suggestive navne ved at følge principperne for ren kode.

Tilkendegivelse af teknologier, rammer, programmerings- eller scriptingsprog, IDE eller udviklingsmetodologi på diagrammer

  • Arkitektonisk design er ikke relateret til eller grundlæggende baseret på nogen teknologi, ramme, programmerings- eller scriptingssprog, IDE eller udviklingsmetodologi. Alle disse kommer senere i processen for at hjælpe med at opbygge arkitekturen, men de er ikke det centrale punkt. De bør ikke indgå i diagrammerne, men angives i arkitekturbeskrivelsen, herunder begrundelsen omkring valget af dem.

Mix runtime- og statiske elementer i samme diagram

  • Runtime-elementer (f.eks. tråde, processer, virtuelle maskiner, containere, tjenester, firewalls, dataregistreringer osv.) er ikke til stede på kompileringstidspunktet, og det anbefales at undgå at blande disse elementer med de statiske elementer (f.eks. komponenter, pakker, klasser) i samme diagram. Der findes dedikerede diagramtyper (f.eks. concurrency-diagram, deployment-diagram), som primært fokuserer på runtime-elementer, og det er vigtigt at skelne mellem disse to elementkategorier og undgå at blande dem så meget som muligt.

Gør antagelser som “Jeg vil beskrive dette verbalt”, og “Jeg vil forklare det senere”

  • Alt, der ikke er beskrevet af selve diagrammet, mangler, og der er ikke plads til at give verbale detaljer til at supplere et diagram. Hvorfor? Fordi alle forklaringer, der nævnes mundtligt, men som ikke er indfanget i diagrammet, går tabt, og senere, når andre interessenter (f.eks. udviklere, arkitekter) læser diagrammet, vil de ikke være opmærksomme på disse forklaringer. Prøv at medtage alle nødvendige detaljer i et diagram for at undgå behov for yderligere præciseringer.

Konflikterende detaljeringsniveauer eller blandede abstraktioner

  • Indførelse af elementer relateret til forskellige abstraktionsniveauer i det samme diagram kan skabe konflikter, da de ses fra forskellige perspektiver. Hvis man f.eks. tilføjer komponenter til et arkitektonisk kontekstdiagram eller klasser til et implementeringsdiagram, kan det afvige fra formålet med selve diagrammet. Når du opretter et diagram, skal du forsøge at holde dig til det samme abstraktionsniveau.

Fuldstændige eller for vage diagrammer, der forsøger at vise for mange eller utilstrækkelige detaljer

  • “Alt skal gøres så enkelt som muligt, men ikke mere enkelt” er et velkendt citat af Albert Einstein. Dette gælder også for arkitektoniske diagrammer; niveauet og granulariteten af de registrerede oplysninger bør vælges meningsfuldt. Dette er ikke let; det afhænger af den anvendte arkitekturmodel, arkitektens erfaring og systemets kompleksitet.

Retningslinjer, der skal følges ved udarbejdelsen af arkitekturdiagrammer

Selvom ovenstående faldgruber, som skal være en del af en forudsætningsmæssig tjekliste for at undgå dem, er der også generelle retningslinjer for, hvordan man korrekt udarbejder diagrammer:

Vælg det optimale antal diagrammer

  • Som Philippe Kruchten sagde, “arkitektur er et komplekst bæst”. Hvis man bruger et enkelt blueprint til at repræsentere arkitektur, resulterer det i et uforståeligt semantisk rod.” For at dokumentere moderne systemer kan vi ikke ende med kun at have én slags diagram, men når vi laver arkitekturdiagrammer, er det ikke altid ligetil, hvilke diagrammer vi skal vælge, og hvor mange af dem vi skal lave. Der er flere faktorer, der skal tages i betragtning, før man træffer en beslutning; f.eks. arkitekturens art og kompleksitet, softwarearkitektens færdigheder og erfaring, den tid, der er til rådighed, mængden af arbejde, der er nødvendigt for at vedligeholde dem, og hvad der giver mening eller er nyttigt for at imødekomme interessenternes ønsker. F.eks. vil en netværksingeniør sandsynligvis ønske at se en eksplicit netværksmodel, herunder værter, kommunikationsporte og protokoller; en databaseadministrator er bekymret for, hvordan systemet manipulerer, administrerer og distribuerer data osv. På baggrund af alle disse aspekter anbefales det at vælge det optimale antal diagrammer, uanset hvilket antal det er.
  • Hvis der ikke er tilstrækkeligt mange diagrammer (f.eks. underdokumentation), kan dele af arkitekturen være skjult eller udokumenteret; på den anden side, hvis der er for mange (f.eks. over-dokumentering), kan den indsats, der er nødvendig for at holde dem konsistente, opdaterede og ikke fragmenterede, øges betydeligt.

Hold strukturel og semantisk konsistens på tværs af diagrammer

  • Hvert diagram bør være konsistent med de andre med hensyn til bokse, former, rammer, grænser, linjer, farver osv. Det strukturelle udseende bør være det samme, og alle interessenter bør ikke have problemer med at forstå diagrammer, der er oprettet af forskellige udviklere i et team. Ideelt set bør man holde sig til et fælles diagramværktøj og genbruge det på tværs af alle projekter.
  • Fra det semantiske synspunkt bør alle disse diagrammer jævnligt synkroniseres med de seneste kodeændringer og mellem dem, da en ændring i et diagram kan påvirke andre. Denne proces kan udløses manuelt eller automatisk ved hjælp af et modelleringsværktøj. Sidstnævnte er den foretrukne mekanisme, men det afhænger af projekt til projekt, idet det i alle tilfælde er tanken at opretholde konsistensen mellem diagrammer og kode, uafhængigt af metode eller værktøj. Simon Brown sagde “diagrammer er ikke nyttige til arkitektonisk forbedring, hvis de ikke er forbundet med koden”, hvilket understreger ideen om semantisk konsistens.

Forebyg diagrammernes fragmentering

  • Hvis man har flere diagrammer, kan det gøre den arkitektoniske beskrivelse vanskelig at forstå, men også en betydelig indsats for at vedligeholde dem. Som en sideeffekt kan der opstå fragmentering (f.eks. kan to eller flere diagrammer illustrere den samme kvalitetsattribut – ydeevne, skalerbarhed osv. – men hvert af dem er individuelt set ufuldstændigt). I sådanne tilfælde anbefales det enten at fjerne de diagrammer, der ikke afspejler relevante kvalitetsattributter (knyttet til arkitektonisk vigtige krav) eller, endnu bedre, at slå diagrammer sammen (f.eks. samtidighed og implementering).

Hold sporbarhed på tværs af diagrammer

  • Det er også vigtigt at kunne kontrollere historikken, foretage sammenligninger mellem forskellige diagramversioner plus let at vende tilbage til en tidligere version. Brug af et modelleringsværktøj, der ikke tillader dette, kan være en hindring. De seneste tendenser i branchen er baseret på at bruge et simpelt og intuitivt almindeligt tekstsprog til at generere diagrammerne ud fra det, hvilket synes at løse problemet med sporbarhed. En anden fordel ved en sådan tilgang er, at den implicit sikrer en homogen strukturel konsistens mellem diagrammerne.

Tilføj legender ved siden af arkitektoniske diagrammer

  • Hvis du ikke følger et standardiseret arkitektonisk beskrivelsessprog (f.eks. UML, ArchiMate), så angiv hver enkelt del af diagrammet i legenden (f.eks. kasser, former, grænser, linjer, farver, akronymer osv.).
  • Hvis dette ikke er tilfældet, skal man i legenden blot tilføje det arkitektoniske beskrivelsessprog som en nøgle, og så er der ikke behov for yderligere forklaringer, da enhver læser vil følge med i de specifikke sprogspecifikationer for at forstå diagrammet.

Gør det arkitektoniske beskrivelsessprog (f.eks. UML, ArchiMate osv.) en forskel?

Der er mange meninger om, hvilket beskrivelsessprog der er det rigtige at anvende i projektet. Nogle vil måske hævde, at UML er stiv og ikke fleksibel nok til at modellere det arkitektoniske design, et synspunkt, som jeg er enig i. Ikke desto mindre kan det i nogle tilfælde være mere end tilstrækkeligt til at dokumentere de grundlæggende elementer i en arkitektur uden at være afhængig af UML’s udvidelsesfunktioner som profiler og stereotyper. Hvis vi ser på andre beskrivelsessprog, kan vi se, at ArchiMate er mere kraftfuldt og velegnet til modellering af virksomhedssystemer i forhold til UML; der er også BPMN, som er specielt rettet mod forretningsprocesser osv. Sammenligningerne kan fortsætte, men jeg har ikke til hensigt at lave en dyb gennemgang på tværs af dem, da det ikke er målet med denne artikel.

At have et arkitekturbeskrivelsessprog, der er omfattende og fleksibelt nok, er et stort skridt fremad, og det bør være et solidt kriterium, når man vælger det. Men fra mit perspektiv ligger den virkelige årsag et andet sted og er relateret til det faktum, at der slet ikke bliver skabt arkitekturdokumentation. Folk synes ofte, at det er kedeligt, ubrugeligt eller meningsløst at lave den. Antallet af softwareprojekter uden eller med uhensigtsmæssig dokumentation er enormt. Jeg tror ikke, at folk skaber eller deltager intensivt i udarbejdelsen af arkitekturdiagrammer ved hjælp af et ukorrekt beskrivelsessprog, og hvis de erstattede dem med et bedre sprog, ville resultaterne være meget anderledes. Nej, folk laver ingen arkitekturdokumentation (herunder arkitekturdiagrammer), og endnu værre er det, at de fleste af dem ikke har nogen idé om, hvordan man laver den korrekt. Det er disse ting, vi skal tage fat på først – at forstå, hvorfor dokumentation er vigtig, og hvordan den skal oprettes korrekt (ved at uddanne softwareingeniører); derefter kommer valget af de rigtige værktøjer helt naturligt.

Hvordan kan diagrammer holdes ajour, efterhånden som systemet udvikles, og ændringer i arkitekturen materialiseres

Der er få tilgange til at holde diagrammer ajour; nedenfor vil jeg udtrykke tre af dem. Den første mulighed, og den letteste, ville være at generere diagrammer automatisk ud fra kildekoden, som er grundsandheden. Dette garanterer, at de alle er konsistente i forhold til koden. Desværre er dette med de eksisterende værktøjer endnu ikke fuldt ud muligt (i det mindste mig bekendt), da de aktuelle værktøjer ikke kan skabe nogen form for nøjagtige og meningsfulde diagrammer udelukkende på grundlag af kildekoden uden betydelig manuel indgriben. Len Bass sagde, at “det ideelle udviklingsmiljø er et miljø, hvor dokumentationen er tilgængelig stort set gratis ved et tryk på en knap”, hvilket implicit indebærer automatisk generering af diagrammerne, men vi er ikke nået dertil.

Den anden fremgangsmåde ville være først at designe diagrammerne ved hjælp af et dedikeret værktøj, som derefter genererer kildetekstskeletterne (f.eks. komponenter/pakker med grænser, API’er), som udviklerne senere bruger til at udfylde koden. På denne måde skal enhver ændring i arkitekturen udløses fra selve diagrammet, som automatisk kan regenerere eller opdatere kodeskelettet.

Den sidste mulighed indebærer manuel opdatering af diagrammerne, hver gang en ny funktion – som har en indvirkning på det arkitektoniske design – implementeres. For at være sikker på, at alle kodeændringer afspejles i diagrammerne, anbefales det, at opdatering af diagrammer at være en del af definitionen af udført i udviklingsprocessen. Dette scenarie anbefales mindre, fordi det let kan medføre forældede eller inkonsekvente diagrammer (f.eks. glemmer udviklerne ofte eller er ikke i humør til at opdatere diagrammer), og desværre sker dette stadig i størstedelen af projekterne.

Tager man højde for de eksisterende værktøjer, er min anbefaling at have en blanding; at blande automatisk og manuelt oprettede diagrammer. Prøv f.eks. at forsøge at autogenerere diagrammer, som kan gengives rimeligt af værktøjer baseret på kildekode uden for meget støj (f.eks. for rodet eller meningsløse oplysninger). I denne kategori kan vi enten inkludere diagrammer med en høj grad af volatilitet (f.eks. mere tilbøjelige til hyppige udviklingsændringer, som normalt har en lavere abstraktion) eller tværtimod statiske diagrammer. Nogle af disse diagrammer kan f.eks. være kontekstdiagrammer, referencearkitekturdiagrammer, pakkediagrammer, klassediagrammer, entitetsdiagrammer osv. Ikke desto mindre er det i nogle tilfælde ikke indlysende alene på grundlag af kildekoden, hvordan systemet opfylder visse kvalitetsegenskaber (f.eks. tilgængelighed, skalerbarhed, ydeevne), og derfor er den automatiske oprettelse af diagrammer ikke en tilstrækkelig mulighed. Det er nødvendigt at supplere den med manuelt modellerede diagrammer. Nogle eksempler på sådanne diagrammer omfatter sekvensdiagrammer, tilstandsdiagrammer, samtidighedsdiagrammer, implementeringsdiagrammer, operationelle diagrammer osv.

Hvilke komplikationer (eller forenklinger) opstår der for arkitektoniske diagrammer, når man beskæftiger sig med moderne arkitekturer (f.eks.

Microservices eller enhver anden moderne arkitektonisk stil (f.eks. serverless, event driven) driver kun systemets struktur, hvordan komponenterne kommunikerer med hinanden (f.eks. relationer mellem dem) og hvilke principper der styrer dem. Personligt mener jeg ikke, at den arkitektoniske stil bør ændre rationalet eller koncepterne omkring oprettelsen af diagrammerne (og implicit den arkitektoniske beskrivelse), ej heller hvad de bør indfange. Men når vi taler om moderne systemarkitekturer, som normalt har en højere grad af kompleksitet i forhold til gamle og klassiske systemer (f.eks. monolit), har de bestemt en indvirkning på arkitekturbeskrivelsen og implicit på diagrammerne, idet der er flere overvejelser, der skal tages hensyn til. Sådanne overvejelser kan være med hensyn til forståelse af antallet af distribuerede komponenter (f.eks. distribuerede mikrotjenester), typen af hver enkelt komponent, hvordan komponenterne kommunikerer med hinanden (f.eks. grænser, API’er, meddelelser), deres livscyklus og hvem der ejer hver enkelt komponent.

Hvis man tager højde for alt dette, bør man som standard overveje visninger, der indfanger systemets dekomponering, udvikling, implementering og driftbarhed. Forestil dig f.eks. et system med et imponerende antal mikrotjenester; i et sådant tilfælde kan antallet af diagrammer stige betydeligt, fordi hver mikrotjeneste kan ende med at have sit eget sæt diagrammer. Problemer vedrørende konsistens (f.eks. påvirker en ændring af API’et for en tjeneste andre X-tjenester, og derfor skal alle berørte diagrammer opdateres), fragmentering (f.eks. er høj tilgængelighed eller ydeevne mellem distribuerede tjenester ikke konsolideret i ét diagram) eller tværgående problemer (f.eks. hvem har ansvaret for at illustrere aspekter som overvågning eller sikkerhed på tværs af hele systemelementer på en konsolideret måde) er måske ikke let at håndtere. Hertil kommer, at der kan være udfordringer i forbindelse med teamets sameksistens og samarbejde under projektudviklingen og endda efterfølgende med henblik på at vedligeholde det.

For at opsummere kan moderne systemer med komplekse arkitekturer medføre yderligere problemer, som kan føre til komplikationer selv på diagramniveauet.

Om forfatteren

Ionut Balosin er en softwarearkitekt og uafhængig teknisk træner. Han er en regelmæssig taler på softwareudviklingskonferencer og meetups rundt om i verden, hvor han leverer præsentationer, kurser og workshops. Du kan finde flere oplysninger på hans websted.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret.