Wednesday, 19 May 2010

The Little Schemer

I just read the first few chapters of The Little Schemer (the first three editions were know as "The Little Lisper"). It's a classic introduction to the Scheme/Lisp language that is written in a very unique style. Instead of lots of long paragraphs of text, it is written in the form of questions and answers (you can find an example chapter on the homepage of the author here). I really like this style, but the opinions are very mixed if you look at the reviews on Amazon. It seems people either love it or hate it, but not much in between.

After only two pages you know what an atom, a list and an s-expression are. Once those basic building blocks have been introduced, the questions gradually build up, letting you learn about car and cdr (getting the first and all but the first elements of a list), and using those primitives to build other list-manipulating functions.
It's not really a full coverage of Scheme the language, as much as it is an introduction to the programming style and culture that defines Scheme.

A very big part of that culture is recursion, which is the emphasis of the book. Recursion seems to come very natural in Lisp: solving problems in the same style would be unreadable in more imperative languages like Java, but are a thing of beauty in Lisp.
I had never really gotten the fascination with recursion, finding the examples often more complicated than simple loop-based ones, but I'm starting to come around on that after reading this book.

The minimal syntax of Lisp is definitely something you need to get used to. It seems like something of a wonder to me that you can write full fledged programs using only round brackets :). I still think that it would be painful to read through lengthy programs written in it, since it seems to be harder to quickly see the structure of the program. But it's probably also something that grows on you.

All in all, it's nice to be introduced to something that is so alien compared to what I use in my daily programming. I'm also very surprised to see how high level Lisp is, considering it has been around since 1958, which to someone my age is still the dark ages :).

Technorati Tags:

Posted by cvf at 11:05 PM in Development

Monday, 3 May 2010

The importance of a fluent interface for building testdata

Today, I was talking to someone about how we made a fluent interface/dsl that allows us to construct data needed for our scenario tests in a readable and maintainable way. This allows us (the developers) to quickly create and understand tests, and even allows us to explain them to a business analyst when discussing a requirement/bug/current behaviour.

He asked me to clarify what I meant with readable, and since talking about code without seeing any is pretty hard, I'm showing an example here.

The core of our datamodel needed for calculating immovable property taxes consists of the following connected entities (a simplification of the real model):
As you can see, that's already quite a bit of data we will need to setup. Since this datamodel is also bitemporal (data has a validity and record dimension to it) and sourced (meaning several sources/reporters can report the same kind of data), setting things up gets complex and verbose very quickly.

This is what a (partial) setup would look like in our raw entity model API:


Person landlord = Person.create();
landlord.getPersonalEvent(Reporter.RR, PersonalEventType.BIRTH)
		.set(new PersonalEvent(PersonalEventType.BIRTH, new Day(7, 6, 1980), Reporter.RR),
				ValidityRange.fromToday());
landlord.getPersonName(Reporter.RR).set(new PersonName("landlord", Reporter.RR));
landlord.getExternalIdentification(Reporter.AKRED, ExternalIdentificationType.AKRED_NUMBER).set(
		Collections.singleton(new ExternalIdentification(ExternalIdentificationType.AKRED_NUMBER,
				"1234567890X", Reporter.AKRED)));
landlord.getOccupiedSpace(Reporter.VLABEL).set(new OccupiedSpace(someSpace, landlord, Reporter.VLABEL));


CadastralArticle article = CadastralArticle.create(someCadastralDepartment, 1);

Collection<RightState> rightstates = CollectionFactory.newList();
RightState rs = new RightState(landlord, 1, new Percentage(100));
rightstates.add(rs);
article.getTimeSlice(Reporter.AKRED, null).set(new TimeSlice(Reporter.AKRED, rightstates),
		ValidityRange.wholeYear(2009));

ImmovableProperty ip = ImmovableProperty.create(someCadastralDepartment, "some-long-code");

Collection<ImmovablePropertyIncome> incomes = CollectionFactory.newList();
ImmovablePropertyIncomeBuilder builder = BuilderFactory.createBuilder(ImmovablePropertyIncomeBuilder.class);
builder.setCadastralIncome(new MonetaryAmount(100));
builder.setFiscalStatus(FiscalStatusType.NORMAL);
builder.setSequenceNumber(1);
builder.setType(ImmovablePropertyIncomeType.NORMAL_BEBOUWD);
incomes.add(builder.build());
ip.getIncomes(Reporter.AKRED).set(incomes, ValidityRange.wholeYear(2009));

// and it just goes on and on

As you can see, that's quite some code to setup the data (and it's just a trivial scenario). Just imagine trying to maintain hundres of testcases written this way. Now, this is what it looks like in our simplified API:

// we need the finals since they're being used in the anonymous inner classes we create.
final Person landlord = new TestPersonBuilder() {
	{
		bornOn(new Day(7, 6, 1980));
		name("landlord");
		eid("1234567890X");
		occupies(someSpace);
	}
}.build();

final CadastralArticle article = new TestCaBuilder() {
	{
		articleNumber(1);
		fullyOwnedBy(landlord);
	}
}.build();


ImmovableProperty house = new TestIpBuilder() {
	{
		plotCode("some-long-code");
		normalIncome(100);
		includedIn(landlordArticle, sequence(1));
		equivalentWith(someSpace);
	}
}.build();

This is already quite a bit more readable, and at the same time offers more functionality. Sane defaults are being used behind the scenes, but you can still override them where necessary. By using these TestDataBuilders (as we called those classes), we've been able to implement hundreds of testcases in a readable and maintainable way, and it was much worth the effort coming up with those.

Technorati Tags:

Posted by cvf at 11:01 PM in Java

« May »
SunMonTueWedThuFriSat
      1
2345678
9101112131415
16171819202122
23242526272829
3031