Joel over Test Driven Development

In de podcast waar o.a. Kent Beck niet zo blij mee was, heeft Joel Spolsky een voorbeeld van een stukje code waar het meer moeite kost om een test eerst te schrijven, dan dat het wat oplevert.

Het gaat over het aanpassen van de jpeg compressie in een stukje remote control software via een toolbar button. Wat hij als test ziet is de actie uitvoeren en het resultaat terug krijgen van een remote machine en dan controleren of twee images gelijk zijn. Veel werk om te automatiseren, maar in mijn vocabulaire heet dit dan ook een integratie test.

Hij zegt zelf dat het enige dat hij hoeft te coderen is dat de button een een bepaalde waarde als parameter mee gaat geven. Ik neem aan dat het geen extra if statement is in een procedure van 100 regels die alles doet, dus begrijp ik niet wat er zo moeilijk aan is om dit te unit testen. Een test hiervoor heb ik ook in om en bij vijf regels code geschreven, afhankelijk van taal en test framework.

En als er toch zo een high coupling is tussen de modules wat het moeilijk maakt, dan is het juist TDD dat ervoor zorgt je de code wat beter modulair opzet. Dat je een betere scheiding krijgt tussen gui en backend. Een andere keer had hij het namelijk ook over een incident waar het veranderen van de menustructuur allerlei testen kapot maakten. Ja dat zijn automatische testen, maar ik durf te wedden dat ze achteraf geschreven zijn. En in dat geval dus niks met het TDD concept te maken.

Anyway, je moet altijd kritisch lezen en luisteren, maar als het gaat om meningen van Joel over zaken die uit de Agile hoek komen, ben ik altijd extra alert.

On 2009-02-25

  • exploring safari 4 beta. it's different. #

On 2009-02-25

  • exploring safari 4 beta. it's different. #

On 2009-02-24

On 2009-02-24

Smalltalk en agile: de feedback loop

Een kenmerk van agile werken is de feedback loop. Door incrementeel steeds iets werkends opleveren, heb je een moment om te evalueren en bij te sturen. De dagelijkse standup meeting zorgt voor een feedback loop per dag en zo kun je steeds fijner gaan.

De feedback loop gaat in Smalltalk door tot het allerlaagste nivo. Als je de applicatie aanpast door code te wijzigen dan zijn deze meteen beschikbaar voor de draaiende applicatie. De applicatie waaran je werkt gaat dus niet down. Je wijzigt het gedrag van bestaande levende objecten en je kunt de veranderingen meteen observeren.

Een voorbeeld is een invulformulier op het web dat uit meerdere pagina's bestaat. Je hebt de eerste pagina gemaakt en gaat het testen. Je vult de pagina in en klikt op 'verder', maar omdat er nog geen tweede pagina is krijg je een debugger. Op dat moment begin je gewoon met het eerste invulveld op je tweede pagina en als die klaar is kun je gewoon 'verder' gaan van de plek waar je gestopt bent met dezelfde sessie en dezelfde instanties van objecten. Klopt het veldje, dan ga je weer verder met de volgende.

Maar werk je dan niet maar een enkele pad uit in de applicatie? Klopt, maar je kunt ook je levende object instanties een bepaalde state geven om in een ander pad van de applicatie te komen. De instantie vraag je op en pas je aan met een scriptje in je workspace:

1
2
3
model := NbvClaimHuisdierenViewModel allInstances last.
model correspondentieNummer: '1234567'. "Ongeldig nummer om validatie tekst op scherm te checken"
model bedrag: 100. "Moet automatisch btw uitrekenen op het scherm"

Deze scriptjes kun je bewaren om steeds in een bekende staat terecht te komen. En zo ga je dus incrementeel verder totdat je aan het eind van de dag een compleet ingevuld formulier kunt submitten.

In talen als java, kan de IDE je wel helpen om automatisch te builden en te deployen als je code hebt aangepast, maar je state raak je steeds weer kwijt dus maak je grotere stappen in een keer om tijd te besparen. Het duurt dan echter wat langer voordat je weet of je goed zit.

Hoe krachtig het concept is wordt geillustreerd in een quote over een moment die de computer industrie heeft verandert, het bezoek van Steve Jobs aan Xerox en de demo van Smalltalk:
One of the best parts of the demo was when Steve Jobs said he didn't like the blt-stye scrolling we were using and asked if we cold do it in a smooth continuous style. In less than a minute Dan found the methods involved, made the (relatively major) changes and scrolling was now continuous! This shocked the visitors, espeicially the programmers among them, as they had never seen a really powerful incremental system before.

The rest is history.

On 2009-02-21

On 2009-02-21

Stackoverflow werkt

De afgelopen week heb ik stackoverflow ontdenkt. Komt een beetje uit de microsoft technologie hoek vandaan, met name van Joel Spolsky en Jeff Atwood, en zal dus meer bekend zijn in de C# community.

Ik was wel onder de indruk hoe snel vragen beantwoordt werden. Binnen een paar minuten kun je op mainstream technologie vragen al antwoord krijgen.

En toen ik vandaag weer eens naar wat moeilijk te vinden info over Monticello zat te zoeken, bedacht ik dat ik de vraag ook op stackoverflow kon stellen. Het duurde een paar uur, maar uiteindelijk kreeg ik wel een bruikbaar antwoord.

Maar wat ik echt super cool vind, is de zichtbaarheid van je vraag. Binnen een uur was het al te Google'en en al makkelijker te vinden dan antwoorden op obscure wiki's en mailinglijsten. Ik denk dat ik de site maar vaker ga gebruiken, ook om vragen te stellen waarvan ik het antwoord al ken. Hiermee bouw ik dan een soort publieke knowledgebase voor mezelf op.

Monticello update scriptje

Ik wordt een beetje gestoord van het klikken in al die browser windows in Smalltalk dus maar een scriptje geschreven om de laatste updates voor Cloudfork binnen te halen.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 
repos := MCHttpRepository
			location: 'http://www.squeaksource.com/Cloudfork'
			user: ''
			password: ''.
MCRepositoryGroup default addRepository: repos.
packages := #(
'Cloudfork-AWS' 
'Cloudfork-ActiveItem-Core' 
'Cloudfork-ActiveItem-Builder' 
'Cloudfork-ActiveItem-Examples' 
'Cloudfork-Squeak-Platform' 
'Cloudfork-Tests-AWS' 
'Cloudfork-Tests-ActiveItem' ).
 
packages
	do: [:package | 
		(versions := SortedCollection newFrom: (repos allVersionNames
                 select: [:versionName | versionName beginsWith: package]))
                 sortBlock: [:predecessor :successor | 
                     predecessor extractNumber <= successor extractNumber].
		(repos loadVersionFromFileNamed: versions last , '.mcz') load]