Managed hosting door True

Standaardisatie van software-ontwerpactiviteiten ontbreekt nog steeds

Software hardleers

 

Software-ontwerp wordt nog steeds als onvolwassen beschouwd. De belangrijkste vraag bij software is vaak 'werkt het of werkt het niet' zonder dat verder de kwaliteit van de software-ontwerpen getalsmatig wordt uitgedrukt. Zeker nu de kosten van het onderhoud stijgen, is het belangrijk een beter inzicht te krijgen in de kwaliteit van software-ontwerpen. Hierdoor moeten we echter eerst vastleggen wat precies een software-ontwerp inhoudt, alvorens aan ontwerpmetingen te kunnen beginnen.

In een drieluik brengt software-architect Frits Greuter de problematiek rond software-ontwikkeling in beeld, door het beschrijven van achtereenvolgens definitie en organisatie van software-ontwerpactiviteiten, en van metingen aan software-ontwerpactiviteiten. Computer hardware engineering als uitgangspunt nemen.
Software-ontwikkelaars worden de laatste jaren 'bestookt' met kwaliteitsverbeteringsprogramma's, vaak binnen het kader van ISO of CMM (Capability Maturity Model). Voeg daarbij een stapel foutrapporten die door de testafdeling wordt aangeleverd en veel programmeurs hebben het gevoel niet meer aan het 'echte' programmeerwerk toe te komen. De metingen die gedaan worden aan software-producten en software-ontwikkelwerkzaamheden binnen het kader van CMM kunnen erg nuttig zijn, maar door het ontbreken van duidelijke standaarden en definities voor de software-ontwerpactiviteiten worden de resultaten onvoldoende teruggekoppeld naar aanbevelingen voor ontwerpverbeteringen. Verder blijven de meetresultaten gebonden aan een bepaalde organisatie en is het lastiger om CMM-meetresultaten van verschillende organisaties met elkaar te vergelijken om zodoende meer te kunnen leren en tot verbetering van de software-ontwerpen te komen.
Ook de term software-architectuur is nu erg in. Een goede software-architectuur wordt als belangrijk beschouwd voor het welslagen van een software-project. Het is echter onduidelijk wat nu precies een (goede) software-architectuur is. In de literatuur zijn verschillende definities van software-architectuur te vinden en voor veel programmeurs 'in het veld' zijn die vaak te abstract. Zij laten dan ook de in de literatuur gegeven definities links liggen.
Om de zin van software-architectuur te verduidelijken, wordt vaak de vergelijking gemaakt met de architectuur van een gebouw. Uiteraard is het geen verkeerd idee om te kijken hoe andere engineering-disciplines soortgelijke problemen hebben opgelost, hoewel het neerzetten van een gebouw een totaal andere activiteit is. Software-ontwikkeling heeft wel veel raakvlakken met het ontwikkelen van digitale hardware: beide disciplines houden zich bezig met de ontwikkeling van systemen waarbij discrete logica een centrale rol speelt. Het is daarom vreemd dat er niet gekeken wordt naar de ontwerpactiviteiten die binnen de computerhardware-engineering gangbaar, geaccepteerd en succesvol zijn. Niemand kijkt ervan op dat op een chip tegenwoordig miljoenen transistoren samen een set van logische functies kunnen vervullen. De hardware wordt alsmaar krachtiger en complexer, en de ontwikkelingen gaan daar snel. Het realiseren van een software-programma van een paar miljoen regels kost echter bijzonder veel manjaren. Als zo'n systeem eenmaal is gerealiseerd, volgt niet zelden een lange fase van duur onderhoud voor relatief kleine functionele uitbreidingen.

Definities ontwerpactiviteiten

