Gestructureerd programmeren

Gestructureerd programmeren kan worden gezien als een subdiscipline van procedureel programmeren, een van de belangrijke programmeerparadigma's, en waarschijnlijk het populairste, voor het programmeren van computers. De programmeur beperkt zich in dit concept in de programma afloop tot de vier basis controlstructuren en past het concept abstractie consequent toe, dat wil zeggen het vermijden van lange programmablokken door het veelvuldig, hiërarchisch toepassen van relatief kleine subroutines.

Geschiedenis

Het werd in de jaren zestig langzaamaan duidelijk dat de omvang en complexiteit van computerprogramma's uit de hand begon te lopen. Softwareontwikkelaars zagen door de bomen het bos niet meer. Gestructureerd programmeren en bijvoorbeeld de watervalmethode werden ontwikkeld om daar iets tegen te doen.

Goede programmeurs wisten door gestructureerd te werken code te produceren, die veel gemakkelijker was te doorzien en waarvan de correctheid eenvoudiger was aan te tonen. Het viel op dat bekwame programmeurs vooral veel minder spronginstructies, dus veel minder GOTO-statements, gebruikten en veelvuldig gebruik maakten van subroutines. Wetenschappers in de informatica, waaronder Niklaus Wirth, Edsger Dijkstra en Michael A. Jackson, zagen de oplossing in het gestructureerd programmeren, waarbij het door het gebruik van nieuwe constrolestructuren in programmeertalen onnodig zou worden om de onoverzichtelijke sprongopdrachten te gebruiken en de leesbaarheid van de code veel beter werd.[1]

Dijkstra probeerde daarbij correctheidsbewijzen van programma's te leveren. Hij is hierin gedeeltelijk geslaagd. Daarnaast werd beoogd parallel werken in grote teams aan grote projecten mogelijk te maken. Dit is door deze aanpak wel gelukt. Een gestructureerde aanpak leidt ook tot software waarin functies meer afzonderlijk van elkaar zijn gebouwd. Dit maakt onderhoud, zowel correctief als adaptief, aanzienlijk eenvoudiger en minder risicovol.

Als alternatief voor het stroomdiagram werd het programmastructuur-diagram, ook wel het Nassi-Shneiderman-diagram, bedacht. De restricties hiervan werken in het voordeel van het programmeren, het zijn dezelfde restricties die men moet hanteren met gestructureerd programmeren.[2]

Het gestructureerde programmeren leidde tot een nieuwe generatie programmeertalen. Vrijwel al deze talen kennen de spronginstructie en het label, het regelnummer in een computerprogramma, nog wel, maar het gebruik ervan wordt sterk afgeraden en bemoeilijkt door extra declaratieverplichtingen.

De essentie van gestructureerd programmeren

De vier basis controlstructuren in gestructureerd programmeren zijn:

  • sequentie = opeenvolging - (S1 S2)
  • selectie = keuzestructuur - (if B then S1 else S2)
  • repetitie of iteratie = herhaling, met de herhalingsvoorwaarde voor- of achteraf - meestal (while B do S) en (do S until B)
  • recursie = het steeds aanroepen van een subprogramma door zichzelf, totdat een eindconditie wordt bereikt

Hierbij staat S voor een opdracht, van Statement, en B voor een logische expressie, Boolean. Belangrijk is hierbij dat zowel een opdracht als een logische expressie willekeurig complex mag zijn. Dat is in programmeertalen voor opdrachten gerealiseerd door begin…end-constructies:

De toepassing van het concept van abstractie en daarmee van de subroutine is ten slotte een essentieel onderdeel van de gestructureerde aanpak.

Enkelvoudige keuzestructuur

Bij een keuzestructuur wordt een bepaald stuk code, afhankelijk van een voorwaarde, al dan niet uitgevoerd door de computer.

structuur beschrijving
if v then xxx xxx wordt alleen uitgevoerd als aan de voorwaarde wordt voldaan
if v then xxx else yyy als aan de voorwaarde wordt voldaan, wordt xxx uitgevoerd, zo niet wordt yyy uitgevoerd
if v1 then xxx elseif v2 ... als niet aan de eerste voorwaarde voldaan wordt, worden vervolgacties afhankelijk van een tweede voorwaarde
voorbeeld van een if
 <?
 $humeur = "slecht";
 if ($humeur == "slecht") {
   echo ("ik ben slechtgehumeurd");
 }
 ?>
