Smalltalk IO

Continuing on my own personal Smalltalk Renaissance, I spent some time investigating threading, IO, and general long-running operations. First a small rant. There is a woeful lack of documentation out there on how threading works (or doesn’t) in Smalltalk. The stuff I did find did not fill me with confidence, as it seemed to indicate that Smalltalk was inherently single-threaded, and thus crippled when it comes to doing network IO. In the end I decided to just try it. This is what I came up with:

| httpClient request response |
httpClient := HttpClient new.
request := HttpRequest get: 'http://www.cincom.com'.
Transcript show: 'Before Request'; cr.
response := httpClient executeRequest: request.
Transcript show: 'Request Complete'; cr.
Transcript show: response body decodedValue.
Transcript show: 'After Request'; cr.

Sure enough, the whole environment froze while waiting for the request to complete. Game over.

Then I finally decided to actually look at the core libraries, and happened upon the BlockClosure class, with the promising looking ‘fork’ method. Hmm. My second attempt looked like this:

| httpClient request response |
httpClient := HttpClient new.
request := HttpRequest get: 'http://www.cincom.com'.
Transcript show: 'Before Request'; cr.
[
response := httpClient executeRequest: request.
Transcript show: 'Request Complete'; cr.
Transcript show: response body decodedValue.
] fork.
Transcript show: 'After Request'; cr.

Note the addition of the [ ] around the code that actually hits the network. This denotes a block, which is in fact an instance of BlockClosure, which brings the ‘fork’ method call into play. Sure enough, the second attempt did not freeze the whole environment, and I saw ‘Before Request’ immediately followed by ‘After Request’ in the system transcript. Shortly followed by the html from Cincom’s homepage.

Smalltalk rocks.

We’re all wrong

The software industry migration away from Smalltalk to Java and .Net may be one of the greatest causes of lost developer productivity, although its impossible to quantify. I’ve never developed Smalltalk commercially, but I have played with it on numerous occasions, and the more I see, the more I like. It really was a language before its time.

Take for example, the hooking a GUI to a domain layer. You want a simple way to uniformly hook the UI to the domain layer, without leaking UI code into the domain objects. The Smalltalk way is this:

| aspect |
aspect := AspectAdaptor subject: aDomainObject.
aspect accessWith: #getSelector assignWith: #putSelector

The above code says: create an instance of the AspectAdapter class, assign it to a variable called aspect, and wrap it around the object referred to by the aDomainObject variable. Whenever you receive a request for data, call the ‘getSelector’ method of aDomainObject. Whenever the UI value is updated by the user, pass the new value to the ‘putSelector’ method of aDomainObject. As getters and setters in Smalltalk generally follow a convention, there’s an even shorter way of writing the same thing:

| aspect |
aspect := AspectAdaptor subject: aDomainObject.
aspect forAspect: #iFieldName

Smalltalk is chock full of things like this, things that we threw out when we moved in favour of strongly typed, C-based languages.

Spaces on a shoestring

What if an application used an irc channel as a (Java)Spaces implementation mechanism? That would be cool. Persistence could be manged by an IRC bot running on the server (or, indeed, any node) that logged all the messages.

Encryption? Any standard mechanism (RSA, blowfish etc) plus base64 encoding should take care of that.

Wonder if anyone’s implemented this idea yet?