Programvare arkitekturer 14. oktober 2001, Tore Berg Hansen, TISIP Kursleksjonene er forfatters eiendom. Som kursdeltaker kan du fritt bruke leksjonene til eget personlig bruk. Kursdeltakere som ønsker å bruke leksjonene til undervisning eller kursformål må ta kontakt med TISIP for nærmere avtale. Tore Berg Hansen
Sammendrag Denne leksjonen tar for seg programvare arkitekturer. Det er et tema som har fått større og større oppmerksomhet i de senere tid. Det er et viktig tema i forbindelse med utvikling av større programvaresystemer. Man ser systemet på et høyere abstraksjonsnivå. Programvare arkitektur dreier seg om strukturen til store programvaresystemer. Man konsentrerer seg om adferd og samspill mellom svart boks komponenter. I bearbeidingsfasen i Unified Process er programvare arkitektur sentralt. Hvis man skal sammenfatte bearbeidingsfasen i setning, som det står i læreboken, blir det denne: Build the core architecture, resolve the high-risk elements, define most requirements, and estimate the overall schedule and resources. Alle disse tingene er bestemt av eller har innflytelse på programvarens arkitektur. Programvarens arkitektur er realiseringen av tidlige beslutninger som må gjøres med hensyn til hvordan systemet skal settes sammen av deler skal gjøres. I en tidligere leksjon introduserte vi begrepet mønster (pattern). Her så vi på gode prinsipper for å fordele ansvar på objekter i et program. Programvare arkitektur dreier seg også om mønstre, men på et høyere nivå.
Innholdsfortegnelse 1 Introduksjon... 1 1.1 Hva er programvare arkitektur?... 1 2 Arkitektoniske stiler... 2 2.1 Rør og filter... 3 2.2 Objektorientering... 3 2.3 Implisitt kall... 4 2.4 Lagdelte systemer... 4 2.5 Repositorier... 5 2.6 Andre arkitektoniske stiler... 6 2.7 Heterogene arkitekturer... 7 Lesestoff... 7 Referanser... 8
1 Introduksjon Programvare arkitektur er en disiplin innenfor systemutvikling 1 som har fått økende interesse de senere år. Grunnen til det er at man har innsett at et av de viktigste kriterier for suksess ligger i å foreta en utforming av strukturen i et programvaresystem. Denne utformingen, også kalt arkitektonisk design, må gjøres tidlig i et utviklingsprosjekt. Gode systemutviklere har alltid hatt i sin verktøykiste et sett med programvarestrukturer som de gjennom erfaring og overføring på folkemunne har visst gir gode resultater. I den senere tid er det gjort flere forsøk på å systematisere og dokumentere slike arkitektoniske mønstre på samme måte som mønstre for god objektorientert design. Men arkitektonisk design går et nivå opp i abstraksjon og er ikke utelukkende knyttet til objektorientering. Vi har i tidligere leksjoner sett på et slikt arkitektonisk mønster Model View Controller. Det er en overordnet struktur som har vist seg velegnet spesielt i systemer som skal samspille med mennesker via et grafisk brukergrensesnitt. I denne modellen vektlegges at det skal være et klart skille mellom selvstendige deler av et program som brukergrensesnitt og de deler av programmet som gjør selve jobben (modell gjerne knyttet til domeneobjektene fra analysen). I eksemplet realiserte vi strukturen ved hjelp av objekter. Men det finnes andre måter å realisere innmaten i en slik struktur på. For andre typer systemer er andre strukturer mer hensiktsmessig. I denne leksjonen skal vi ta for oss noen slike strukturer. Spesielt skal vi se på det som kalles arkitektoniske stiler og som representerer en type struktur. Vi skal se på styrker og svakheter og hvilke typer av systemer de er velegnet for. Men systemer kan ha flere strukturer. Hver av dem viser sin side av arkitekturen. Vi må derfor definere og avklare hva som ligger i begrepet programvare arkitektur. Det er ikke lett, fordi det finnes mange forskjellige definisjoner. Men til tross for de mange definisjoner, så er det ting som er felles. Det er det viktige fordi det er disse felles tingene som avgjør om et utviklingsprosjekt skal resultere i suksess eller fiasko. Det er det gjennomgående poeng i denne leksjonen. 1.1 Hva er programvare arkitektur? I http://www.sei.cmu.edu/architecture/definitions.html#bibliographic gis en rekke definisjoner på hva programvare arkitektur er. Det man slår faste er at det ikke er noen én felles definisjon. En av grunnene til det er at fagfeltet er i sin barndom. Men røttene strekker seg langt tilbake i tid. I læreboken [2] på side 448 finner man en definisjon. Den er hentet fra [3]. Men læreboken har utelatt de siste setningene som lyder som følger: Software architecture is not only concerned with structure and behavior, but also with usage, functionality, performance, resilience, reuse, comprehensibility, economic and technology constraints and trade-offs, and aesthetic concerns. Det man kan trekke ut er følgende: - Arkitektur dreier seg om komponenter 2. En arkitektur omfatter informasjon om hvordan komponenter samspiller. - Et programvaresystem kan inneholde mer enn en struktur. - Ethvert programvaresystem har en arkitektur fordi det er bygd opp av komponenter og relasjoner mellom dem. 1 Software engineering 2 Begrepet komponent favner vidt i denne sammenheng. Eksempler på komponenter er klienter, tjenere, objekter, filtre, lag, databaser. Vi kommer i neste leksjon nærmere inn på temaet. 1
- Oppførselen til hver komponent er en del av arkitekturen. Det er denne oppførsel som gjør at komponenter kan samspille. I [1] som betraktes som en av klassikerne innenfor fagfeltet finner vi følgende beskrivelser: Programvare arkitektur dreier seg om beskrivelser av elementene som systemer bygges opp av, samspillet mellom disse elementene, mønstre som gir retningslinjer for hvordan komponentene skal settes sammen og rammer for disse mønstrene. Og videre klipper vi the design and specification of overall system structure become more significant issues than the choice of algorithms and data structures of computation. I [4] gis en omfattende definisjon. Hovedpoengene er følgende: Arkitekturen definerer komponenter. Det omfatter informasjon om hvordan komponenter samspillet med hverandre. Et system kan ha mer enn en struktur. Ikke en struktur er arkitekturen. F. eks så kan store systemer deles opp i komponenter som er egnet til fordeling av arbeid mellom grupper. Det kan også tenkes at systemet skal bestå av prosesser som skal kjøre på forskjellige prosessorer, kanskje geografisk distribuert. Det er en annen side ved strukturen til systemet. Alle systemer har en arkitektur. Dette fordi et system alltid kan deles opp i komponenter og relasjoner mellom dem. I det mest trivielle tilfelle er systemet selv en komponent. Adferden til hver komponent er del av arkitekturen. Det betyr at et diagram som viser bokser og linjer mellom bokser ikke er systemets arkitektur. I beste fall viser det en side ved arkitekturen. I disse poengene ligger også at arkitekturen til et system kan være god eller dårlig. Det betyr at en god arkitektur gjør at systemet tilfredsstiller alle krav, både funksjonelle krav og ytelseskrav og har i seg muligheter for senere utvidelser. 2 Arkitektoniske stiler Dere har sikkert støtt borti arkitektoniske stiler som klient-tjener, objektorientering og lagdelt. Noen av disse begrepene er knyttet til design metoder. Andre er knyttet til spesielle systemer. Man forsøker nå å beskrive slike stiler på en ensartet måte ved å se på typer av komponenter og typen av samspill mellom disse. En arkitektonisk stil definerer dermed en familie av systemer som er organisert etter et felles mønster. En arkitektonisk stil kan beskrives ved at man får svar på disse spørsmålene: - Hva er typen av komponenter og forbindelser mellom komponentene? Man bruker begrepet vokabular. - Hva er de tillatte strukturelle mønstre? - Hvilken beregningsmodell ligger i bunnen? - Hva er invariantene i stilen? - Finnes det noen kjente eksempler på bruken stilen? - Hvilke vanlige spesialiseringer finnes? Vi skal i det etterfølgende se på noen av de mest kjente slike stiler. Stoffet er i det vesentlige hentet fra [1]. 2
2.1 Rør og filter I en rør og filter arkitektur har hver komponent et sett med inputt og utputt. En komponent leser en strøm med data på inngangen og produserer en strøm med data på utgangen. Den Filtere Rør prinsipielle oppbygging er vist i figuren. Invarianter for denne stilen er at hvert filter må være uavhengig av hverandre. De vet ingenting om de filtere som kommer foran eller bak. En vanlig spesialisering er pipeline hvor strukturen er en lineær sekvens med filtere. De mest kjente eksempler på denne arkitekturen er fra skallprogammering i UNIX. I UNIX finnes mekanismer for å sette sammen komponenter i form av prosesser. Et annet kjent eksempel er tradisjonelle kompilatorer. De gode egenskapene til denne arkitekturen er: - lett å forstå - støtter gjenbruk - lett å vedlikeholde og utvide - gir støtte for samtidig eksekvering Noen ulemper er: - ikke så godt egnet for interaktive systemer 2.2 Objektorientering Dette er den arkitektoniske stilen vi har konsentrert oss om i dette kurset og skulle dermed være vel kjent. Hovedpoenget er dataabstraksjon og innkapsling av implementasjonsdetaljer. Objekter samspiller ved å sende meldinger i form av prosedyrekall. 3 Av de gode egenskapene til denne arkitekturen er: - man kan endre implementasjon uten at det påvirker brukerne av objektet - lettere å avspeile problemdomenet Men det er også noen ulemper: 3 I UML kalles det operasjon, i Java metode. 3
- Et objekt må for å samspille med andre objekter kjenne disses grensesnitt. Endres grensesnittet må alle objekter som er avhengige av dette objektet endres. - Dype arvhierki kan gi sterk kobling. 2.3 Implisitt kall Denne stilen ligner litt på objektorientering. Men i stedet for direkte kall til en operasjon, frikobler man de involverte komponenter. Det skjer på den måten at en komponent kringkaster eller annonserer et kall eller en hendelse. Andre komponenter i systemet kan registrere seg som interessenter i å håndtere visse hendelser. Det gjør de ved å registrere prosedyrer for disse hendelsene. Systemet kan da kalle slike registrerte prosedyrer. Dermed vil annonsering av en hendelse føre til et implisitt kall av en prosedyre. Eksempler på slike systemer er: - I Windows assosieres vindusprosedyrer med hendelser i brukergrensesnittet. Det er operativsystemet som kaller disse prosedyren i det programmet som skal håndtere disse hendelsene, som f.eks klikk på en knapp. - Hendelser i det grafiske grensesnittet i Java. Metoder assosieres med hendelser og programmer som skal fange opp disse hendelsene må implementere disse metodene. Den viktigste invarianten i slike systemer er at annonsøren av hendelser ikke behøver å vite hvem som blir mottaker. Det betyr at komponenten ikke kan gjøre antagelser om rekkefølgen av prosessering eller hvilken prosessering som blir resultatet av en hendelse. En annen god egenskap er lett gjenbruk. Nye komponenter kan introduseres ved at de registrerer sin interesse for visse hendelser. Den største ulempen er at en komponent ikke har kontroll over den resulterende oppførsel. Når en komponent annonserer en hendelse er den ikke garantert respons. Denne stilen finner man igjen i designmønsteret Observer/Publish-Subscribe/Delegation Event Modell. Det er bl.a beskrevet på side 372 i [2]. 2.4 Lagdelte systemer Et lagdelt system er organisert hierarkisk. Hvert lag sørger for tjenester til laget over og er klient til laget under. De mest kjente systemer som bruker denne arkitektoniske stilen er kommunikasjonsprotokoller. Man finner også igjen denne stilen i operativsystemer og databasesystemer. 4
Lag 7 Lag 6 Lag 5 Lag 4 Lag 3 Lag 2 Lag 1 Her i denne figuren har vi prinsippet. Lagdelte systemer har disse egenskapene: - Design basert på økende absttraksjonsnivå som betyr at komplekse systemer kan bygges i inkrementelle trinn - Fordi et lag bare samspiller med lag over og under vil endringer bare berøre høyst to komponenter. Det gjør det lett å utvide slike systemer. - Støtter gjenbruk. Forskjellige implementasjoner av et lag kan byttes ut. Det gjør det mulig å definere standard grensesnitt som andre kan bygge på (OSI ISO modellen). Av ulemper har vi: - Ikke alle systemer lar seg lett strukturere i lag. - Det kan være vanskelig å finne frem til det riktige antall lag (riktig abstraksjonsnivå). Det er noe av årsaken til at OSI ISO ikke har fått den forventede utbredelse, men taper i forhold til TCP/IP. I lærebokens kapittel 30 vies spesielt lagdelte strukturer stor oppmerksomhet. Der diskuteres også hvordan grensesnittet mellom lag kan realiseres med forskjellige design mønstre som Fasade, Controller og Observer. Det vises også at kommunikasjon ikke nødvendigvis går mellom to nærmeste lag, men også over lag. Dette kan by på spesielle problemer, men kan av og til være nødvendig bl.a av hensyn til ytelse. 2.5 Repositorier I repositorier er det to helt forskjellige typer av komponenter. Det er en sentral datastruktur og en samling uavhengige komponenter som opererer på denne datastrukturen. Datastrukturen lagrer tilstanden til systemet (informasjon, kunnskap). 5
Det er to hovedtyper av slike systemer. Database eller tavle (blackboard). Forskjellen går på hva som trigger utvelgelsen av prosesser som skal kjøre. I det første tilfellet er det typen av transaksjoner i en innstrøm som bestemmer hvilken prosess som skal kjøre. Hvis det er tilstanden til den sentrale datastrukturen som er utløsende har vi et tavlesystem. Det siste prinsippet er illustrert i denne figuren. ks2 ks3 ks1 Tavle (felles data) ks4 ks7 ks6 ks5 Her er det forskjellige kunnskapskilder (ksi). Samspillet mellom disse uavhengige komponentene foregår via tavlen. Tavlen representerer den felles datastruktur. Kunnskapskildene endrer på denne datastrukturen. Disse endringen fører etter hvert til løsningen av et problem. Kontrollen styres av tilstanden til tavlen (dvs innholdet i dataene). Slike arkitekturer har tradisjonelt vært bruk i systemer for gjenkjenning av tale og visuelle mønstre. Andre eksempler er programmeringsomgivelser som inneholder forskjellige verktøy som opererer på et program eller deler av et program. Moderne kompilatorer designes gjerne med denne arkitektoniske stilen. 2.6 Andre arkitektoniske stiler Prosesskontroll er en stil som kan brukes i sanntidssystemer. Klient-tjener er en velkjent arkitektur for distribuerte systemer. I slike systemer er en tjener en prosess (komponent) som yter tjenester til andre prosesser kalt klienter. Tjeneren vet som regel ikke på forhånd hvem klientene er. Klientene må kjenne til tjeneren eller har muligheten til å finne frem til egnede tjenere. Hovedprogram-subrutine er det vanlige resultatet når man programmerer i tradisjonelle programmeringsspråk som C, Fortran, Basic osv. 6
2.7 Heterogene arkitekturer De arkitekturene som er presentert kort her er såkalte rene arkitekturer. I større systemer finner man gjerne blandinger av disse stilene. Arkitekturer kan kombineres på forskjellige måter. Den kan være hierarkisk ved at systemer på øverste nivå har en stil, mens komponentene på nivåene under kan ha andre stiler. F.eks så kan filtre i et rør-filter system realiseres med objekter. Det samme kan lag i en lagdelt arkitektur. En annen måte å kombinere stiler på er å la en enkelt komponent bruke en blanding av arkitektoniske konnektorer. F.eks så kan en komponent samspille med et repository gjennom deler av sitt grensesnitt, mens andre deler av systemet kan nås gjennom rør. Et rør kan realiseres som en FIFO kø (først inn, først ut). Det vi har sett på her er logiske arkitektoniske stiler. Det avspeiler ikke hvordan et totalsystem realiseres med applikasjonen, operativsystem og maskinvare. I noen applikasjoner kan alle komponenter ligge på en maskin og kjøre under en tråd. For distribuerte systemer eller systemer som har parallellprosessering vil bildet være et annet. Lesestoff I denne utgaven av læreboken er det kommet til flere kapitler som omhandler programvare arkitektur. Kapittel 8 plasserer arbeidet med utforming av arkitekturen i bearbeidingsfasen. Det påpekes at det er viktig å få på plass de sentrale elementene i arkitekturen og prøve de ut i et kjørbart subset av systemet. Dette subsettet kan ses på som en tidlig versjon av det endelige system. Det kalles gjerne executable architecture eller architectual baseline. Hensikten er å få avdekket risikoer så tidlig som mulig og sørge for å eliminere før de fører til store problemer. Denne arkitekturen skal være et solid fundament hvor ny funksjonalitet kan legges til i inkrementer gjennom nye iterasjoner. Kapittel 30 diskuterer den logiske arkitekturen og hvordan den kan realiseres med mønstre. Det legges spesielt vekt på lagdelte strukturer. Det gis en definisjon av programvare arkitektur og sentrale begreper. Arbeidet med arkitektur deles inn i: Undersøkelser som dreier seg om å finne funksjonelle og ikke-funksjonelle krav som har avgjørende innflytelse på hvordan systemet må utformes i det store. Arkitektonisk design å finne frem til hvordan systemet skal struktureres når man må avveie forskjellige faktorer knyttet til programvarekrav, maskinvare, nettverksløsninger, drift osv. Spesiell behandling får tradisjonelle tre-lags arkitekturer. Det gås også litt inn på hvordan UML pakker kan brukes til å detaljere arkitekturer. Men husk at det finnes andre måter å beskrive arkitektoniske mønstre på enn ved hjelp av UML. Det gis også en begrunnelse for hvorfor det er viktig å skille Modell og View og gir eksempler på hvordan kommunikasjon kan skje mellom modell og view. I kapittel 32 introduseres SAD Software Architecture Document. Det er i dette dokumentet man nedtegner alle vesentlige beslutninger som dreier seg om systemets arkitektur. Kapittelet diskuterer arkitektonisk analyse, trinnene i denne analysen og vektlegger det å identifisere de faktorer som har innflytelse på valg av arkitektur. Tekniske memos introduseres. 7
De seks forskjellige arkitektoniske view i UP beskrives som. 1. Logisk 2. Prosess 3. Deployment 4. Data 5. Use case 6. Implementasjon [1] og [4] er to av standarverkene innen fagfeltet. De som skal arbeide med programvarearkitektur vil ha utbytte av å studere disse nærmere. Referanser 1. Mary Shaw and David Garland, Software Architecture, Prentice Hall, 1996, ISBN 0-13- 182957-2. 2. Craig Larman, Applying UML and Patterns. An Introduction to Object-Oriented Analysis and Design and the Unified Process, Prentice Hall, 2.utgave 2002, ISBN 0-13- 092569-1. 3. Grady Booch & al, The Unified Modelling Language User Guide, Addison Wesley, 1999, ISBN 0-201-57168-4. 4. Len Bass & al, Software Architecture in Practice, Addison Wesley, 1998, ISBN 0-201- 19930-0. 8