Tijdregistratie in Squeak

Ik ben begonnen met een tijdregistratie tool in Squeak. Het heeft nog geen gui en alleen image persistence, maar ik kan er al mijn uren in bijhouden via scripts in de workspace. Het begon als een pet project om de concepten van TDD aan collega's uit te leggen. Ik maakte wat CRC cards en begon wat te spelen met de verantwoordelijkheden en interactie tussen objecten. Daarna ging ik verder met Java en junit, maar het vlotte niet echt. Een gegeven moment wilde ik wat mock'en en toen realiseerde ik me dat ik weer eerst interfaces moest definieren. Is dan wel weer veel werk, zeker als je iemand nog de beginselen van TDD wilt bijbrengen. Dan maar geen mock testen. Toen kwam het moment dat ik met datum en tijd moest werken en toen merkte ik dat ik me liet leiden door de Java calendar en date api. Dat was niet de bedoeling, ik moest wel aan het stuur blijven.

Waarom niet Squeak weer eens proberen dan, alles heeft tenslotte zijn oorsprong in Smalltalk. Van de gui waarmee de hele wereld dagelijks werkt, tot aan de Java virtual machine. TDD heeft inderdaad ook zijn roots in Smalltalk en je merkt al gauw waarom. In Smalltalk kun je je testen volledig schrijven en zelfs uitvoeren zonder maar ook een regel implementatie code te hebben geschreven. In Java krijg je al in je code editor allerlei meldingen als een methode nog niet bestaat en dat moet je leren negeren of je moet steeds even een lege stub implementeren, zodat de meldingen weggaat. In beide gevallen leid het af. En omdat Smalltalk dynamic typed is hoef je tijdens het schrijven van de testen nog niet te focussen op types of classes, maar alleen op het gedrag van de objecten. De bottomline is dat je echt in ontwerp modus zit, en niet in implementatie modus.

Mijn fixtures setup:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
setUp
  |period |
 
  thisWeek := Week starting:  (DateAndTime year: 2008 month: 5 day: 11).
 
  nextWeek := Week starting:  (DateAndTime year: 2008 month: 5 day: 18).
 
  period := Timespan 
	    starting: (DateAndTime year: 2008 month: 5 day: 15) 
	    duration: (Duration hours: 2).	
 
  codingWork := Action during: period describedAs: 'some coding work' for: '1234'.
 
  studying := Action during: period describedAs: 'study smalltalk' for: 'myself'.
 
  james := Employee new.
  james register: codingWork.
  james register: studying.

Maar ook tijdens implementatie zijn er gemakken. De libraries in Smalltalk zijn uitgebreider en simpeler te gebruiken. Er is een hele chronology package in Squeak voor datum en tijd gerelateerde zaken. De Timespan en de Week class zijn precies wat ik nodig heb voor mijn tijdregistratie. In Java had ik zelf wat moeten maken met de Calendar en Date api's.
Ook de collections in combinatie met closures zijn een genot om mee te werken. Het selecteren van werkzaamheden gedaan in een bepaalde week, doe ik in een paar regels code.

De selectie van werkzaamheden uit een bepaalde week:

1
2
workdoneDuring: aWeek
  ^ allWorkdone select: [ :workdone| workdone isInWeek: aWeek ].

Workdone bepaalt zelf of het in de geselecteerde week zit:

1
2
isInWeek: aWeek 
  ^ timespan between: (aWeek start) and: (aWeek end).

Ik schat zeker een factor 10 minder code dan in Java. In het tweede stuk ben ik wel afhankelijk van library functionaliteit. Als ik in Java een Timespan en Week class zou implementeren zou het waarschijnlijk net zoveel code zijn.

De Java versie zal ik uiteindelijk ook nog maken, omdat ik daarin het TDD verhaal moet uitleggen. Ben echt benieuwd op hoeveel regels code ik meer moet schrijven.
Deze Squeak versie wil ik nog uitbreiden met een frontend in Seaside en wat betere persistence dan de image.