Wordt Spekkoper Met Spec#

Momenteel is Spec# (spreek uit Spek-Sjarp) nog in een experimentele fase maar
ik verwacht veel van het Spec# initiatief. Spec# is een ‘laboratorium
experiment’ van Microsoft om code zelfbeschrijvend te maken, zodat ontwikkelaars elkaar behoeden tegen het verkeerd aanroepen ervan.

Als ontwikkelaar is het eenvoudig om een methode te schrijven welke een
hoeveelheid werk uitvoert. Helaas wordt bij het beschrijven van de interface van
de methode (parameters, return waarde, members binnen de class welke aangeraakt worden, etc.) meestal ervan uit gegaan dat de code zelf beschrijvend is. We vinden het heel normaal dat als een parameter de naam index heeft, deze vast wel een waarde zal krijgen tussen NUL en het huidige lengte van een lijst, bv. een array of collection. Bij het doorgeven van parameters By Reference gaan
we er ook vaak vanuit dat deze wel geïnstancieerd zullen zijn. Helaas blijkt dit
in de praktijk vaak tot problemen te leiden waar de gemiddelde ontwikkelaar zijn
schouders bij ophaalt en maar aan het debuggen slaat, alsof dit er bij
hoort.

We hebben allemaal wel eens van pre-condities, invarianten en post-condities
gehoord maar zeg eens eerlijk: Wie test nu echt altijd aan het begin of het
einde van de methode of alle paramaters correct zijn ingevuld? En wie is die
die-hard welke alles met Debug.Assert(); vol hangt? En wie-o-wie test de
unittests op het volledige bereik van de mogelijke aanroepen? Juist, we willen
wel maar wat schieten we er mee op? Ach, het knalt een keer en dan fixen we alle
referenties en het is weer pappen en nathouden. De testers vinden vast nog wel
een null-reference en daarna staat het in productie…

Maar het zou prachtig zijn als we al design-time kunnen aangeven dat een
parameter niet aangeroepen mag worden met een waarde die null is of
buiten een bepaald bereik is. En het zou nog mooier zijn als we binnen een klas
kunnen beschrijven dat een bepaalde property in verhouding tot een andere
property altijd een bepaalde waarde moet hebben (b.v. Position tov. Length). En
als we bij tijdens designtime al gewaarschuwd worden dat we (vrijwel) zeker niet
aan deze condities kunnen voldoen dan het alle dagen feest zijn met ranja en
taartjes en zo…

Dit is dus wat Spec# belooft. Er is momenteel een kleine verzameling klassen
van .Net 2.0 omgezet naar Spec# en daarmee is te zien dat wat hierboven
beschreven is, mogelijk moet zijn via een post compile slag welke de
geïnstrumenteerde code analyseert en verifieert.

Kijk maar eens naar

public void Foo(T index)
{
  if (index == null)
  {
    throw new ArgumentNullException("index", "Sorry,
      geen Null toegestaan");
 }

if ((index.Waarde < 0) || (index.Waarde >= _Length))
{
  throw new ArgumentOutOfRangeException("index waarde" ,
    "Sorry, waarde valt buiten het bereik toegestaan");
 }

  // doe hier je ding
}

Dit kan herschreven worden tot

public void Foo(T! index)  // ! betekent: mag niet null zijn
requires 0<=index && index<Length;     //preconditie
{
  // doe hier je ding
}

Dit is niet alleen een kortere (..) notatie maar het mooie is dat de compiler
dit al tijdens designtime herkent en aan de ontwikkelaar welke de methode
aanroept, kenbaar maakt.

Nu is dit nog maar het begin van de mogelijkheden. Zo wordt het letterlijk
mogelijk om bv. ook invarianten in de code te plaatsen en daar waar tijdelijk
afgeweken moet worden van de validaties, kan dit als sectie in de code aangegeven worden. Maar het mooie is dat we er nu al mee kunnen beginnen 😉

De methode

public void Foo(T/*^!^*/ index)
/*^requires 0<=index && index<Length;^*/
{
  // doe hier je ding
}

compileert al nu uitstekend in .Net (er staat wat commentaar tussen) maar in
de toekomst zal dit ook door de compiler niet als commentaar genegeerd worden.
Straks kan de compiler al designtime de restricties uit het commentaar lezen en
aanbieden aan de aanroepende ontwikkelaar. Dit is dus een investering in de
toekomst welke wel de moeite waard is.

Wat we zullen zien is dat we straks veel minder unittests nodig hebben en dat
ook de testers een heleboel nutteloze testen kunnen overslaan omdat de code al
bepaalde combinaties van parameters afdwingt.

Poets dus je feestmuts alvast op, met Spec# zal code veel stabieler worden
overgedragen en zullen de overwegingen in het hoofd van de ontwikkelaar
eindelijk gevalideerd worden. En daar worden we allemaal beter van.

Klik hier om meer te weten te komen over Spec#

ps: In principe zullen de foutmeldingen niet in de XMLcomments staan omdat ze runtime niet gaan optreden… Dmv. Spec# zal de compiler al de code afkeuren. Dat er een pro/post condities zijn, wordt in de IDE zichtbaar, wellicht wordt dit ook in de XML comments opgenomen.
De leesbaarheid is inderdaad even wennen, maar over schoonheid valt niet te twisten 😉
Er is een en ander NDA rond Spec# dus het zou zo maar kunnen dat (delen van) Spec# in het volgende .Net framework ondersteund worden.