De software-ontwikkeling wordt vaak georganiseerd op basis van de hardware-architectuur. Dit verhoogt de kans op een functioneel interface tussen de software-subsystemen op elk hardware-platform. De integratie van subsystemen wordt hierdoor echter bemoeilijkt, terwijl er ook meer communicatie tussen de diverse software-ontwikkelgroepen nodig is. Dit is te vermijden door de software-organisatie te baseren op de software-architectuur, stelt architect Frits Greuter in dit tweede artikel van een drieluik.
De ontwikkeling van grootschalige, software-intensieve systemen is zowel een technisch als een organisatorisch probleem. Om het systeem binnen een aanvaardbare tijd te kunnen realiseren dient het te worden opgedeeld zodat meerdere mensen aan het werk kunnen. Deze mensen verschillen van inzicht over de manier waarop de technische problemen zijn op te lossen. Om de geschillen uit de wereld te helpen is onderlinge communicatie vereist, moeten er afspraken over verantwoordelijkheden komen, kortom is een organisatie van de software-ontwikkeling nodig. Juist omdat software in essentie niet meer is dan een weergave van ideeën (en ideeën zijn erg persoonsgebonden) zijn de technische en organisatorische problemen vaak verweven met elkaar. Beide zullen moeten worden opgelost, wil men met succes grootschalige softwareontwikkeling kunnen doen.
Brooks [1] geeft aan dat het stroomlijnen van goede oplossingen en ideeën (‘conceptual integrity’) binnen de software-ontwikkeling van doorslaggevende betekenis is voor het welslagen van een project. In een goede organisatie worden sommige goede ideeën verworpen, omdat ze niet goed in het totale plaatje passen – hoe vervelend dat ook voor de bedenker ervan is. In een slechte organisatie zullen goede ideeën en oplossingen niet optimaal benut worden.
Een goede organisatie alleen is echter niet voldoende. Indien de mensen niet genoeg inzicht en inventiviteit hebben om de technische problemen op te lossen, zal dit ook leiden tot middelmatige producten met langere ontwikkeltijd en hogere ontwikkelkosten.
De organisatie van een grootschalige software-intensieve systeemontwikkeling reflecteert de manier waarop het systeem wordt opgedeeld. Die moet aan diverse randvoorwaarden voldoen. Allereerst moet de opdeling in een kwaliteitssysteem passen zodat de kwaliteit van het product binnen de gestelde ontwikkeltijd en ontwikkelkosten gewaarborgd kan worden. Dit betekent dat het mogelijk moet zijn de status, omvang, herleidbaarheid en traceerbaarheid van de te ontwikkelen componenten te bepalen. Ten tweede moet de opdeling dusdanig zijn, dat ontwerpbeslissingen zo lang mogelijk kunnen worden uitgesteld. Bij complexe systemen is nu eenmaal een inwerktijd noodzakelijk om de problematiek überhaupt te begrijpen. Het is daarom noodzaak dat keuzes kunnen worden gemaakt op het moment dat er voldoende zicht is op de problematiek.
Er bestaan diverse invalshoeken om een grootschalige multidisciplinaire ontwikkeling op te delen: Een opdeling in systeem/product-eigenschappen; in betrokken disciplines (hardware/software/mechanica, enzovoort); per ontwikkelactiviteit (specificeer, ontwerp, test, integreer, enzovoort) en per component (discipline).
Een organisatie op basis van opdeling in systeemeigenschappen zal alle activiteiten van de betrokken disciplines versnipperen en wordt voor zover ik weet niet toegepast. De overige verdelingen vinden allemaal geheel of gedeeltelijk toepassing.
Om tot een goede organisatie van ontwikkelactiviteiten te komen, analyseren we eerst de diverse opdelingen vanuit een ontwerpperspectief. Het bepalen van de systeem/product-eigenschappen is multidisciplinair en noemen we systeemontwikkeling (systeemontwikkeling) . De ontwerpactiviteit die de opdeling van het systeem en per discipline bepaalt, is het architectuurontwerp. Allereerst komt de analyse van de multidisciplinaire afhankelijkheden van het architectuurontwerp per betrokken discipline aan bod.
Opdeling en architectuur per discipline
Software op zichzelf is nutteloos: we hebben altijd hardware nodig om een programma uit te voeren, en een scherm of audio-output naar een gebruiker, of fysieke connecties naar andere systemen. In elk software-intensief systeem hebben we dus minimaal met zowel elektrische als mechanisme disciplines te maken. De taken en problemen voor deze ontwerpdisciplines zijn echter eenvoudig in het geval dat standaard hardware en een standaard pc-kabinet worden gebruikt. Toch moet voor een schijnbaar eenvoudig lcd-scherm rekening worden gehouden met de invalshoek waaronder de gebruiker naar het scherm kijkt. Dit kan bijvoorbeeld leiden tot de eis aan een softwareprogramma dat tekst ‘diapositief’ wordt weergegeven. De systeemontwikkelaar bewaakt alle externe interfaces en maakt een scheiding in verantwoordelijkheden voor elke discipline. Voor een geschikte definitie van architectuur die rekening houdt met een multidisciplinaire ontwikkelomgeving, gebruiken we de definitie van Blaauw en Brooks [2] voor systeemarchitectuur:
‘De architectuur van een systeem is de functionele verschijningsvorm van het systeem naar zijn directe gebruiker’.
Lezen we voor gebruiker in dit geval ook een ander systeem, dan is de architectuur van een systeem (vanuit een ontwikkel perspectief) bepaald door de complete en gedetailleerde specificatie van alle externe interfaces van het systeem (inclusief de gebruikers-interface). Omdat er meerdere gebruikers zijn van een systeem, bestaan er, volgens bovenstaande definitie, meerdere architecturen voor één systeem. Voor een specifieke architectuur (discipline) identificeren we de directe gebruiker en de functionele verschijningsvorm zoals deze gebruiker die waarneemt, zie tabel 1.
Architectuur | Directe gebruiker | Functionele verschijningsvorm |
Systeem | Eindgebruiker | Gebruikershandleiding die de interactie met het systeem beschrijft. |
Systeem | Productafdeling | Lijst van producteisen |
Systeem | Verkoopafdeling | B.v. Lijst van plus- en minpunten t.o.v. concurrerende producten/systemen |
Hardware | Systeemprogrammeur | Handleiding voor systeemgebruiker, beschrijft hoe de beschikbare hardware registers te gebruiken. |
Hardware | Lopende-bandwerker | Lijst van materialen/onderdelen en instructies voor de assemblage. |
Software | Applicatieprogrammeur | Softwarespecificatie, die de datastructuur en bijbehorende functies van de software beschrijft, het dynamisch gedrag en de belangrijkste randvoorwaarden voor de implementatie. |
Software | Software-release ontwikkelaar | Lijst van directories, source files, executables, libraries en configuration files. |
Systeem Software Hardware | Afdelingsmanager | Lijst van werkzaamheden met geschatte tijdsduur, beschikbare mankracht, kostprijs, doorlooptijd enzovoort. |
Tabel 1. Definitie van architecturen per discipline.
We zien dus dat er niet één systeem-, software- of hardware-architectuur bestaat, maar dat verschillende gebruikers elk hun eigen architectuur zien. Bij software-intensieve systemen kan de systeemarchitectuur overlappen met de software-architectuur. Bij een besturingssysteem wordt de systeemarchitectuur bijvoorbeeld gegeven door de ‘programmer reference manual’, die de geboden systeemfuncties en de groepering in modules of bibliotheken aangeeft. De ‘include files’ die zichtbaar zijn voor de eindgebruiker, zijn ook onderdeel van de software-architectuur.
Indien een externe interface een protocol beschrijft, is het waarschijnlijk dat we de lagen en berichten die voor het protocol gedefinieerd worden, in de software-architectuur terugzien. Al kan de software-architect natuurlijk een andere afbeelding kiezen om de gewenste systeemfunctionaliteit te bereiken.
Voorbeelden van systeeemafwegingen
Binnen de multidisciplinaire systeemontwikkeling zijn systeem-, software- and hardware-ontwerpkeuzes niet onafhankelijk van elkaar. Systeemeigenschappen en systeemontwerp beïnvloeden de software-architectuur omdat ze de grenzen aangeven tussen hardware en software. Zeker bij de ontwikkeling van ingebedde systemen in een multidisciplinaire omgeving, zijn veel aspecten van belang om te komen tot de juiste oplossing van de problematiek. Hieronder volgt een drietal voorbeelden:
Om de besturing van een chemische reactor te realiseren hebben we kennis nodig van de chemische reactie zelf, van de meet- en regeltechniek (filterkarakteristieken, stabiliteit), en kennis van software en hardware. Moet het proces elke seconde worden bijgestuurd, elke tiende seconde of is wellicht elke tien seconden ook genoeg? Dit leidt tot een groot verschil (een factor honderd) in de hoeveelheid meetgegevens die getransporteerd (bandbreedte) en verwerkt (cpu-prestatie) moeten worden, en heeft gevolgen voor software en hardware. Er dient een afweging te worden gemaakt tussen de realisatiemogelijkheden binnen de diverse disciplines, zodat het doel, een kostenefficiënte regeling voor een reactor, binnen het gestelde ontwikkelbudget en -tijd gerealiseerd wordt.
Een ander voorbeeld betreft de externe seriële asynchrone RS232-verbinding met 1 startbit, 8 databits en 1 stopbit. De gebruiker wil alleen maar de stekker aansluiten om de verbinding te maken. Het zal hem weinig interesseren of de seriële verbinding in een hardwarecomponent (bijvoorbeeld de externe standaard Uart, onchip Uart, Fpga) is gerealiseerd of dat dit softwarematig is opgelost, waarbij de cpu snel genoeg moet zijn om de seriële datalijn te samplen.
Het laatste voorbeeld betreft het ontwerp van een route-informatiesysteem voor een auto. Een systeemeis bepaalt dat het systeem in staat moet zijn een route te genereren die aan bepaalde randvoorwaarden voldoet (kortste reistijd, kleinste reisafstand of toeristische route). Hiervoor zijn verschillende algoritmes mogelijk, die een andere informatie kunnen verlangen van de input (de route-informatie) of leiden tot langere routebepalingstijden. Het is de verantwoordelijkheid van de systeemontwikkelaar om het algoritme te selecteren en te beslissen welke informatie nodig is vanuit een (externe) routedatabase. Hij vraagt de software/hardware-architect naar de benodigde en beschikbare verwerkingskracht en kan dan besluiten om de eisen voor een specifieke discipline te verlichten, bijvoorbeeld minder cpu-kracht door het toestaan van grotere responstijden. Zodra het algoritme bekend is, kan de software-architect dit vertalen in de benodigde datastructuren en functies. Wellicht is voor een elegant maar rekenintensief algoritme te kiezen, indien er meerdere cpu’s gebruikt kunnen worden.
Opdeling in softwarecomponenten
Binnen de software-architectuur kunnen we een onderscheid maken in statische (passieve) componenten en dynamische (actieve) componenten. Om de diverse aspecten van de opdeling in softwarecomponenten weer te geven is bijvoorbeeld de ‘4+1 model-view’ van Rational gebruiken. Een typische implementatie-‘view’ van een gelaagde software-architectuur is die waarbij van onder naar boven de volgende lagen zijn te onderscheiden: besturingssyteem/hardware; framework-code; domeinspecifieke code; functionele applicaties (A, B, …). De framework-code dient op alle te ondersteunen hardware/besturingssysteemcombinaties te worden geïmplementeerd en maakt het onderliggende platform transparant voor de applicatieprogrammeur. De functionele applicaties kunnen daardoor over meerdere hardwareplatformen verdeeld zijn. Voor de software-architectuur zijn de eigenschappen van de framework-code cruciaal, omdat die de infrastructuur bepalen waarmee de overige softwarecomponenten in staat moeten zijn om de uit te voeren taken te coördineren. De framework-code geldt voor alle functionele applicaties en bevat dus geen specifieke applicatiefunctionaliteit, maar implementeert alleen de niet-functionele systeemeigenschappen. Niet alleen kan deze platformeigenschappen lokaliseren, maar ook bijvoorbeeld de ‘look & feel’ van een weergavesysteem bevatten alsmede faciliteiten voor (gedistribueerd) objectmanagement, ‘event’- en ‘datareporting’, alarm, herstel, enzovoort.
Bij domeinspecifieke componenten valt te denken aan protocolcomponenten, specifieke informatieadressering, of specifieke definitie van informatiestructuren die voor meerdere functionele applicaties gelden.
Functionele applicaties zijn een of meerdere actieve componenten voor bijvoorbeeld een robot-controller of het beheren van de systeembronnen.
Activiteiten per discipline
Een verdere opdeling van de ontwerpactiviteiten is te bereiken door onderscheid te maken in architectuur, implementatie en realisatie. Ook binnen andere ontwikkeldisciplines is het gebruikelijk dat een ontwikkelorganisatie het aantal ontwerpactiviteiten reflecteert (wie kent niet de tekenkamer en de productieafdeling?). Voor software-ontwikkeling is dan sprake van een architectuurafdeling, een implementatie- en een realisatieafdeling. Aangezien de ontwerpactiviteiten er altijd zijn, zal dit een stabielere organisatievorm opleveren. Maar ook dan is een verdere werkopdeling op basis van de software-architectuur gewenst: er moeten tenslotte softwareproducent worden ontwikkeld. De software-architectuur bepaalt dan de werkopdrachten voor de implementatie- en realisatieafdeling.
In de praktijk is het niet ongebruikelijk dat de software-ontwikkeling wordt opgesplitst volgens de hardware-subsystemen: verschillende groepen ontwikkelaars (soms ondergebracht in een andere afdeling) ontwikkelen de software per hardware-platform. Vervolgens wordt een functionele opdeling gemaakt: binnen een afdeling kan een groep zich richten op een bepaalde systeemfunctie, zie figuur 1.
De figuur toont een veel gebruikte opdeling voor meet- en regelsystemen met een man-machine interface voor een operator. Een opdeling per hardwaresubsysteem is weergeven. Voor het realiseren van systeemfuncties A en B zijn één of meerdere softwarecomponenten nodig op elk hardware-platform.
Wil men nu de software-ontwikkeling parallel laten lopen, dan moeten de (functionele) relaties tussen de softwarecomponenten op de verschillende hardware platformen al in een vroeg stadium bekend zijn. Door deze opdeling zijn de interfaces die tussen de softwarecomponenten worden gedefinieerd, vaak functioneel gericht. Dat leidt tot grotere integratieproblemen, zeker wanneer de ontwikkeling van de softwarecomponenten per subsysteem in verschillende afdelingen plaatsvindt. Bij complexe systemen kan het niet anders dan dat de interface wordt vastgesteld terwijl er nog onvoldoende zicht is op de volledige functionaliteit. Wil een van de groepen, op grond van verbeterde inzichten of door gewijzigde systeemeisen, de interface wijzigen, dan is dat vaak niet mogelijk omdat dit extra werk genereert bij een andere groep. Hierdoor bestaat de neiging om de afgesproken interface in stand te houden en de problemen lokaal op te lossen. Dit betekent dat de software onnodig complexer wordt gemaakt. Deze nadelen zijn te vermijden indien de software-ontwikkeling van een systeemfunctie bij één groep terecht komt. Dit kan door een organisatie te baseren op een opdeling in softwarecomponenten.
Software-architectuur als basis
De softwarecomponenten die nodig zijn om systeemfuncties te realiseren, kunnen worden samengevoegd in een samenhangend geheel verspreid over de diverse hardwarecomponenten. (De twee trio’s van onderlinge ellipsen in figuur 1 worden dan vervangen door twee grote ellipsen die door de drie hardwarecomponenten heen lopen.)
![]() |
Figuur 1. Systeemopdeling per subsysteem. |
Een systeemfunctie kan een toegangsmechanisme voor een verbinding zijn. In bovenstaande opdeling is één groep verantwoordelijk voor zowel de realisatie van het toegangsmechanisme alsmede voor de configuratie ervan. Uiteraard dient deze groep zich alleen bezig te houden met de functionele zaken. Dataoverdracht tussen de verschillende platformen, het implementeren van een bepaalde ‘look & feel’, en het kunnen omgaan met verschillende besturingssystemen en/of microcontrollers behoren niet tot deze functionele taak. Dit is mogelijk door een gelaagde software-architectuur te gebruiken. Omdat de afspraken tussen de applicatieprogrammeurs en de framework-programmeurs geen functionele inhoud hebben, zal de benodigde communicatie tussen deze groepen ook minder zijn. Op basis van de hoeveelheid data die de subsystemen moeten uitwisselen (benodigde bandbreedte), de te overbruggen fysieke afstand, en de gewenste topologie van de subsystemen kiest de systeemarchitect een bepaalde fysieke interface (bijvoorbeeld ethernet). Het software-framework zal mogelijkheden moeten bieden tot toegang op de fysieke interface. De ‘contents’ van de interface worden echter door de applicatie bepaald en zijn ook door de applicatieprogrammeur later te wijzigen zonder dat de framework-programmeur daarvan op de hoogte hoeft te worden gesteld. Door een andere opdeling in de componenten is het dus inderdaad mogelijk bepaalde ontwerpbeslissingen uit te stellen.
Scheiding van verantwoordelijkheden
Naast de opdeling van het systeem in verschillende componenten, is bij een organisatie ook de verantwoordelijkheid van de diverse mensen of groepen van belang. Hier wordt alleen even kort een schets gegeven van de architectenrollen.
De business-architect controleert alle disciplines, waarbij systeemontwikkeling ook als een discipline wordt gezien. Hij kan ervoor kiezen elke groep of discipline te belonen voor het realiseren van specifieke doelstellingen. Binnen bepaalde grenzen kan zo een tegenstelling in belangen worden gecreëerd; door de groepen of disciplines te belonen voor lokale optimalisaties, verwacht de business-manager het beste totale resultaat voor de systeemontwikkeling. Om conflicten tussen de diverse groepen te kunnen oplossen gebruikt de business-architect standaard beschikbare business-indicatoren: ontwikkeltijd, risico, productie of onderhoudskosten en verwachte opbrengst voor gewenste functionaliteit of producteigenschap. Elke groep moet in staat zijn om zijn belangen in termen van bussiness-indicatoren te verdedigen en te beargumenteren.
Alle architecten in iedere discipline gebruiken een identieke bron voor het architectuurontwerp: de producteisen of specificaties. De hoofdtaak van de software-architect is het realiseren van de gevraagde functionaliteit in een softwaresysteem. Het is niet zijn hoofdverantwoordelijkheid om een ‘business-case’ voor het softwaresysteem te creëren (dat is de taak van business-architect) of te controleren dat de eisen correct zijn voor de eindgebruiker: dit is een taak voor de systeemarchitect. Het belangrijkst voor de verkoopafdeling is de juiste functionaliteit voor de beoogde markt op de juiste tijd. De afdeling kwaliteitsborging bewaakt of de ontwikkeling voldoet aan de gestelde normeringen binnen de organisatie. De productieafdeling kan wensen dat zoveel mogelijk standaard beschikbare componenten worden gebruikt om het productieproces te vereenvoudigen. De afdeling mechanisch ontwerpen wil misschien de beschikbare ruimte minimaliseren om het product draagbaar te maken. Kortom, de producteisen zijn vaak tegenstrijdig per groep of per discipline.
Rol software-architect
Zeker bij software-intensieve systemen zal de software-architect een sleutelrol spelen.
Software is een erg kneedbaar materiaal, waardoor de eisen nogal eens kunnen wijzigingen. Hoewel fouten in de eisen bijdragen tot systeemfouten is het niet de taak van de softwareactiviteit om te waarborgen dat de eisen correct zijn voor een bepaald systeem. De spaarzame softwarekennis kan beter worden ingezet voor het verbeteren van de softwareontwerpen. Het verbeteren van het vastleggen van de eisen is de verantwoordelijkheid van kwaliteitsborging of systeemontwikkeling. Toch moet de architect meer in huis hebben dan alleen softwarekennis, bijvoorbeeld voldoende begrip van de domeinspecifieke problemen en de domeinspecifieke systemen. Verder moet hij over goede analytische vermogens beschikken, zodat hij specifieke en generieke softwarecomponenten kan identificeren. Overzicht van de belangrijkste realisatierandvoorwaarden is voorts een vereiste, anders is zijn ontwerp niet realiseerbaar. Tot slot moet hij zich bewust zijn van zowel financiële als persoonlijke gevolgen van de keuzes die gemaakt worden, en communicatieve vaardigheden bezitten.
Dat laatste is erg belangrijk. De software-architect moet niet alleen kunnen communiceren met verschillende mensen; zij hebben vaak een eigen vocabulaire en eigen interpretatie van identieke woorden. In een turbulente omgeving blijft het de hoofdverantwoordelijkheid van de software-architect om een goed softwareontwerp af te leveren binnen de gestelde eisen. Echter, goed ontworpen software is geen businessdoelstelling op zich; de architect moet zich bewust zijn van afwijkingen van zijn ontwerprichtlijnen. Als deze afwijkingen de software-architectuur te veel aantasten, zal de software-architect het verzoek moeten verwerpen. Indien ‘short-cuts’ worden toegestaan om bijvoorbeeld functionaliteit snel te realiseren, zal de architect extra budget moeten claimen om deze weer te verwijderen.
Voor een goede gang van zaken is veel meer inzicht nodig in de stijging van de kosten van softwareonderhoud ten gevolge van een lagere modulariteit of een hogere afhankelijksgraad tussen de diverse softwarecomponenten. In een ideale situatie zou de software-architect in een projectvergadering moeten kunnen zeggen: "Indien ik deze functionaliteit binnen drie maanden moet leveren zal het onderhoudsgetal van de software stijgen van 3,5 naar 5, terwijl voor onze producten 4,5 als maximum geldt. Verder neemt de testbaarheid af van 7 naar 6 waardoor er meer storingen in het veld zullen optreden tenzij we acht manmaanden extra besteden aan het testen." Om dit soort uitspraken te kunnen doen, is het nodig om veel meer te meten aan softwareontwerpen. Dat is het onderwerp van het derde artikel van dit drieluik.
Frits Greuter Software-architect Rohill Technologies
Literatuur
Brooks, F.P.: The Mythical Man Month, Essays on Software Engineering Anniversary Edition, Addison-Wesley (1995)
Blaauw, G.A. en Brooks, F.P.: Computer Architecture, draft, collegedictaat bij cursus 126113 van de Technische Universiteit Twente (1982)
Deze serie bestaat uit drie delen: