21/08/2008

Exception handling - oh, that's how it works

The general idea behind exception handling is that you assume everything works, and so you don't check return values.

Using ifFalse: instead of ifTrue: as a guard clause

Smalltalk by Example advocates returning using an ifFalse test that returns self rather than an ifTrue test that then executes your code. For example doing this:


MyClass>>someMethod
(some condition) ifFalse: [^self]
self doThingOne.
self doThingTwo.
self doMoreLinesOfCode]

instead of:


MyClass>>someMethod
(some condition) ifTrue:
[self doThingOne.
self doThingTwo.
self doMoreLinesOfCode]


I don't think I understand this properly yet. There is something odd about asking, for example a list to do something, and for the return result to be the list. I am not sure how my coding would cope with that, i.e. rather than getting a failure message or something like that. More pondering required.

How should you name your methods and what should they return

Kent Beck's book on design patterns for smalltalk has some very useful rules about this. However, there are quite a few of them, and I have yet to commit them all to memory!

In the meantime, this section from Smalltalk By Example, seems really helpful. I am going to make sure any of my methods follow these rules - if only to avoid confusing myself further.


Often the method name will tell you what type of object will be returned. For example, method names that start with is will usually return a Boolean, true or false. For example,isEmpty,isNil. Messages that start with as will usually return the thing specified. For example,asSortedCollection sent to a collection will return aSortedCollection. The asNumber message sent to a string will return a number of the appropriate type. (However,asString is not implemented by numbers so you should use printString or displayString instead.)

Methods that add objects to collections, such as add: and at:put:, return the object that is added. Methods that remove single objects from collections, such as remove: and removeFirst, return the object that was removed. Because of this it's worth knowing about the yourself message. The following example illustrates how the use of yourself ensures that collection contains the list rather than the last object added


collection := List new 
add: thisObject;
add: thatObject;
yourself.


Consistency and predictability are great virtues, so when adding these types of methods to your own classes, follow the common usage patterns. Otherwise you'll confuse every programmer who looks at or uses your code.

More words of wisdom from The Joy of Smalltalk

I found the following points to be really useful:

We will now evaluate the desirability of the selected nouns as classes:
  • Address. If the address included the name of the city, postal code, province or state, and other information, we would implement it as a class. As it is, an address is just a string of alphabetic and numeric characters and strings are already in the library. We thus remove Address from our list of candidates.

  • Apartment. Yes, we will implement this concept as a new class because it represents an object that holds a lot of apartment information together and no related class exists in the library. The class will be called Apartment and we will decide shortly what exact meaning it will have.

  • Building. Another and non-trivial object that does not have a counterpart in the library and will have to be implemented. The class will be called Building.

  • File. The concept of a file is implemented in VisualWorks library and does not require a new class.

The reason I found this so helpful is that it provides some really useful heuristics for object modelling. If what you are trying to store exists as a simple object, e.g. a string for address, then don't bother creating a new class. If, on the other hand, it is a more complex 'type', AND, you can't find an existing object that will do. Create a new one.

Blindingly obvious and really helpful

20/08/2008

Digging into methodologies

Given that I really wanted to get into writing some Smalltalk, I seem to be spending a lot of time just reading stuff on the internet! However, it is all proving very interesting.

I downloaded Ivan Tomek's Joy of Smalltalk, which is a very good book - not squeak oriented, but very interesting none the less.

I was in the midst of reading his approach to development when I came across this phrase

In the first iteration, we will focus on the ‘normal’ sequences of events and leave the
abnormal alternatives (such as what happens when the information file does not exist) for the next iteration.

Doh! that should have been on my list of what I did wrong. I definitely over-engineered the initial attempt, and that contributed to my confusion.

Well, that didn't work!

After getting advice, from the beginners' list, about how to create model classes (subclass Object, rather than anything in the collection class, was the general advice), I boldly went forth and tried to build my first app.

It didn't go well!

Actually, I found the whole process both fascinating and frustrating. I started by sketching out - on paper - a class hierarchy, and identifying the properties of each class. Having done that, I then started implementing them in Squeak. As a side note, I am actually beginning to like the Squeak UI! I suspect this is a little like discovering that the mauve kitchen in your new flat is actually quite pleasant, after you get used to it. Actually, that probably isn't fair. I think what is really happening is that I am starting to understand Squeak's tools, and appreciate their usefulness. And, as a result, the very dodgy appearance is fading into the back of my consciousness.

OK, back to the code. I implemented the root class easily enough, and started building the others. However, very soon, I found that I was running around changing the object types used by the various instance variables. This is turn led me to change the method selectors, and that broke the message sends.

What was so fascinating about all this was that I was managing to confuse myself when I only had 4 classes!

Having had a chance to think about this - and ask for advice on the list - I have realised some of my mistakes:

  1. I identified object properties whereas I should have thought about methods - in other words what did I need the objects to do.
  2. I didn't create use cases. I know it seems crazy to do that for such a simple system, but as my experience shows, it is very easy to get it wrong.
  3. I should have written the tests first - yes, I know, that's what the book says, I just wanted to get on with building things :-)