Binnen de software-ontwikkeling vinden vele activiteiten plaats. Er bestaan diverse software-ontwikkelmodellen die de benodigde activiteiten benoemen en rangschikken. Afhankelijk van het gebruikte ontwikkelmodel worden de activiteiten verschillend benoemd. Het 'watervalmodel' identificeert onder andere activiteiten als 'high-level design', 'low-level design' en 'coding'. Binnen het objectgeoriënteerde model worden de ontwerpactiviteiten aangeduid als analyse, ontwerp, en implementatie. Exacte definities, die een eenduidige beschrijving van de resultaten van de ontwerpactiviteiten moeten geven, ontbreken.
Wat is precies het verschil tussen analyse en ontwerp? Is het resultaat van de analyse niet een ontwerp? Waar houdt het 'ruwe ontwerp' ('high-level design') op en begint het fijne ontwerp ('low-level design')? Wordt dit puur bepaald door de omvang? Bij een omvangrijk project kan een fijn ontwerp best uit 50.000 regels software bestaan terwijl dit voor een ander project de totale hoeveelheid code is. Maar in kleinere projecten is toch ook sprake van ruw- en fijn-ontwerpactiviteiten? De activiteit 'software-architectuur' ontbreekt zelfs nog in genoemde ontwikkelmodellen, tenzij we high-level design of analyse als zodanig interpreteren.
Voor software-architectuur kunnen we vele definities vinden. De meest gangbare definitie komt van Bass, Clements en Kazman (http://www.sei.cmu.edu/architecture/definitions.html) : 'De software-architectuur van een programma of computersysteem is de structuur of structuren van het systeem bestaande uit softwarecomponenten, de externe zichtbare eigenschappen van deze componenten en de relaties tussen de componenten.'
Voor het beschrijven van de exacte resultaten van het software-architectuurontwerp schiet deze definitie in verschillende opzichten te kort. Zo is een aantal zaken onduidelijk: wat is precies een component (een regel code, een klasse, een file?), wat zijn precies extern zichtbare eigenschappen (software is per definitie onzichtbaar voor een eindgebruiker) en hoeveel software-componenten moeten er nu bekend zijn voordat de software-architectuur is bepaald? Verder wordt er zowel over een programma als over een systeem gesproken terwijl er toch een groot onderscheid gemaakt kan worden tussen een systeemarchitectuur en een software-architectuur. Door (oo)programmeertaalelementen te gebruiken worden veel van de onduidelijkheden in bovenstaande definitie opgelost. De definitie wordt nu: 'De software-architectuur van een programma is de structuur of structuren van het systeem bestaande uit klassen ('classes'), de externe zichtbare eigenschappen van deze klassen ('public methods' en data) en de relaties (overerving ('inheritance'), lid ('member'), enzovoort) tussen deze klassen.'
Nu laat de definitie weinig ruimte meer voor verschillende interpretaties. Echter, voor grote systemen (met een paar duizend klassen) is deze definitie niet bruikbaar omdat niet alle klassen even belangrijk zijn voor wat de software-architectuur wordt genoemd. Ook zijn de in de definitie genoemde relaties (overerving, lid) statisch, de dynamische relaties en eigenschappen van een software-architectuur worden niet beschreven. Toch zien we dat een beschrijving van de software-ontwerpactiviteiten in programmeertaalelementen exacter kan zijn en veel van de onduidelijkheden in de bestaande definities kan wegnemen. Maar laten we eerst de ontwerpactiviteiten voor computerhardware eens bekijken.

Hardware-ontwerpdefinities

Blaauw en Brooks [1, 2] worden gezien als de grondleggers van de definities van ontwerpactiviteiten. Als ontwerpactiviteiten zien zij architectuur, implementatie en realisatie elk met specifieke resultaten. Alle ontwerpactiviteiten vereisen specifieke kennis, en vragen een creatieve inspanning van de ontwerpen om tot een 'goed' ontwerp te komen. De definities zijn weergeven in tabel 1.

OntwerpDefinitieSleutelwoordBetreft
ArchitectuurFunctionele verschijningsvorm voor de systeemprogrammeurWatFunctie
ImplementatieLogische structuur waarmee de architectuur uitgevoerd kan wordenHoeMethode
RealisatieFysieke structuur die de implementatie belichaamtWelke,
Waar,
Wanneer
Middelen

Tabel 1. Definitie ontwerpactiviteiten voor hardware.
 
De cpu-systeemprogrammeur ziet de programmeerbare hardware via een aantal registers (adres, data) waarmee met behulp van een instructieset operaties zijn uit te voeren. De implementatie bepaalt hoe de instructies worden afgehandeld (bijvoorbeeld gebruik microprogramma of 'hard-wired control') en de realisatie bepaalt waar de benodigde registers en instructieset in transistoren worden opgeslagen. Als algemene definitie voor systeemarchitectuur geven Blaauw en Brooks:
'De architectuur van een systeem is de functionele verschijningsvorm voor de directe gebruiker'.
Hieruit volgt direct dat de architectuur per type gebruiker kan verschillen: een verkoper zal anders tegen een systeem aankijken dan een ontwikkelaar. Als directe gebruiker van een computerhardware-systeem zien zij dus de systeemprogrammeur; zij hebben dan ook gekozen voor een gebruiker buiten de hardware-ontwikkelafdeling.

Toepassen op software

Willen we bovenstaande definities toepassen op software, dan zullen we eerst de gebruiker van de software-architectuur moeten bepalen. Nu is software op zich nutteloos: we hebben altijd hardware nodig voor de uitvoering ervan en een scherm plus keyboard of audioapparaat om de functionaliteit aan de gebruiker te tonen. Een keuze voor een externe gebruiker van software-architectuur (buiten de software-ontwikkelafdeling) ligt dus niet voor de hand. Kijkend naar gebruikers binnen een software-ontwikkeling zouden we de persoon moeten nemen die de software-architectuur implementeert. Wie is dit? De programmeur? Maar houdt programmeren niet in dat er gecodeerd, gecompileerd, gelinkt en gedebugged moet worden? Gaat het kortom om een persoon die zich bezig houdt met software-realisatie in plaats van software-implementatie? Het probleem is dat een programmeur beide activiteiten doet en vaak ook meer (specificeren en testen). Onderscheid maken met behulp van de sleutelwoorden biedt meer soulaas, zie tabel 2.

OntwerpDefinitieSleutelwoordBetreft
ArchitectuurWat is de functionaliteit
Waar wordt de functionaliteit geplaatst
Wanneer wordt de functionaliteit uitgevoerd
Wat
Waar
Wanneer
Functie
ImplementatieHoe wordt de functionaliteit gemaaktHoeMethode
RealisatieWelke ontwikkelomgeving, taal, platform moet gebruikt wordenWelkeMiddelen

Tabel 2. Definitie ontwerpactiviteiten voor software.
 
Zoals hardware-functionaliteit bestaat uit een keuze van de registers en de operaties daarop, zo bestaat software-functionaliteit uit de keuze van de datastructuren en de operaties daarop. De software-architect vertaalt systeemfunctionaliteit in datastructuren en operaties of functies daarop, en de groepering van functionaliteit in bibliotheken of 'executables'. De software-implementatie bepaalt de logisch 'flow' (algoritme) van de software-architectuur. De software-realisatie vertaalt de logische 'flow' in een uitvoerbaar software-product op de gewenste omgeving van hardware en besturingssysteem. Gebruiken we wederom de terminologie uit een oo-programmeertaal, dan zijn ook de producten c.q. resultaten van elke ontwerpactiviteit duidelijk te omschrijven.

Resultaten

De software-architectuur resulteert in een volledige beschrijving van alle klassen, de 'public methods' en 'public data' en de groepering in bibliotheken, 'executables', 'threads', en 'tasks'[1,2]. Wanneer de realisatie gedeeltelijk bekend is (de programmeertaal en de ontwikkelomgeving) kan een architectuurontwerp worden afgeleverd als een programma dat compileert, linkt en executeert en verder niets doet omdat alle functies nog leeg zijn. De software-architect kan raamwerken van ontwerppatronen ('frameworks of design patterns') toepassen en functionele en niet functionele code scheiden. Op het hoogste niveau wordt de software-architectuur bepaald door: de identificatie van de bibliotheken (statische subsystemen) en hun onderlinge afhankelijkheden; de identificatie van de 'executables' en 'threads' (dynamische subsystemen) en hun interacties, en de afhankelijkheden tussen dynamische en statische subsystemen.
De identificatie van de bibliotheken en de 'executables' is het resultaat van de logische en gelaagde opdeling van de software-functionaliteit.
De resultaten van de software-implementatie zijn de stroomdiagrammen van de 'public methods' en een beschrijving van de benodigde persoonlijke data alsmede een stroomdiagram van de persoonlijke 'methods'. De implementatie richt zich op efficiënte algoritmes, zowel in tijd als ruimte. De implementatie kan ook goed worden weergeven met behulp van een hogere programmeertaal.
Het resultaat van de software-realisatie is de binaire code die uitgevoerd kan worden op de gekozen hardware. De software-'realisator' is een programmeertaal-expert. Indien de implementatie in een hogere programmeertaal is weergegeven, controleert hij of die correct en efficiënt wordt gebruikt. Hij kent de onderliggende hardware en het besturingssysteem en weet alles van de compiler, de linker, de ontwikkelomgeving en de gebruikte externe bibliotheken. Uiteraard hoeft het niet één persoon te zijn.

Verschillen software en hardware

Vergelijken we de gegeven definities van de software met de hardware, dan valt op dat de sleutelwoorden 'waar' en 'wanneer' verschoven zijn van het realisatiedomein naar het architectuurdomein. Het tijdsaspect (wanneer) speelt een rol in alle ontwerpactiviteiten zowel bij hardware-ontwerpen als bij software-ontwerp. Bij hardware is het tijdsaspect prominent aanwezig in het realisatiedomein (snelheid van de componenten en vertraging over de verbindingslijnen). Hardware-implementatie heeft te maken met de relatieve timing en hardware-architectuur bepaalt de logische volgorde (wat moet sequentieel en wat mag parallel). Ook bij de software-ontwerpen speelt het tijdsaspect mee in zowel architectuur, implementatie en realisatie. Het belangrijkst is hier echter de logische volgorde waarin de functies geëxecuteerd worden, hoewel elke functie een absolute executietijd heeft op een cpu.
Dit geldt ook voor sleutelwoord 'waar'. In hardware is dit de fysieke locatie op een chip; in software is er meer sprake van allocatie aan een bibliotheek of 'executable' dan aan een bepaald geheugengebied.
Een belangrijke eigenschap van de hardware-definities is verder dat deze relatief (ten opzichte van elkaar) zijn gegeven, hetgeen ze beter toepasbaar maakt voor projecten van verschillende omvang. Nadeel is dat het resultaat van de ontwerpactiviteiten niet wordt benoemd in terminologie van het realisatiedomein, waardoor de definities veel minder ruimte laten voor verschillen in interpretaties. Voor grote software-projecten kan de software-architect zich beperken tot de 'ruwe' architectuur: het benoemen en identificeren van de 'executables' of 'threads' en de bibliotheken.

Verschillen met bestaande definities

Een belangrijk verschil is dat de gegeven opdeling in ontwerpactiviteiten duidelijker van elkaar te onderscheiden zijn. Het definiëren van data-structuren wordt bijvoorbeeld gezien als ruw ontwerp, terwijl er ook op gedetailleerd niveau nog steeds datastructuren worden gedefinieerd. Dit maakt het lastiger een duidelijke scheidslijn te trekken. De opdeling van de ontwerpactiviteiten betekent geenszins dat er een aristocratie van software-architecten ontstaat die een leger 'domme' implementatieprogrammeurs tot hun beschikking hebben, zoals Brooks [1] al duidelijk beschrijft.
We zien ook dat de definitie voor software-architectuur van Blaauw en Brooks [2] dicht bij die van Bass, Clements en Kazman komt. Indien we 'verschijningsvorm' vertalen met 'structuur en eigenschappen van de software-componenten' en 'directe gebruiker' vertalen met 'applicatieprogrammeur' krijgen we:
'De softwarearchitectuur van een systeem is de structuur en de eigenschappen van de software-componenten, zichtbaar voor de applicatieprogrammeur'.
Hoewel deze definitie nu dicht bij de definitie van Kazman komt, heeft hij ook dezelfde nadelen: het ontbreekt aan duidelijk gedefinieerde resultaten van de verschillende ontwerpactiviteiten.
Het identificeren van verschillende activiteiten en het duidelijk omschrijven van de resultaten zijn belangrijke uitgangspunten voor elk kwaliteitssysteem. Vanuit een kwaliteitsstandpunt gezien moeten we vaststellen dat de software-ontwerpactiviteiten onvoldoende gedefinieerd zijn. De onduidelijkheden in de definities van software-ontwerpactiviteiten en met name software-architectuur zijn weg te nemen door de resultaten ervan te benoemen in het realisatiedomein van de software (de programmeeromgeving). Hierdoor wordt vermeden dat de ontwerpactiviteit verschillende interpretaties krijgt.
Tevens kunnen we concluderen dat de definities van hardware-ontwerpactiviteiten ook voor software-ontwerpactiviteiten zijn toe te passen. Door de opdeling in architectuur, implementatie en realisatie worden alle benodigde software-ontwerpactiviteiten afgedekt, terwijl ook de verantwoordelijkheden beter verdeeld zijn.
De gegeven software-ontwerpdefinities geven een opdeling in de ontwerpactiviteiten (eventueel per systeemfunctie) terwijl in de huidige praktijk vooral een opdeling op basis van systeemfunctionaliteit plaatsvindt. Dit blijkt bijvoorbeeld uit de personeelsadvertenties voor software-programmeurs. Vaak wordt vermeld dat de programmeur zowel in het traject van specificatie, ontwerp, codering en testen van een bepaalde systeemfunctie wordt ingezet. Dit heeft diverse nadelen.
Een functionele opdeling van de werkzaamheden is niet bevorderlijk voor het verbeteren van de softwarekwaliteit, omdat er geen onafhankelijke controle van gescheiden taken plaatsvindt. Een software-ontwikkelorganisatie wordt hierdoor ook afhankelijk van de betreffende programmeur omdat de functionele kennis van een onderdeel bij slechts één persoon wordt ondergebracht. Specifieke ontwerpgebieden worden onvoldoende gespecialiseerd, hetgeen leidt tot productiviteitsverlies. Verder wordt er onvoldoende van de beschikbare capaciteiten gebruikt gemaakt. Niet elke programmeur is tenslotte even getalenteerd om een goede keuze van datastructuren te maken. Juist in een bedrijfstak waar mensen onvoldoende geschoold zijn, kennis van specifieke (formele) talen niet altijd voorradig is, en een redelijk groot personeelsverloop bestaat, is dit onverstandig. Verder leent een opdeling in architectuur, implementatie en realisatie
zich ook beter voor uitbesteding van software-ontwikkelactiviteiten naar bijvoorbeeld lage-lonen-landen. Ook de interne communicatie kan sterk worden verminderd, zeker indien een strikt onderscheid wordt gemaakt in systeemarchitectuur en software-architectuur. Hoe de genoemde verdeling van de software-ontwerpactiviteiten onder deze voorwaarde zijn toe te passen in een ontwikkelorganisatie wordt in een volgend artikel belicht.
 

Frits Greuter Software-architect Rohill Technologies

Literatuur

[1] Brooks, F.P.: The Mythical Man Month, Essays on Software Engineering Anniversary Edition, Addison-Wesley, 1995
[2] Blaauw, G.A. en Brooks, F.P.: Computer Architecture, fall 1982, draft, collegedictaat bij cursus 126113 van de Technische Universiteit Twente.
 
Deze serie bestaat uit drie delen:

Dit artikel is afkomstig van Computable.nl (https://www.computable.nl/artikel/1348263). © Jaarbeurs IT Media.

?


Lees meer over


 
Vacatures

Stuur door

Stuur dit artikel door

Je naam ontbreekt
Je e-mailadres ontbreekt
De naam van de ontvanger ontbreekt
Het e-mailadres van de ontvanger ontbreekt

×
×