Tuesday, 13 January 2009
The Socratic Method
In this context, Garlikov is attempting to teach a third grade class about binary arithmetic by asking only questions and allowing the children to work out the answers themselves. A major part of the article is a transcript of this class, which lasted only 25 minutes and apparently resulted in 19 out of 22 students having "fully and excitedly participated and absorbed the entire material".
The article is a quick and inspiring read and I suggest you take a look. I sometimes think it would be nice to volunteer to work with a group of school children (eToys maybe?) and this would be an interesting approach to play with.
There is also a letter to his daughter with further details on Plato and the Socratic Method. If you are at all interested in pedagogy or philosophy, you might also want to check out some of his other articles. I seem to recall finding the article about mistakes made when teaching math interesting.
Monday, 12 January 2009
First Sprint of 2009
Among other things, we added the ability to configure the new session cache, removed our dependency on MessageSend, standardized on the ANSI exception handling protocol and made sure we were signaling meaningful errors.

We also got a shiny new Control Panel implemented in OmniBrowser (see image to the right). There will be more features coming in this area.
Lukas was cleaning up the FileLibrary code on the train on the way here but lost most of it when his image suddenly crashed and ended up only 4MB in size.
I still need to look at some package dependency issues and Philippe and Lukas are working on the ability to add cookies during the callback phase and related bugs.
All in all, a very productive two days!
Wednesday, 7 January 2009
Object Initialization
- What should you call a new parameterized initialization method?
- How should a subclass with one of those make sure its superclass is initialized?
- How should class-side instance creation methods work?
- How do you make sure inherited instance creation methods don't result in partially initialized objects?
- What if someone else has made subclasses of yours and is already overriding your superclass' initialization method?
- Each object must be initialized once and only once.
- During initialization, all initialization methods must be called in a predictable order. If my subclass has already overridden my superclass' initialization method, it should still be called. (This means a method should never call super with a selector other than its own).
- All inherited instance creation methods must result in a completely initialized object.
- The conventions must be consistently applicable in all cases.
- It should be very clear to users of the class what parameters are required for initialization.
- It is more important to minimize the complexity and effort for users of the framework than for developers of the framework.
- Without sacrificing the above points, we should not have to write or override more code than necessary (we don't want to have to override every instance creation method each time we subclass, for example).
Monday, 29 December 2008
Seaside 2.9: Exception Handling
Ok, I promised well over a month ago to start documenting some of the new bells and whistles in the Seaside 2.9 Alpha series. I thought I'd start things off with a discussion of the new exception handling mechanism.
Have you ever wanted to customize the look of Seaside's error pages? Want to send yourself an email whenever an exception is raised? Maybe save a copy of the image on errors so you can look at the stack later? It has been possible for ages to implement a custom error handling class for your Seaside application but the process was not necessarily obvious and you were limited to catching subclasses of Warning and Error. In the upcoming Seaside release, we have cleaned up the exception handling code to really simplify the error handlers that come with Seaside and to make your custom handlers simpler and more flexible.
Basic Usage
To create your own exception handler, the first question is what class to use as your superclass. If you are just interested in customizing the appearance of error pages or performing some additional action when an error occurs, you probably want to subclass WAErrorHandler. If your requirements are more complex, you may want to subclass WAExceptionHandler directly (see Advanced Usage below).
Subclassing WAErrorHandler
WAErrorHandler is already configured to handle Error and Warning and is a good starting point if you don't need to drastically change the error handling behaviour. In your custom subclass, you can implement #handleError: and #handleWarning: to define the behaviour you want in each case. The methods take the exception (either an Error or Warning respectively) as a parameter and should ultimately either resume the exception or return an instance of WAResponse. By default, both methods call #handleDefault: so you can provide common implementation there.
For example, assuming you had defined a routine to notify yourself of errors by email, you could provide an implementation like this:
handleError: anError
self notifyMeOfError: anError.
^ WAResponse new
internalError;
contentType: WAMimeType textPlain;
nextPutAll: 'Eek! An error occurred but I have been notified.';
yourself
Returning an HTML Response
You could of course provide an HTML response but you would want to make sure your HTML is valid (and that means a head, a title, a body, etc.):
handleError: anError
^ WAResponse new
internalError;
nextPutAll: '<html>
<head><title>Error!</title></head>
<body><p>An error occurred</p></body>
</html>';
yourself
If you want to use the Canvas API, you can subclass WAHtmlErrorHandler instead. Just implement #titleForException: and #contentForException:on: (it gets passed the exception and a canvas) and you're done.
Using Your Exception Handler
Once you have written your exception handler, you need to configure your application to use it. Open your web browser and navigate to the Seaside configuration page for your application. There you will find a preference called 'Exception Handler' and you should be able to choose your new class from the list.
Alternatively, from a workspace, execute something like:
(WAAdmin defaultDispatcher entryPointAt: 'myapp')
preferenceAt: #exceptionHandler put: MyHandlerClass
Advanced Usage
If your needs are more complex than the above, you may want to subclass WAExceptionHandler directly. An exception handler needs to do two things:
- choose which exceptions to handle
- define how to handle them
Selecting Exceptions
The easiest way to select which exceptions to handle is to implement #exceptionSelector on the class-side of your new handler (note: in Seaside 2.9a1 this method is named #exceptionsToCatch). Your #exceptionSelector method should return either an ExceptionSet or a subclass of Exception. You probably want to continue handling the exceptions handled by your superclass so your implementation might look like:
exceptionSelector
^ super exceptionSelector, MyCustomError
If your needs are somehow more complex, look at implementing #handles: and #, yourself on either the class- or instance-side, as appropriate (note: these two methods do not exist in Seaside 2.9a1).
Handling Exceptions
When an exception is signaled and your handler indicates (via #handles:) that it wishes to handle the exception, #handleException: is called and passed the signaled exception. To define your exception handling behaviour, simply implement #handleException: on the instance-side of your handler. Note that the same handler instance is used throughout a single HTTP request even if multiple exceptions are signaled.
The #handleException: method is expected to return a WAResponse object. It may also choose to resume the exception, cause the Request Context stored in its requestContext instance variable to return a response (by using #redirectTo: for example), or otherwise avoid returning at all; but if it returns, it should return a response.
Internal Errors
WAExceptionHandler also provides a class-side method called #internalError:context:. This method creates a new instance of the handler and calls #internalError:, which should generate a very simple error message. This method is used whenever the exception handling mechanism itself signals an error as well as any other place in the system where we cannot be certain that a more complex error handler will succeed. This method should not do anything that has potential to raise further errors.
Setting Up an Exception Handler
Exception handling for Seaside applications is set up by WAExceptionFilter (more information on filters in a later post) and you do not need to do anything else if you are using WAApplication and WASession. If you are implementing your own request handler, however, and want to use the exception handling mechanism, you will need to set up an exception handler yourself.
Although you could do everything yourself, the easiest thing is to call #handleExceptionsDuring:context: on your handler class, passing it the block you want wrapped in the exception handler and the current WARequestContext object. You can look at RRRssHandler for an example.
Examples
The Seaside distribution includes a few exception handlers that you can look at for examples of usage. Beware of WADebugErrorHandler and WAWalkbackErrorHandler, though, as they do crazy things to get debugging to work the way we want in Squeak; although they are well commented and may be interesting to look at, they are probably not good examples of general usage. The Seaside-Squeak-Email package includes WAEmailErrorHandler, an abstract class that can be subclassed and used to send an email whenever an error occurs.
Monday, 15 December 2008
Christmas giving
Thursday, 11 December 2008
The will of the people
So best I can tell, when the Governor General does allow the opposition to take power without an election there is noise, controversy and eventually change so it cannot happen again. And when the Governor General does not give power to the opposition then history seems to just continue along. I guess I must have missed McArthur's convention.Perhaps this is nitpicking, but we're not talking about the Governor General giving power to the opposition; we're talking about the Governor General giving power to a new coalition, one with the support of the majority of parliament.
Now I agree that the Governor General has this option but certainly no obligation to choose it. On the other hand, I still can't fathom why we would want another election right now: Canadians elected 308 MPs to represent them and if the majority of them want a change in parliament then that is the will of the people, particularly this soon after an election. The incessant cries of Canadians who seem to think they live in an the US and therefore elected the Prime Minister are driving me nuts.
I also disagree that the Governor General has lost her authority to act against the will of the Prime Minister. By convention, she normally follows the advice of the Prime Minister, but, at least as far as I'm concerned, this is only in his role as the head of parliament. The Prime Minister in Canada is not a political office; he does not have any special privileges and should not; the Governor General is bowing to the will of the people (as represented by their elected MPs in parliament), not to the Prime Minister.
Tuesday, 28 October 2008
One, Two, cha-cha-cha
I've been wanting to take ballroom lessons for years (at least since my first friend got married). We just need to practice enough to let muscle memory kick in; I think there's some worry from my better half that I'll be scheduling nightly drills so I'll have to control myself.