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.