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]

On 2009-02-20

On 2009-02-20

On 2009-02-16

On 2009-02-16

Named arguments in Java

Named arguments maken je code beter leesbaarder. In Visual Basic kon het, in Ruby kun je het met een hash en in Smalltalk is het gewoon verplicht. In de volgende versie's van C# en Scala komt het ook. In Java zal het wel nooit komen, maar er is wel een manier om het te simuleren in Java.

Wat is het nut van named arguments? Neem als voorbeeld de volgende methode.

1
public void setMargin(int top, int bottom, int left, int right){..};

Bij de aanroep krijg je iets van:

1
setMargins(2,1,2,1);

Zonder de method signature te kennen weet ik niet precies wat de code doet. Met named arguments heb je volgende code:

setMargins(top:=2, bottom:=1, left:=2, right:=1);

Ik hoef nooit te kijken naar de method signature of het uit mijn hoofd te kennen om te begrijpen wat er staat. Maar hoe kunnen we het doen in java. Je kunt simpele syntactic sugar gebruiken door static wrapper methodes te gebruiken:

1
2
3
4
5
6
int top(int i) {return i}
int left(int i) {return i}
int bottom(int i) {return i}
int right(int i) {return i}
 
setMargins(top(2), bottom(1), left(2), right(1));

Dit maakt de code wat leesbaarder, maar het is niet meer dan wat commentaar. En net zoals met commentaar weet je nooit zeker of het echt klopt. Het is nog steeds mogelijk om de volgorde te wisselen en de lezer op een verkeerd spoor te zetten.

Maar wat als elk argument een eigen type heeft i.p.v. een primitive:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public void setMargin(TopMargin top, BottomMargin bottom, LeftMargin left, RightMargin right);
 
static TopMargin top(int i) {return new TopMargin(i)}; 
static BottomMargin bottom(int i) {return new BottomMargin(i)}; 
static LeftMargin left(int i) {return new LeftMargin(i)};
static RightMargin right(int i) {return new RightMargin(i)};
 
class TopMargin{
  int value;
  TopMargin(int i){
    value := i;
  }
 
  int getValue(){
    return i;
  }
}

Het definieren van de classes is wel veel extra werk, maar dit kun je via een template in je IDE laten genereren. Het blijft wel extra code waarin fouten kunnen sluipen. Doordat je constructors niet kunt overerven in Java zal een Margin superclass niet veel helpen in het reduceren van de code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Margin{
  int value;
  Margin(int i){
    value := i;
  }
 
  int getValue(){
    return i;
  }
}
 
class TopMargin extends Margin {
  TopMargin(i){
    super(i);
  }
}

Ik heb deze techniek gebruikt bij het schrijven van JUnit testcases. Ik had daar veel literals als input, maar het was niet goed duidelijk of ik het had over een aantal, een prijs of over kosten.

1
2
buyPhilips(100, 100, 10);
p.setCurrentQuote(createQuote(philips(), 200, 100, 100));

werd dan:

1
2
buyPhilips(amount(100), price(100), costs(10));
p.setCurrentQuote(createQuote(philips(), price(200), lastYearPrice(100), lastQuarterPrice(100)));

Het is nu duidelijk waar de argumenten voor staan en het is ook typesafe.

On 2009-02-13

On 2009-02-13

On 2009-02-11