# Subprogramma

In de informatica is een subprogramma of subroutine (soms ook functie, procedure of routine genoemd) een duidelijk afgebakend programmablok met een eigen naam binnen een computerprogramma, dat elders in het programma aangeroepen (uitgevoerd) kan worden. De naam die aan subprogramma's wordt gegeven kan afhangen van de gebruikte programmeertaal.

## Onderscheid tussen procedures en functies

Sommige programmeertalen, zoals Pascal en PL/SQL, maken onderscheid tussen procedures en functies; een functie is dan een speciaal geval van een procedure, die één resultaatwaarde retourneert aan het aanroepende programma. Ze worden vooral gebruikt voor het implementeren van wiskundige functies.
In andere talen, zoals C en Scala, worden alle subroutines functies genoemd, ook als ze geen waarde retourneren. Ze retourneren als het ware een leeg type, bijvoorbeeld void of Unit.
In functionele talen worden (vrijwel) alleen functies in de wiskundige zin gebruikt. In zuiver functionele talen als Haskell en Clean kunnen deze functies zelfs geen neveneffecten veroorzaken.
In objectgeoriënteerde programmeertalen worden procedures en functies methodes genoemd indien ze binnen een object gedefinieerd zijn. Ze zijn met dat object gebonden en worden aangeroepen met een prefix die link aangeeft naar het object en zijn methode.

## Redenen om een subprogramma te gebruiken

Er zijn verschillende redenen om een subprogramma te gebruiken:
* om redundantie te vermijden, Don't Repeat Yourself (DRY) principe;
* om code in meerdere programma's en toepassingen te kunnen hergebruiken, Single-Point-of-Definition;
* om de complexiteit van een programma in kleinere, beter beheersbare delen te kunnen opsplitsen;
* om de leesbaarheid van een programma te verbeteren;
* om een deel van een programma te verbergen of beschermen.

## Parameters en returnwaarden

Veel programmeertalen faciliteren het doorgeven van gegevens tussen het aanroepende programma en het subprogramma. Deze gegevens worden vanuit het aanroepende programma aan het subprogramma doorgegeven als parameters. Hierbij wordt onderscheid gemaakt tussen invoer- en uitvoerparameters. Invoerparameters geven alleen waarden aan het subprogramma door. Uitvoerparameters geven data vanuit het subprogramma terug aan het hoofdprogramma. Meer strikte talen als C# kennen een aparte type waarin de parameters beiden kunnen zijn, andere talen gebruiken de uitvoerparameters tevens als invoerparameter.
Over het algemeen gesproken zijn er drie mechanismen van het doorgeven van parameters aan subprogramma's:

### pass by value

    Bij dit mechanisme wordt, in de aanroep van een subprogramma, voor iedere formele parameter van het subprogramma een uitdrukking in de zin van de programmeertaal opgegeven. Tijdens het uitvoeren van het programma wordt, bij aanroep van het subprogramma, die expressie doorgerekend. De waarde van die expressie wordt dan als initiële waarde van de formele parameter doorgegeven aan het subprogramma. Een duidelijk kenmerk van dit mechanisme ten opzichte van andere mechanismes is dat als de expressie bestaat uit een programma-variabele, de waarde van die variabele doorgegeven wordt aan het subprogramma maar de variabele zelf niet. Wat het subprogramma ook met die waarde of de formele parameter doet, heeft geen effect op de waarde van de programma-variabele.

### pass by reference

    Bij dit mechanisme wordt een formele parameter van het subprogramma een synoniem voor een variabele van het hoofdprogramma. Kenmerkend voor dit mechanisme is dat ieder verandering aan de formele parameter in het subprogramma ook direct een verandering is aan de waarde van de doorgegeven variabele. De meeste talen die dit mechanisme gebruiken, stellen verplicht dat wat er doorgegeven wordt aan het subprogramma als parameter een muteerbare variabele is en niets anders.

### pass by name

    Bij dit mechanisme wordt, bij aanroep van een subprogramma, de referentie van een waarde doorgegeven. Tijdens het uitvoeren van het programma wordt in de programmatekst van het subprogramma de formele parameter vervangen door de doorgegeven variabele- of functienaam. Hiermee wordt de kans geschapen dat de evaluatie later of zelfs helemaal niet wordt uitgevoerd. Dit is analoog aan de callback parameter in sommige talen. Een typisch gebruik is in het facultatief doorgeven van loggegevens. Wanneer geen loggegevens gevraagd worden, worden er ook geen onnodige evaluaties gedaan.
Soms wordt er gebruikgemaakt van een combinatie van mechanismen, of van een neveneffect van een mechanisme waardoor meer dan één waarde doorgegeven wordt. De Java-taal bijvoorbeeld kent als typen voor programma-variabelen een aantal basis-typen en verder de "object referentie"; variabelen van dit type zijn doorzichtig en worden in de taal feitelijk behandeld alsof het de objecten zijn waarnaar zij verwijzen. Daarnaast kent Java als parametermechanisme pass by value. Wordt echter de waarde van een object referentie doorgegeven, dan wordt natuurlijk feitelijk ook dat object doorgegeven -- alsof het pass by reference was. Men zou dit mechanisme zoiets als "pass by reference-value" kunnen noemen.
Bij subprogramma's wordt soms onderscheid gemaakt in de waarden die geretourneerd worden na een aanroep. Sommige talen kennen alleen subprogramma's met een resultaat-waarde, sommige talen kennen alleen subprogramma's zonder, weer andere talen kennen een combinatie.

## Gezond programmeren

Vanuit het oogpunt van gestructureerd programmeren gelden verschillende vuistregels bij het schrijven van subroutines.
* Allereerst dienen zowel de procedure zelf als de parameters self-documenting names, dus zichzelf verklarende namen te hebben.
* Een subroutine hoort één en slechts één taak uit te voeren. Wanneer er twee taken zijn, breng deze dan in twee subroutines onder.
* Een subroutine dient evenals elk programma slechts één ingang en één uitgang te hebben.
* Een subroutine heeft strong cohesion en weak coupling, dat wil zeggen dat de elementen binnen de subroutine een sterke samenhang vertonen en naar buiten toe slechts weinig raakvlakken hebben.

## Recursie

Sommige talen staan toe dat subprogramma's zichzelf aanroepen. Dit verschijnsel wordt recursie genoemd. Het is belangrijk dat er in het subprogramma een voorwaarde geldt voor de recursieve aanroep, om te voorkomen dat een subprogramma, door zichzelf aan te roepen, in een oneindige lus terechtkomt. De voorwaarde waaraan moet worden voldaan om de recursie te laten eindigen wordt wel de stopconditie genoemd.