So, let's have another go.

18/08/2008

The 'thought vs code' ratio in Smalltalk is quite amazing

Obviously, all programming involves deep thought, head scratching and staring out of the window, whilst you manipulate data structures in your mind. However, Smalltalk seems to be quite amazing, in comparison to e.g. Javascript, in the amount of time I spend thinking, only to produce tiny amounts of code.

The great part is that tiny code can produce amazing results.

Starting to program!

I had an interesting experience, a couple of days ago, I looked at someone's Smalltalk code and understood it! It wasn't until a few moments later that I suddenly realised what had happened. The code is starting to make sense :-)

Emboldened by this discovery, I decided to start thinking about the design of my first 'real' application. It is still really just an experiment, but it is something I want to make work, because I need to compare the development process/effort with that of doing it all in Flex.

So, I have spent the afternoon drawing objects and wondering about what should go where. Although all programming involves this type of thinking, the Smalltalk hierarchy really makes one think in a different way. For example, I have just spent the last 10 minutes comparing Dictionary and SortedCollection; trying to establish which object would be the better container for a list of clients (in the end I have gone with Dictionary because it seems to offer much better access).

The whole experience is a lot like standing in a hardware store looking at various nuts and bolts, trying to work out which to use.

16/08/2008

Magritte - very clever stuff

I spent a few minutes reading the tutorial for Magritte. I am not yet at a stage where I really understand how it works, but it does appear to be a very cool way of making objects 'self rendering', i.e. avoiding having to build views for components. You can learn more about it here

Configuring Apache to work with Squeak

This is another one of those things that I am blogging just to keep it somewhere. I don't use Apache (yet), and I am probably some way from needing it. However, when I do, this is how to configure it

15/08/2008

Resetting the username and password on an image

I am bound to need this again sometime!

"reset the username/password of the seaside config app"
WADispatcherEditor initialize.

"cleanup sessions"
WARegistry clearAllHandlers.

Setting a static URL for an application

I want to provide an api for some of my future apps. That means that I need to be able to define static urls and handle requests to them.

To do this, you have to override Class>>initialRequest. Something like this:

initialRequest: aRequest

super initialRequest: aRequest.
aRequest fields at: 'action' ifPresent:
[:action | 'put'=action ifTrue:[self confirm: 'you want to put']. 'get'=action ifTrue:[self confirm: 'you want to get?']].


I have a little way to go on this, because at the moment it is only processing the url argument, whereas I want to get to the contents of a 'posted' document. However, I am sure that will just be an object message away ;-)

This looks important - for some point in the future

This links to an article about a seaside 'announcer' framework. Looks like I will need it at some point

14/08/2008

Trying Seasidehosting.st

I thought it was time to try the process of sharing an image. I set up an account with seasidehosting.st and uploaded the image and the change set (I am not sure if I need to upload both). A few minutes later - having started my server - I had a working environment - just like the one on my machine. Very simple, very slick.

Call: and Answer: are my new best friends!

Consider this problem. You have a web page in which you need to control the values that a user enters. If the value of an item is 'unusual' you want to ask the user if it is correct, and then - if they confirm it - set the value and tell them that you have done so.


There are several ways you could do this. You could have some javascript functions that check values and communicate via alert boxes, you could submit the page each time, track the state and branch accordingly, and then rebuild the original page if everything is kosher. And... you could do what Seaside does:


decrease
count = 0
ifTrue: [(self confirm: 'are you sure you want to do that?')
ifTrue: [self inform: 'go for it'.
count := -1000]]
ifFalse: [count := count - 1]

I have to admit, this is really impressive. And, once I figure out how to do this via ajax, it will be even more so. Andiamo!

Gradually, light dawns

I am starting to feel as though I understand Seaside - at least a bit. And, if anyone is going to try to learn the system, this is what I would now recommend they do:
  1. Read the parts of the documentation dealing with creating basic HTML pages - I referenced then in a previous post. The explanations are quite clear, and, for me, helped to demystify the system.

  2. Read the tutorial A Walk on the Seaside. Although the HPI tutorial is much more comprehensive, I found this one much easier to understand.

  3. Go through the 'tests' section in the Seaside code. I.e., when you have the website running, navigate to the Tests section and go through each of the tests e.g. WAButtonTest. Make sure you use the Toggle Halos option and have a look at the code - typically the renderContentOn: method. This will really help you connect the code with what it does on screen.

  4. Remember to click the '?' in the Squeak browser. I only just stumbled across all the class comments. I don't know why I didn't do this before, but I think I was looking for the comments in the classes themselves. Perhaps that is how it worked in an earlier version? Anyway, the class comments help a lot

13/08/2008

This would have been a good place to start!

I am slowing working my way through the Seaside documentation. This page provides a great overview of how to generate HTML. Very useful.

12/08/2008

It seems as though any keyword message, sent to a WATagBrush is going to set an attribute

I have been looking at the various table tags a bit more, and I realised that all of the methods such as scope:, colspace: etc, are implemented as something like

self attributes at: 'summary' put: aString

This is useful for reading the code. With: contains the code that will go between tags and everything else is likely to set the tags attributes.

Why isn't tableCaption: a method within WATableTag?

I was looking at the code - in the previous post - and realised that the with: block says:

html tableCaption: 'blah blah'

And that suddenly struck me as odd. The tag is being generated by the WAHtmlCanvas object rather than by the table tag object. That would make sense if the tag could live outside of the table, but I don't think it can.


I don't think this is a problem, it's really more of a design question. I wonder why they built it like this. I feel a question to the beginners' list coming on!

Still slow going!

Smalltalk syntax is pretty easy to grasp, but understanding the class library can take forever (or so it feels at the moment!). Take this example:

renderEntityTableOn: html
html table
summary: 'This table gives the character entity reference,
decimal character reference, and hexadecimal character
reference for 8-bit Latin-1 characters, as well as the
rendering of each in your browser.';
with: [
html tableCaption: 'HTML 4.0 entities'.
self renderEntityTableColumnGroupsOn: html.
self renderEntityTableHeadOn: html.
self renderEntityTableFootOn: html.
self renderEntityTableBodyOn: html]

It looks reasonably straight forward, but I had a couple of questions
  1. what was the summary: item?
  2. and why did we need the with: block?
So, off I went, digging around. Now, the first thing I did was to copy this method and save it as renderEntityTableOn2:. Being able to do this from within the browser is great. Then I started removing bits. A quick look at the generated code (toggle halos and then select 'S' for the html source) showed that summary: produced an attribute in the table tag. It turns out that this is part of the html spec - I just didn't know about it.


But what about the with: block? The reason I was pondering on this was that it seemed redundant. Why not send all the messages directly to html and self? And, this is where it all gets a bit messy - although in retrospect it is all very easy to understand. I used a method finder to locate the implementors of table, and started looking at it. My initial thought was that html table would return a WAHtmlCanvas tag (not sure why I thought that), but it turns out that although table is defined in that object, it actually returns a WATableTag. And... the tag has a 'closed' property. I think that determines whether the tag is rendered as

or not. Anyway, it turns out that by sending the with: block, the contents of the block gets rendered between the table tags, rather than as separate tags.


Another bit learned ;-)

Kent Beck demonstrates the expressive power of talking about smalltalk

I asked a question, the other day, about whether an object should access its own properties directly, or via getters/setters. One of the responses, in the beginners' list, pointed me to a draft of Kent Beck's book - Smalltalk Best Practice Patterns


Now, I must be honest and say that I don't fully understand what Kent is talking about - yet. However, it is interesting to see some of the Smalltalk jargon put into a new context, and I am finding that really helpful. However, what really caught my eye was this sentence.

The other advantage of code written to reveal intention and conceal implementation is that it is much easier to refine by inheritance.
.
This highlights the problem I have been having. I am always trying to understand the implementation, instead of focusing on the intention. Now, clearly, if you are learning a new language, looking at implementation is important - if only to pick up coding style - but I am slowly beginning to understand that productivity in Smalltalk comes - at least in part - from treating objects as black boxes, and relying on understanding the intention.


in other words, you program with the assumption that the object does exactly what it says on the label. I am going to try that as an approach and see if it helps to clarify things.

06/08/2008

Should an object always use getters to access its own properties?

I just noticed that the seaside tutorial code always seems to do this - basically the code always says: self valueName. However, the Scriptaculous demos just do: valueName.

I have asked a question about this on the beginners list.

Update:

Randal Schwartz replied - almost immediately - and said

Clearly, position is an instance var, or perhaps a temporary. An instance var
may or may not have accessors, depending on whether it is meant to be tweaked
from the outside. #menuComponent, on the other hand, may be just an accessor,
or it may be a whole pile of code to generate that menu on the fly. At this
point, it doesn't matter.

Whether internal accesses to instance vars should use accessors instead of
direct access is a subject to debate (read: religious war). I hope you
haven't accidentally triggered that thread here. I tend to do the simplest thing that works, and leave it at that.


I totally agree with the simplicity principle. I can see why always accessing properties via getters would result in a consistent experience, i.e. the returned value would be the same whether the inquiring code was internal to the object or another object. However, it seems like more work.

There again, if you have gone to the trouble of establishing getters, perhaps one should use them everywhere. I will have to think about this.

Learning Seaside is really quite confusing

I realised today - whilst rereading the Ajax section of the tutorial that part of the difficulty I was experiencing in learning Seaside was related to the fact that I was trying to understand what it was doing.

Seaside successfully hides all of the javascript required to do Ajax type operations. This means that you can write purely in Smalltalk, and yet deliver Ajax functionality. My problem was that I was trying to interpret the Smalltalk code in a javascript context. in other words, I was trying to work out how the Smalltalk would actually work in the browser. The answer is - it won't. All that happens is the Smalltalk code generates javascript.

On the one hand, understanding what is happening is a useful learning exercise. But, on the other hand, I don't try to understand the bytecode that Squeak generates, so why worry about the javascript? I think the difference is that I understand javascript and therefore naturally want to understand what is happening. I think I have to get over this!