Modelgedreven ontwikkelstraat in .NET (3): Methodes

 
02 november 2008

Eerder heb ik uitgelegd hoe je op basis van een model gemaakt met behulp van Microsoft DSL Tools klassen met attributen en associaties kunt genereren. Als we echter op een serieuze manier met OO omgaan komen we al snel tot de conclusie dat we ook zaken met betrekking tot gedrag willen modelleren.

Aangezien ik UML class diagrams in deze serie als enige bronmodelsoort beschouw kan ik niet zoveel doen aan gedragsmodellering. Ik kan echter wel zorgen dat mijn in het model gedefinieerde methodes (de operations) worden verreikt door een beetje metadata toe te voegen aan het model. Laten we voor nu uitgaan van het kunnen definiëren van pre- en postcondities voor mijn methoden.

Hiertoe zijn in de DSL een tweetal modelattributen opgenomen: precondition en postcondition. Het meest puristisch en UML compliant zou zijn als ik hierin OCL expressies zou kunnen opnemen. Om het concept te bewijzen kies ik er echter voor om mijn pre- en postcondities in C# te beschrijven. Uiteraard kan er een parser geschreven worden die de expressies vanuit OCL omzet naar C# maar dat bewaar ik voor een andere keer. Wellicht dat “M” of “Oslo” hier iets voor bieden over een paar jaar :).

Ok, eenvoudig grote stappen, snel thuis. Ik kies ervoor mijn pre- en postcondities direct op te nemen in de code, en ik gooi ze netjes om de daadwerkelijke implemenatie heen. Hiertoe neem ik tussen de pre- en postchecking code een aanroep op naar de daadwerkelijk implementerende methode, die ik in dit geval <methodenaam>Impl wordt genoemd. Op basis van bovenstaande instellingen wordt de Work() methode dan als volgt gegenereerd:

public Employee Work(A ctivity activity)
{
if(!(activity != null && this.Activities != null))
throw new Exception(“Precondition of Work not met!”);

WorkImpl(activity);

if(!(this.Activities.Where(a => a.Date == activity.Date).Select(a => a.Duration).Aggregate((x,y)=>x.Add(y))
<=
new TimeSpan(24, 0, 0)))
throw new Exception(“Postcondition of Work not met!”

);

return this;
}

Dit genereert meteen een compilererror:

Error 1 The name ‘WorkImpl’ does not exist in the current context

Vreemd genoeg beschouw ik dat als gewenst gedrag van de omgeving. We hebben immers de methode nog niet geimplementeerd. In feite lopen we nu tegen de grenzen van codegeneratie op; daadwerkelijke methode-generatie zou mogelijk zijn maar weegt in mijn optiek (nog) niet op tegen de flexibiliteit van ouderwets zelf uitcoderen.

We kunnen dit nu doen door de volgende class toe te voegen aan het project:

namespace

sogyo.hrm
{
public partial class Employee
{
public void WorkImpl(Activity activity)
{
this.Activities.Add(activity);
}
}
}
Da’s wel overzichtelijk zo :). In plaats van de honderden regels boilerplate code voor properties, fields en event passing heb ik een heel schone classfile met alleen mijn handgeschreven code. Scheelt veel zoekwerk :).

Voordelen: We hebben een duidelijke plaats voor het ‘managen’ van de pre- en postcondities van onze methodes. Er is een duidelijke plaats waar we iets met formele specificatie kunnen doen, wat te prefereren is boven het valideren met unit-tests achteraf. We kunnen echter deze pre- en postcodities net zo goed omzetten in een aantal validerende tests, dit is triviaal om in een template te gieten.
Tevens hebben we een aangrijpingspunt om metadata toe te voegen voor andere thema’s die betrekking hebben op methodes. Denk bijvoorbeeld aan use-case management of parallele verwerking.

De keerzijde van deze manier van werken is echter synchronisatie van het model met de code. Er is niets dat een ontwikkelaar ervan weerhoudt om een aantal methoden te schrijven die niet in het model staan. Wat dat betreft lijkt een synchronisatiemechanisme hier wenselijk.

Rest nog de download van deze template.


Werken met ?
Kijk dan bij onze mogelijkheden voor starters en/of ervaren IT'ers.


Categorieën: Development

Tags: