Aha momenten

November 14, 2006

Ik merkte vandaag weer hoe procedureel we aan het programmeren waren in ons java project. Het komt met name doordat we een applicatie aan het uitbreiden zijn door ant tasks te schrijven. Het zijn in wezen ook sequentiele acties die je achter elkaar uitvoert heb je gauw de neiging procedureel te denken. Voor code reuse gebruiken we dan methodes in utility classes. Ik begin nu in te zien dat dit een code smell is.

We gebruiken bijvoorbeeld een writedocument methode dat een xml DOM document naar een bestand schrijft:

public static void writeDocument(Document doc, File file)
{
    ....
}

Naar wie stuur ik de boodschap als ik deze methode gebruik? Wat stelt util voor? Util stelt niets voor en is gewoon een module zoals we dat met Pascal hebben leren gebruiken. Het is een manier om code te organiseren en niet om iets te modelleren.

Een object georienteerd model zou zijn dat we classes hebben die een DOM document als storage gebruiken welke we kunnen serializen naar het file systeem. Je kunt de writedocument boodschap sturen naar een instantie van deze class. Die weet wat zijn DOM document is en hoe het weggeschreven moet worden. Code reuse vind dan plaats door te generalizeren naar een super class.

Ik zit dan wel nog met het probleem dat je in Java single-inheritance hebt en en dan is zo een generieke super class niet echt geschikt. Je wilt uiteindelijk toch domein objecten hebben en geen generieke objecten waar alles in past. Een OO oplossing in Java zou dan iets met interfaces en dependency injection zijn denk ik. En dan is een util class misschien toch the simplest thing that could possibly work.

Ik begin nu dan ook de elegantie van Ruby mixins te begrijpen. Je kunt hiermee generieke utility functionaliteit toch bij je object onderbrengen. Wat de juiste manier in Smalltalk is moet ik nog uitzoeken, maar ik vermoed dat je met codeblocks functionaliteit kunt injecten in een object, net zoals je met de collection classes doet.

  1. De juiste manier in Smalltalk is om Traits te gebruiken. Bij mijn weten zijn er implementaties voor Squeak (zou standaard in 3.9 zitten) en VisualWorks (is voorlopig nog onstabiel en niet geoptimaliseerd).

    Comment by Robin Barendregt — November 15, 2006 @ 6:55 am

  2. Bedankt voor de tip, ik zal naar Traits kijken. Maar is dit niet al een vrij oud probleem, waar al wat meer “proven” oplossingen voor zijn?

    Comment by soemirno — November 15, 2006 @ 7:33 am

  3. Hangt ervan af wat je bedoelt met “dit”.
    Als je daarmee ‘software composition’ (wat zou dat in het Nederlands zijn? :-) bedoelt, dan is dat zou oud als de informatica zelf.
    Voor Smalltalk zijn er al veel pistes bewandeld. Dan Ingalls heeft ooit een multiple inheritance Smalltalk gemaakt en mixins zijn door verschillende mensen ook al uitgewerkt.
    Traits is eigenlijk ook relatief oud (komt van Lisp begin jaren 80) en, denk ik, een oplossing die elegant is en het best in het conceptueel model van Smalltalk past.

    Comment by Robin Barendregt — November 16, 2006 @ 9:44 am

  4. Met “dit” bedoel ik het patroon om statische util classes te gebruiken voor code reuse i.p.v. de functionaliteit in het object model onder te brengen. Ik merk wel dat het in smalltalk minder vaak voorkomt dan in java.
    Op een of andere manier lijkt het daar makkelijker om het gedrag te generalizeren in een superclass, waarschijnlijk omdat alles open is en in java niet.

    Comment by soemirno — November 16, 2006 @ 6:50 pm

  5. Ja inderdaad. Classes in Java zijn geen first-class objecten, waardoor je o.a. geen class (static) methods kan overerven en men daardoor vaak terugvalt op procedurele gewoontes zoals globale state bijhouden.
    (Sorry dat ik je blogpost in eerste instantie niet grondiger gelezen heb) :-)

    Comment by Robin Barendregt — November 19, 2006 @ 7:46 pm

blog comments powered by Disqus

Get free blog up and running in minutes with Blogsome | Theme designs available here