Aanpak van softwareontwikkeling

Zoals voorbeeld 8 laat zien, moeten ontwikkelaars omgaan met de afhankelijkheden die ontstaan als gevolg van hun decompositie van een probleem en de oplossing daarvan in een aantal modules. We zeggen dat een module van een systeem afhankelijk is van een andere als het mogelijk is dat een wijziging in de ene module een wijziging in een andere module vereist. Als een bedrijf bijvoorbeeld zijn produktiemethoden wijzigt, kan dit tot gevolg hebben dat de manier waarop het de betalingen berekent die nodig zijn voor de goederen die het produceert, verandert.

Een ontwikkelaar moet niet alleen rekening houden met de aard van elke afhankelijkheid, maar ook met het aantal afhankelijke modules. In de software engineering wordt “koppeling” gebruikt om te verwijzen naar de mate van onderlinge afhankelijkheid tussen de verschillende onderdelen van een systeem. Het is gemakkelijk in te zien dat bepaalde systemen ketens van onderling afhankelijke modules kunnen hebben, waarbij bijvoorbeeld module A afhankelijk is van module B, die weer afhankelijk is van module C, enzovoort. In sommige gevallen kunnen deze ketens samenkomen en een circulaire afhankelijkheid creëren, wat een bijzondere vorm van sterke (of hoge) koppeling is.

Ontwikkelaars proberen losjes gekoppelde systemen te construeren omdat die gemakkelijker te begrijpen en te onderhouden zijn. Een goed softwaresysteem heeft dus een lage koppeling, wat betekent dat veranderingen in één onderdeel minder snel doorwerken in de rest van het systeem. Een ander voordeel van een geringe koppeling is dat onderdelen gemakkelijk kunnen worden vervangen en eventueel hergebruikt.

Wat de mate van koppeling in een softwaresysteem ook is, het is belangrijk te weten welke modules gekoppeld zijn. Als er geen gegevens over de koppeling tussen modules zouden zijn, zou een ontwikkelaar tijd moeten besteden aan het doorlopen van de modules om te bepalen of elke module al dan niet door een wijziging wordt beïnvloed. Het resultaat zou zijn dat er veel moeite wordt besteed aan het controleren, zelfs als er geen wijzigingen nodig zijn. Voorbeeld 9 illustreert het gevaar van meer dan één module die gebruik maakt van gemeenschappelijke of gedeelde gegevens.

Voorbeeld 9

Hantering van de datum is altijd een probleem geweest voor software-ontwikkelaars. Voor toepassingen van een bepaalde leeftijd was het meest toepasselijke opslagformaat voor het weergeven van een jaar een getal tussen 0 en 99. Dat was logisch omdat 1966 werd opgeslagen als 66, 1989 als 89, enzovoort, en er dus minder ruimte nodig was om slechts twee cijfers op te slaan. Bovendien, als datums werden opgeslagen als getallen, waren taken waarbij sorteren op datumvolgorde nodig was eenvoudig – 22 januari 1989 opgeslagen als 890122, is na 22 december 1966 opgeslagen als 661222.

Helaas waren een aantal van deze toepassingen nog steeds in gebruik toen het jaar 2000 naderde, zodat elke module in elke toepassing die de korte vorm van jaartal gebruikte moest worden onderzocht.

Een belangrijk aspect van het probleem in Voorbeeld 9 was dat verschillende ontwikkelaars verschillende manieren hadden om de waarden die waren opgeslagen in variabelen die de zes-cijferige datumnotatie gebruikten, te lezen en te manipuleren. Dit vergrootte de inspanning die nodig was om de zogenaamde millennium bug op te lossen. Als de ontwikkelaars een consistente manier hadden gehad om datums te manipuleren die niet afhankelijk was van het opslagformaat, zou de millenniumbug geen punt van zorg zijn geweest.

Cohesie is een manier om te beschrijven hoe nauw de activiteiten binnen een enkele module met elkaar zijn verbonden. Cohesie is een algemeen concept – bijvoorbeeld, een afdeling in een organisatie kan een samenhangend geheel van verantwoordelijkheden hebben (boekhouding, bijvoorbeeld), of niet (diverse diensten). In software systemen voert een zeer samenhangende module één taak uit of bereikt één doel – “doe één ding en doe het goed” is een nuttig motto om toe te passen. Een module moet een enkele logische taak of een enkele logische entiteit implementeren.

Lage koppeling en hoge cohesie zijn concurrerende doelen. Als elke module slechts één ding doet op een laag abstractieniveau, hebben we misschien een complex bouwwerk van sterk gekoppelde modules nodig om een activiteit op hogere abstractieniveaus uit te voeren. Een ontwikkelaar moet proberen het beste evenwicht te bereiken tussen de koppelings- en cohesieniveaus voor een softwaresysteem. Bijvoorbeeld, hotels genereren inkomsten door hun kamers te verhuren aan gasten. Het concept kamer zal waarschijnlijk ergens in het softwaresysteem voor reserveringen voor een hotel vertegenwoordigd zijn. Het kan handig zijn om een module of klasse te gebruiken die het begrip kamer vertegenwoordigt om gegevens te verzamelen en op te slaan over de inkomsten die worden gegenereerd door kamers te verhuren. Een betere oplossing is echter een aparte module voor rekeningen of betalingen, omdat dit meer samenhang vertoont, vooral wanneer een hotel ook op andere manieren inkomsten genereert, bijvoorbeeld uit het serveren van maaltijden aan mensen die geen hotelgast zijn.

Activiteit 5 Verdeel en heers