voorbeeld van een elseif
 <?
 $humeur = "goed";
 if ($humeur == "slecht") {
   echo "ik ben slechtgehumeurd";
 }
 elseif ($humeur == "verveeld") {
   echo "ik verveel mij";
 }
 else {
   echo "ik ben goedgeluimd";
 }
 ?>

Meervoudige keuzestructuur

Bij een meervoudige keuzestructuur, of: switch, kan op verschillende waarden worden gereageerd. Dit kan ook worden geïmplementeerd met een aantal enkelvoudige keuzestructuren, en de kans is groot dat daar dan elseif-statements in voorkomen, maar met een switch gaat het eenvoudiger:

 <?
 $humeur = "goed";
 switch ($humeur) {
 case "slecht":
   echo "ik ben slechtgehumeurd";
   break;
 case "verveeld":
   echo "ik verveel mij";
   break;
 default:
   echo "ik ben goedgeluimd";
 }
 ?>

Voorwaardelijke herhalingsstructuur of iteratie

Als statements voorwaardelijk herhaald moeten worden zijn er twee mogelijkheden:

  • eerst testen, daarna de opdracht uitvoeren en vervolgens opnieuw testen, en eventueel de opdracht uitvoeren, opnieuw testen enzovoorts
  • eerst de opdracht uitvoeren, daarna testen, eventueel de opdracht herhalen, opnieuw testen enzovoorts.

In het eerste geval kan het zijn dat de opdracht helemaal nooit wordt uitgevoerd, geen herhaling of meer keren, in het tweede geval wordt de opdracht minimaal één keer uitgevoerd.

PHP-voorbeeld van eerste mogelijkheid
 <?
 $teller = 0;
 while ($teller <= 12) {
   echo "de teller zit nu aan: $teller <br />";
   $teller++;
 }
 ?>
PHP-voorbeeld van de tweede mogelijkheid
 <?
 $teller = 0;
 do {
   $teller++;
   echo "de teller zit nu aan: $teller <br />";
 } while ($teller <= 12);
 ?>

Abstractie en subroutines

Subroutines zijn opvraagbare eenheden zoals procedures, functies of methoden die worden gebruikt om naar een reeks instructies te verwijzen door een enkele instructie: de call-instructie. Call-instructies roepen een subroutine aan.

Het hiërarchisch gebruik van het concept van de subroutine is te vergelijken met het concept van abstractie in de systeemtheorie. Door het samenbouwen van vele subprogramma's kunnen toch betrouwbare en complexe informatiesystemen worden gebouwd, omdat ze uit van elkaar geïsoleerde subprogramma's zijn opgebouwd, die afzonderlijk kunnen worden gebouwd en getest. Op deze wijze worden gedetailleerde datastructuren, algoritmes en bewerkingen verborgen gehouden voor programma's op hogere systeemniveaus. Dat heet data-hiding of encapsulation.

Edsger Dijkstra wees als eerste in augustus 1969 op de noodzaak van deze aanpak vanwege de beperkte vermogens van de menselijke geest:

"Het is onmogelijk om de correctheid van een programma van vele pagina’s te doorgronden."

Hij pleitte er daarom voor om computerprogramma's en hun subroutines altijd in omvang te beperken en van een heldere, goed afgebakende, bij voorkeur enkelvoudige functionaliteit te voorzien. Later is dit concept van abstractie en gebruik van subroutines terecht gekomen in de objectgeoriënteerde aanpak, waarbij subroutines vervangen zijn door methods, die op objects en classes werken.

Ole-Johan Dahl, E.W. Dijkstra en C.A.R. Hoare publiceerden in 1972 gezamenlijk een boek waarin de basisprincipes van programmacorrectheid, gestructureerde data, programma hiërarchie en lagen van abstractie fundamenteel werden behandeld. Het denken in klassen met data hiding en encapsulation werd hierin geïntroduceerd. Deze drie vroege informatici hebben daarmee de basis gelegd voor alle latere wetenschappelijke en commerciële werken over gestructureerd programmeren en de object georiënteerde aanpak.