Timing: Reken op ongeveer 20 minuten.
  • a.Waarom zou je kunnen overwegen om een groot project op te splitsen in kleinere brokken?
  • b.Hoe beïnvloedt de complexiteit van een softwaresysteem de onderhoudstaak?
  • c.Wat is een module?
  • d.Waarom helpt een lage koppeling in een softwaresysteem?
  • e.Geef voorbeelden van het soort informatie dat waardevol zou zijn bij het overwegen van een wijziging in een bepaalde module.
  • f.Wat zijn de contextafhankelijkheden van een module? Hoe verhouden deze zich tot de interface van een module?
  • g.Wat zijn de voordelen van het gebruik van modules met gedefinieerde interfaces?
  • h.Waarom helpt het om een hoge cohesie te hebben in de modules van een softwaresysteem?
  • i.Welke eigenschappen moet een module vertonen die ertoe bijdragen dat deze eenvoudig en goedkoop te ontwikkelen en te onderhouden is, en dat fouten tot een minimum beperkt blijven?
  • j.Waarom is het belangrijk een evenwicht te bereiken tussen koppeling en samenhang?

Antwoord

  • a.Er is een grens aan hoeveel één persoon op een bepaald moment kan begrijpen. Er is dus een grens aan de omvang van een softwaresysteem waar één persoon zich mee bezig kan houden. Door een groot project op te splitsen in kleinere brokken, is het mogelijk een aantal beter beheersbare taken voor de betrokkenen vast te stellen.
  • b.Het is essentieel om een wijziging in een softwaresysteem te kunnen aanbrengen zonder dat men alles van dat systeem hoeft te weten. Elke wijziging wordt moeilijk wanneer de controlestroom en de afhankelijkheden binnen programma’s complex zijn. Hoe groter het aantal en de aard van de afhankelijkheden, des te moeilijker is het om een softwaresysteem te onderhouden.
  • c.Een module is elk aanwijsbaar deel van een softwaresysteem dat afzonderlijk wordt beschouwd. Modules kunnen bijvoorbeeld subroutines zijn (in een procedurele taal equivalent aan methoden), klassen (in een objectgeoriënteerde taal), bibliotheekfuncties of andere constructen die onafhankelijk kunnen worden behandeld.
  • d.Bij een lage koppeling zijn er weinig afhankelijkheden tussen modules. Daarom is het minder waarschijnlijk dat wijzigingen in een deel (een of meer modules) van een softwaresysteem doorwerken in het hele systeem. (Een duidelijk overzicht van de afhankelijkheden tussen modules helpt u bij het voorspellen van de gevolgen van een voorgestelde wijziging van een softwaresysteem.)
  • e.Er zijn twee soorten informatie die bijdragen aan de analyse van een voorgestelde wijziging:
    • Welke modules zijn klanten van de module in kwestie? Deze informatie geeft aan hoe ver een wijziging zich door het softwaresysteem kan verspreiden.
    • Welke aannames zijn gedaan in client-modules van de module in kwestie? Inzicht in de verwachte services van een module helpt bij het inschatten van de risico’s die aan een bepaalde wijziging zijn verbonden.
  • f.De contextafhankelijkheden voor een module zijn de services van andere modules die de module nodig heeft om correct te kunnen werken. U kunt de context afhankelijkheden voor een module uitdrukken in termen van andere interfaces. In feite kunt u de verantwoordelijkheden van een module uitdrukken in termen van zijn interface en context afhankelijkheden. Als de context de diensten levert die de module nodig heeft en de clients voldoen aan de voorwaarden die in de interface zijn gespecificeerd, kan de module de levering van de in zijn interface beschreven diensten garanderen.
  • g.De voordelen zijn als volgt:
    • Ontwikkelaars hoeven alleen te weten wat de interface van de module is (de syntaxis en wat het vereist en bereikt – de semantiek), niet hoe het die diensten levert. Daardoor kunnen ontwikkelaars productiever zijn.
    • Ontwikkelaars kunnen aspecten van het softwaresysteem beter begrijpen, zodat er minder bugs worden geïntroduceerd.
    • Het zou eenvoudiger moeten zijn om bugs te vinden, omdat irrelevante modules worden vermeden.
    • De mogelijkheid van hergebruik van modules wordt vergroot als eenmaal bekend is wat die module biedt en vereist.
  • h.Bij een hoge cohesie voert een module een zinnige reeks bewerkingen of activiteiten uit. Idealiter impliceert een hoge cohesie slechts één grote abstractie per module. De interface abstraheert van wat een ontwikkelaar moet weten om een module te gebruiken. Dit maakt het gemakkelijker voor ontwikkelaars om het doel van de module te begrijpen en hoe ze te gebruiken. Bovendien maakt een hoge cohesie een module meer herbruikbaar in andere toepassingen, omdat het een reeks operaties biedt die op natuurlijke wijze bij elkaar passen.
  • i.Een module moet een lage koppeling en een hoge cohesie hebben, een goede abstractie vertegenwoordigen, en een goed gedefinieerde interface hebben die een ingekapselde abstractie is van een goed begrepen concept.
  • j.Bij het construeren van een systeem kan men de keuze hebben tussen een kleinere set van losjes gekoppelde, minder samenhangende modules, of een grotere set van strak gekoppelde, meer samenhangende modules. In het eerste geval kan elke module moeilijk te begrijpen zijn, terwijl in het tweede geval de relaties tussen de modules over-complex kunnen zijn. U moet een goed evenwicht zien te vinden.

Geef een antwoord

Het e-mailadres wordt niet gepubliceerd.