28/12/2008

Objective-j versus Seaside

I have just spent the last few hours learning about objective-j and the cappuccino framework. In essence, the guys at 280 North have implemented the OS X Cocoa frameworks, in Javascript. The whole thing is very impressive indeed.

However, it has got me thinking about different ways of developing web applications. In the Cappuccino model, the client programming is done in objective-j, and is - essentially - totally separate from the backend system. The client application has no connection with the server language. All that is required is the appropriate set of REST services. This is obviously very different from the Seaside model in which the client application is, almost, a by-product of the Squeak code.

But which approach is better? Cappuccino looks like an excellent development framework. A lot of basic OS X code (written in Objective-c) can be run, almost completely unchanged, in objective-j. And, perhaps best of all, the documentation is very good. This is achieved partly through the efforts of 280 North, but also because the Cocoa docs match up very well.

On the other hand, Seaside offers much better development tools and a very different way of working. I don't know enough about each approach to really form a conclusion, yet. But, it is nice to be spoilt for choice :-)

08/11/2008

Adding Javascript to seaside

This was posted by Lukas Renggli on the Seaside list, seems like useful stuff for the future.

Whenever you want to include Javascript verbatim, you can use SUStream>>#on:. Otherwise a Smalltalk String is automatically escaped as a Javascript string.

27/10/2008

Developing your applications through the debugger

Yesterday, while I was listening to an episode of FLOSS Weekly, Randal said something that caught my attention. He talked about writing unit tests and then running them before you had actually written the code - that much I had heard about before - but he then went on to talk about how you would then fix each of the tests by writing the code in the debugger, and clicking proceed.
This struck me as a really interesting way of coding. It's almost like having your office applications built into your to-do list. The to do item becomes the item you are trying to do.
I think I am going to experiment with this approach - I still need to understand a bit more about the debugger's capabilities. But what really appeals to me is that one could write almost pseudo code (although I think it is more of a declarative description) of what you want the object to do, and work away - a piece at a time - until it does it.
In a way, one could think of this style of programming as gradually removing all the bugs until the code does what you want.

Security 'watch outs' in Seaside

There was an interesting question raised on the Seaside list, today. I have pasted the thread below. Basically, if you share a URL with someone, they can potentially take over your seaside session. There are ways around the problem, but it is important to note for the future.

>
> hey, guys..
>
> one quick question after watching the seaside movie last night..
>
> pretend i have an application like ebay written in seaside..
>
> so, i log into my account..
>
> check my bids..
>
> then, i do a search for something..
>
> during that search, i find something my friend would really like..
>
> so i send the link to my friend..
>
> now.. suppose he immediately clicks it (i sent it over IM..)
>
> does he now have full access to my session, including my account
> information?

Unless you take action to prevent it, yes. This problem isn't unique
to Seaside, of course; any system with session keys in URLs will be
have the same problem. You can, of course, configure the session key
to be stored in cookies, which eliminates the problem. Or you can use
a WASessionProtector to prevent the IP address of the user from
changing.

Note that in either case, you would need to make sure to include
enough information in the URL via #updateUrl: that a new session could
be built pointing to the right item.

24/10/2008

I have no idea what this means, but I hope, in time, it will make sense

I am noting it here for future reference.

> is there a way to clean up the callback registry, or to unregister some
> callbacks?

With the model of Seaside, it is hard to tell what callbacks are still
used when doing AJAX. Therefore I suggest to do a full refresh from
time to time.

Note that you can easily do a full refresh through AJAX. Just trigger
an AJAX request to a normal callback, extract the string between
body and /body and place it into the DOM tree. This recreates all
the callbacks in the page and ensures that old ones eventually expire.
To the outside this "full request" feels like a normal AJAX action,
just that it is maybe a bit slower than the other ones.

Actually I planned to write a blog entry about this technique, just
didn't find the time yet.

23/10/2008

So that's what decorators do!

I have been reading about decorators in various tutorials, but not really got my head around them - largely because I am still trying to understand more basic information. However, this post in the Seaside list really helps me understand the concept.



You may also want to take a look at WADecoration, which can help you
to decouple the header/footer from the main page:

WADecoration:
I am an abstract decoration around instances of WAComponent. I can be
added to aComponent by calling #addDecoration: and I change the basic
behaviour or look of a component. There are several methods that can
be overriden to archive this:

- #renderContentOn: to emit xhtml around the decorated component. Call
#renderOwnerOn: to let the owner emit its output.
- #processChildCallbacks: to intercept the callback processing of the
owner.
- #handleAnswer: to intercept the answer processing.



I am sure I will find all the methods useful, eventually, but it is the first one that struck me as particularly interesting. It's almost as if it allows you to add 'decoration' to a component. Hmmm, intention revealing method names, not such a bad idea after all ;-)

Switching between https and http sessions

Establishing SSL connections is going to be important in a lot of my apps, so this code snippet from Ramon is well worth noting

14/10/2008

It won't work, if you don't use the right objects

I had a very interesting problem yesterday. I am slowly moving forward on building the threaded discussion system. I have worked out how to render the basic HTML, as a series of components, and I was at the stage of wanting to render the discussion items. My question was how to represent them?

In an earlier post I had looked at how one might identify the objects in a system, and in particular which ones should be written from scratch. The basic idea was that if one were storing information that already 'fitted' into a class, there was no reason to create something new. The class could be a simple one, such as Array, or something more complex such as Person. In either case, the basic principle was - don't reinvent the wheel. However, as we will see sometimes reinventing the wheel is the right thing to do!

I decided to represent the conversation as an array of nested arrays, e.g.,

discussion := #(topic1 topic2 (sub-topic2.1 sub-topic2.2) topic3).

Initially, the structure seemed to work well. It was simple, easy to traverse and didn't involve the creation of any new classes. I was quite pleased with myself for following the design principles. Unfortunately, I soon discovered that rendering the subarrays was a pain. Basically, I want Seaside to create an Ordered List and add the entries as List Items. When it comes across a subarray, it should start another ol tag and add the elements.

I played with this problem for a little while, but everything I did seemed ugly, and not very smalltalk. In the end, I asked on the beginners' list and received two interesting replies:

  1. Randal suggested using the Visitor Pattern

  2. Ramon suggested creating two new objects and using recursion (see below)


I had never heard of the visitor pattern, but fortunately Wikipedia came to the rescue. AIUI this would involve adding a method to both the array, and the strings/arrays it contains, so that they know how to render themselves. Ramon's code, more directly challenged the way I was storing the discussion threads. He suggested something like this:

renderPost: aPost on: html
html render: aPost.
aPost comments do:
[ :each | self renderComment: each on: html ]

renderComment: aComment on: html
html html: aComment body.
aComment comments do:
[ :each | self renderComment: each on: html ]

For the time being, I am going to try Ramon's approach, purely because I have a better understanding of how to do it. However, I am now intrigued by the visitor pattern, so I will go back to that, once I understand a bit more about OO design. However, for me, the most interesting aspect of this whole problem was the question of why couldn't I see the answer? I think the explanation is that once I had decided to go with an Array, my thinking was limited to that set of methods etc. And, the choice of the Array was driven by the fact that the data could be made to fit into it. So, I now need to develop a more sophisticated design heuristic when thinking about object modelling. Basically, just because something could fit, doesn't mean it should. Now, obviously, design is an iterative process, and all programmers run around refactoring, sooner or later. What I am trying to understand is how I might think about the problem in a more flexible manner.

13/10/2008

Creating a framework on top of Seaside

Now that I am starting to understand Seaside (and Squeak), I am beginning to realise that I will probably need to customise a bit. Not because of shortcomings, but rather because there will be various good practices that one will almost always want to build into a project. My previous post about Ramon Leon's initialisation tricks is a good case in point.

Randal's comment on that post - I have included his version in this post - came at the exact moment I happened to be reading another of his entries, which addressed configuring the startup/shutdown issue. So, my default application settings will now contain something like this:


MyClass class >> initialize
self registerAsApplication: #foo.
Smalltalk addToStartUpList: self.
Smalltalk addToShutDownList: self.
self startUp.

MyClass class >> #registerAsApplication: name
^(super registerAsApplication: name)
libraries add: SULibrary;
preferenceAt: #sessionClass put: FooSession;
yourself.

MyClass class >> startUp
self start. "in case I want more things here"

MyClass class >> start

WAKom default.
... other stuff if I want it...
HttpService startOn: 9090 named: 'httpd'.

MyClass class >> shutDown

self stop.

MyClass class >> stop

HttpService allInstancesDo: [:each | each stop. each unregister].

Tips and tricks for making seaside applications easy to manage

One of my current web applications is built on top of Lotus Domino. I have used Domino & Notes for years, and I have a deep respect for it. This particular application was only meant to have a short shelf life, but it has turned into the application that wouldn't die. Normally, I would be happy with that, it is always nice to know that your work is appreciated. However, in this case, because it was put together in a hurry, we didn't build a web based admin console for it. Unfortunately, for us, this means that every time someone want's to use the app, we have to scurry around with a copy of Lotus Notes, messing about with environment variables by hand.
Granted, our 'suffering' is trivial in comparison with people who deal 'real' jobs. After all, as many of my friends have pointed out, all we do is sit around, drinking tea and chatting with people, followed by messing around with computers - hard to argue with that assessment. Anyway, as we move applications over to Seaside, I am really keen that we should do everything possible to simplify the admin. And, that is why I found this section of Ramon Leon's Terse Guide to Seaside, so interesting. He wrote:

FooComponent class>>initialize
"self initialize"
| app |
app := self registerAsApplication: #foo.
app libraries add: SULibrary.
app preferenceAt: #sessionClass put: FooSession

This sets up a dispatcher at /seaside/foo with the Scriptaculous library (SULibrary) and a custom session class that might contain things like the current user or current database session. You can then highlight the comment “self initialize” and run it to create your site. This has the additional advantage of automatically setting up your site in any new image when you load your package into it and also allowing you to programatically recreate your site on demand. This comes in very handy when upgrading to newer versions of Seaside which sometimes require recreating your sites.


I think this is going to be very useful for the future

12/10/2008

Oh, so when you say 'literal' you really do mean 'literal'!

This comes from the 'hard of thinking' category.

I was trying to create my 'children' method - necessary when you are rendering subcomponents in seaside. I knew it need to return a collection, and when I looked at an example, it showed:

 ^#()


In other words, return an empty array. Obviously, it was using the array literal syntax. This, of course, it where my thinking went horribly wrong. I created my method with the following code:

 ^#(pageHeader pageFooter).


Seaside stopped working :-( It complained about a decorator method not being understood by ByteSymbol. If you are new to seaside, and you don't already know the answer, see if you can work out what I was doing wrong.

Give up? OK, the array literal syntax creates an array of literals. I know, who would have thought it! My array contained the symbols #pageHeader and #pageFooter, NOT the value of those two instance variables. Totally obvious now, but I share it in case you are ever tempted into similar thinking. And, just for your information, the correct code is:

 Array with: pageHeader with: pageFooter.


## Update: Randal has just pointed out that there is also 'curly brace' runtime Array constructor that was limited to Squeak, but is now available in Gemstone and possibly VW. The syntax is:

 {pageHeader. pageFooter}


This makes much more sense, and is a very slick way of creating arrays. Thanks Randal

11/10/2008

As Homer would say "Mmmm Smalltalk, is there nothing it can't do?"

No sooner had I posted my vague 'pipe dream' about automatically creating methods, than Randal posted a comment, showing exactly how to do it. In case you aren't subscribed to the comments feed, this is what he wrote:

#(one two three four five) do: [:each | YourClass compile: (each asString , ' self flag: #toBeWritten') ].


Actually, he finished his code with a :-) . Out of curiosity, and powered by my new found belief that Smalltalk really can do anything, I opened a method finder to check whether :-) is a method. Sadly, and not surprisingly, it is invalid syntax. However, if I ever do find a way of implementing it, I shall get it to return an Anchor tag to this video.

Misusing the 'create accessors' menu option

I spent some of last night sketching out the UML for my test project. I wanted to turn the sketches into code, but it was late and I couldn't be bothered to type out all the method names etc. Then I had an idea. If I created instance variables for each of the methods, I could use the Accessor menu item to automatically build the stubs. Then, delete the superflous variables, and my structure is ready to fill in.

Now, clearly this is an ugly hack. However, it did save me some time, and it made me curious about how the accessor code generator works. At some point in the future, I will see if I can find the appropriate methods and create a new version. Ideally, I would like to have a new item in class definition, something like stubMethods: that would allow me to generate the methods and mark each one with a self flag: #toBeWritten. call.

Starting to use the refactoring tools in OB

Up to now, the only OmniBrowser tool I have used is the 'accessors' option, which automatically generates instance variable access methods. All my other actions, e.g. moving methods, creating subclasses etc., have been done manually, largely because my mind was fully occupied just trying to work out what I was meant to be doing!

Last night, I decided to bite the bullet and explore a bit further. And finally, I am beginning to understand why experienced Smalltalkers describe the system as being more than just a language. There are some really clever tools that can save you from, not just wasting time, but also the chance of messing things up, badly!

For example, I needed to rename a variable in a method, and therefore also rename its accessor. When I used the rename menu option, it went off, did the rename and then updated all the methods which accessed that method - brilliant!

Now, clearly this sort of global search and replace isn't rocket science, but the fact that the tools are so beautifully integrated means that coding, and refactoring, become a 'relative' pleasure.

Smalltalk and Etoile

Some time ago I stumbled across an open source project called Etoile

The project is attempting to create a new, configurable, interface for computers, based upon the GNUStep library. My interest lay in the potential to build workspaces that might support creative problem solving. Anyway, recently, they announced that they were planning to build Smalltalk into the system, and that has now happened.

The class library is a little unusual, because it builds on top of the GNUStep library, but the basic language will be familar to anyone who has used Smalltalk. I really like the idea of being able to program the whole OS via Smalltalk.

10/10/2008

A terse guide to seaside

Ramon Leon has put together a very good, and - as the name suggests - brief guide to Seaside. You can read it here.

What I find so interesting about the guide is that a few months ago the contents would have been largely unintelligible to me, and now, they seem to make perfect sense. I am sure people have the same experience when learning any new skill, but it does reinforce the idea that it is worth going back over tutorials, several times, because you can get a lot of new information that you may have missed the first time through

06/10/2008

Class side variables, an alternative to Global variables

I have built my small experiment, using Globals, and it actually works quite well. However, over the weekend, I was thinking about whether I should use a Class instead of the Globals. Mark Volkmann was thinking similar thoughts, but with a different objective. He added this to the beginners' list


create a class that represents the enumerated type
add a class variable for each enumerated value (must start uppercase)
add a class-side initialize method that creates an instance of the
class for each enumerated value using basicNew and assigns it the
corresponding class variable
prevent creation of additional instances by overiding the class method
new with "self error: 'new instances cannot be created'"
add class-side getter method for each enumerated value that simply
returns it
Here's an example ColorEnum class.

Object subclass: #ColorEnum
instanceVariableNames: ''
classVariableNames: 'Blue Green Red'
poolDictionaries: ''
category: 'SomeCategory'

initialize
Red := self basicNew.
Green := self basicNew.
Blue := self basicNew

new
self error: 'new instances cannot be created'

red
^Red

green
^Green

blue
^Blue

---
Mark Volkmann

03/10/2008

Timing execution speed

Premature optimisation is Evil. However, I think Evil has an unfair reputation. And, because of that, this particular code fragment is well worth remembering

Time millisecondsToRun: [].

Update: Turns out you can actually send

timeToRun to any block. Much easier.

Creating some sort of data bus

How might I get the various Seaside components to know about their underlying models?

I am trying to build a simple application - sort of a discussion forum. There could be several fora, plus a collection of users - each of whom needs to authenticate. What I am trying to get straight is the easiest/best/most reuseable etc., way of linking the presentation with the data.

Clearly, when I instantiate components, I could pass them the address of the model - or just the subpart of the model they will be interested in, but somehow that feels clunky to me.

As I was sitting here, thinking about it, it suddenly occurred to me that I could identify the shared objects, e.g., user directory etc, and declare them as Global variables in the Smalltalk SystemDictionary. That way, they would be naturally accessible to all components. But, is this a good idea? Aren't Global variables evil?

I don't know, but it does seem to be a neat solution, that builds on top of Smalltalk's 'natural' behaviour, and means that the objects can initialize themselves.

I am going to have a play with the design and see how it pans out.

Building a login system for Seaside

I need to build a website that has individual user authentication. I was confused about how to do this, but fortunately, this article seems to cover it very well. I shall go and experiment.

Clever ways to build strings

Mark Volkmann asked a question, on the beginners' list, about the best way to build a concatenated string. He wonder whether there was a benefit in doing one of the following:

Approach #1

s := ''.
s := s, 'foo'.
s := s, 'bar'

Approach #2

stream := WriteStream on: ''.
stream nextPutAll: 'foo'.
stream nextPutAll: 'bar'.
s := stream contents


Randal responded with this suggestion:


s := String streamContents: [:stream |
stream
nextPutAll: 'foo';
nextPutAll: 'bar'.
].

Then you don't even have to name the stream, because it has that
temporary name inside the block.


It has taken me a little while to understand how this works. Up to now, I have been thinking about blocks with arguments as having their argument passed in from the 'thing' they are associated with. E.g.

(1 to: 10) do: [:index| Transcript show: index]


In this case, the argument is created within the called method:

streamContents: blockWithArg
| stream |
stream := WriteStream on: (self new: 100).
blockWithArg value: stream.
^stream contents


This gives me a new way of thinking about arguments and blocks.

30/09/2008

SUnit loves my instances

I have been trying to find out how to get rid of dead instances, because I seem to have collected a few. I first noticed this when I ran
Fspace allInstances size
and discovered 7 instances floating around. After some digging around, I was pointed to this entry on clearing up junk.
The entry introduced me to the idea of a PointerFinder, and that helped me identify where the instances were being referenced. However, that just lead to more confusion, because they seemed to be being held by the TestRunner, even though the window was closed.
A search of the squeak wiki brought up this article, which was interesting but didn't really solve the problem because I was already following its advice - at least I thought I was!
In the end, I started a new image, filed in my code, and changed the SUnit tests to include tearDown code as well as setUp code. This seems to have solved the problem. However, the documentation suggests that this isn't necessary, so perhaps I am doing something wrong.

Redirecting on session expiry

I am collecting up little code snippets, because I am bound to need them at some stage. I am tempted to start my own wiki, however, I think it would be better if there is somewhere I can store this on the smalltalk wiki - that way everyone can benefit from them.

This snippet controls the redirection of the user when their session expires.


You should overwrite the expire method on your session and redirect to the
desired url,
i.e:
MySession>> expire
super expire.
self redirectTo: 'http://seaside.st'

29/09/2008

Cincom's Seaside Tutorials

I have now had the chance to go through the tutorials, and they really are very good indeed. If you are interested in learning Seaside, this is a great place to start.

It seems as though James is in the middle of rerecording them, because the earlier ones are now using full-motion screen capture, whereas the later ones use Wink and are more 'static'. It was interesting to compare my reaction to the two styles. There is something about seeing the mouse move, in real time, and even seeing James type, that made the newly recorded ones much easier to follow. I think that cutting and pasting code into the text boxes is slightly jarring to ones learning process. Something for me to bear in mind when I make video demos.

Using Flex directly with Squeak

Thierry Thelliez has been doing some experiments, trying to integrate Flex with Seaside. I am interested in this too. He has now worked out how to pass data to a Flex component, embedded in a Seaside page.



I found the solution:

The FLEX HTTPService is encoding the request URL and that's not
playing well with Seaside style.

I found another way to do it with a FLEX URLLoader (code sample
below). So far so good. The FLEX widget can talk back to Seaside to a
dynamic URL, get back some XML data and draw whatever FLEX can offer
(datagrid, charts,...). Cool. (Next step for me: https support?)

Thanks again.
Thierry


On the MXML side:

private var myLoader:URLLoader = new URLLoader();
...
private function initApp():void {
...
var request:URLRequest = new URLRequest(aSeasideURL);
myLoader.addEventListener(Event.COMPLETE, onLoaded);
myLoader.load(request);

private function onLoaded(event:Event):void {
sourceXML = XML(myLoader.data);
}
...
private function onLoaded(event:Event):void {
sourceXML = XML(myLoader.data);
}
...

...


Glare UI, combining Flex and Smalltalk

Glare is a new, experimental, Flex remoting interface for Smalltalk - currently Visualworks. James Robertson made a brief video of the system at ESUG 2008, and you can see it here

I think this looks really interesting. Combining a Smalltalk back-end with the near universal availability of the Flash player, could provide some very exciting capabilities.

Squeak Map and Package Universe - the fog clears

At little while ago, I asked the question - on the beginners' list - about whether Package Universe had now replaced Squeak Map as the place to look for software. I didn't get a response, at the time, which surprised me because the experts on the list are usually excellent at answering newbies' queries. Anyway, today Ralph Johnson answered a similar question, and I can see now that the situation is more complex that I had imagined. I am including his explanation for future reference.

> What I observed is that it is very hard to find the latest (working)
> packages within the tools provided (SqueakMap, Universe browser).

What you call "Universe Browser", I will call "Package Universe", or
PU. SqueakMap is SM.

SM and PU are comparable. SM is a lot older, and is nice because,
until a year or so ago, it had a pointer to pretty much everything
being distributed. Montecello (MC) is different. It is aimed at
development, not at distribution. For a long time people used MC for
development and SM for distribution. SM basically would point to a MC
repository with the version of the software you wanted. I think it
was called "SqueakMap" because it would be a map to everything in
Squeak.

The problem with SM was that it had no dependency information. It
would not try to load dependent packages, or even warn you that you
needed to load them. You could read the comments of a package and see
if it advertised that it was built on another package, but it was a
pain to build a large system with SM.

PU was an attempt to solve this, but it went a long way beyond
dependency information. Lex Spoon wanted a package universe to have
only packages that were known to work together. Thus, there would be
many package universes. Each one would be self consistent, but
packges from one universe might not work with those from another. In
contrast, there was only one SM.

PU has been around for several years, but it didn't get popular until
it got used for 3.10. its popularity had the obvious-in-hindsight
consequence of people putting their packages in it but NOT putting
them in SM. So, SM no longer has the latest and greatest of
everything. Moreover, PU tends to have lots of versions of each
package, which is entirely against the original purpose of PU, since
not all versions will work with every other. In retrospect, PU should
have used SM to find the latest version of a package. That would have
forced people to keep putting info in SM.

I am surprised that nobody has yet upgraded SM to do everything that
PU does. That would be one solution to the problem. Keith Hodges has
built something called Sake/Packages that lets you write scripts that
does everything that PU does, but that can do this upon SM, and has
proposed using this and SM instead of PU. One of the reasons that PU
got off the ground was the Lex Spoon built a few universes, and then
he got some people to maintain them. Perhaps someone needs to write
the Sake packages to get things started.

If you are using a fairly standard image, you should try using the
universe for the package and then complain to package authors when the
version of the package in it is out of date. If you use SM, complain
to package authors when the latest version is not in SM. The tools
are there, but people have to use them. Certainly they can (and
should) be better. But until they are better, we ought to use them as
best we can.

-Ralph Johnson

28/09/2008

Sometimes I 'get it' and sometimes I don't!

Today I was trying to free up some objects, so that they would garbage collect. What I tried to do was:

Fspace allInstancesDo:
[:each |
each := nil.
Transcript show: (each value); cr.
Smalltalk garbageCollect]

What I expected it to do was to set each of the instances to nil. Of course, as Randal kindly pointed out, it would do no such thing. What it actually does is set the value of the :each temporary variable, to nil.

I was thinking about why I had made that mistake and the conclusion I came to was that I was becoming so used to sending messages to objects, that I thought I was somehow communicating with the instance, rather than with the temporary variable.

Ah well, onwards and upwards :-)

Keeping the development image up to date

I noticed, today, that I seem to be running an older version of Seaside (2.8). I am tempted to upgrade, but I am still not clear how the upgrade process works, and whether it would overwrite any changes I had made. I suspect not, but I am reluctant to try - just at the moment.

As luck would have it, there was an interesting comment in the beginners list today. I am noting this for future use.




In the dev image, from the world menu, select "open...", then "Universe
Browser (enhanced)" (or basic if you prefer). Make sure up update the list
from the network.
Now others will have to chime in, because you can also select "open..." and
then "Squeak Map Package Loader." Much of the same material is in both
places, but they ARE different somehow. I've never been quite clear how.

However, if you take a standard dev image, and execute (in a workspace):


(HTTPSocket httpGet: 'installer.pbwiki.com/f/LPF.st') readStream fileIn.
"Bootstrap"

and then

Installer install: 'Packages'.

You will get a pretty nice stable image with nearly every dev image release,
at which point you can also load packages by doing things like:

Installer sake addPackage: 'FreeTypePlus'; install.
Installer sake addPackage: 'MemoryUsage'; install.
MemoryUsage new openInWorld.

(These are just two packages I like to load). Anyway, the nice thing about
using the Universe Browser or the Sake package loader is that they take care
of the dependencies for you...

I have NO IDEA how it all works--I've just finally figured out how to use
it.

Also, with a fresh dev image, try, in the Universe Browser, updating the
list, then "select upgrades." Click the "all" button, and scroll through
the list. It will show you what packages it selected. You can than update
if you want...

27/09/2008

Web Velocity - very clever stuff

I had heard about Web Velocity, but knew nothing about it. So, I was very pleased to find this video. Well worth watching, if you are interested in using Smalltalk for web apps.

26/09/2008

Fantastic Seaside tutorial from Cincom

James Robertson of Cincom Systems was kind enough to point me to a Seaside tutorial that he built. You can access the tutorial here. Although the link to the tutorial is included as a comment to my previous entry, I wanted to bring it up to the top level in case anyone else is subscribed to these entries, and may miss it if they aren't subscribed to comments.


The interesting thing about James' comment is the timing. I have just started listening to his podcast, and, as a result of that, I downloaded the Cincom smalltalk this morning!


I have a couple of outstanding questions that I need to get answered, in due course:

  1. How do I get it to run on a Mac! Yes, I am sure it is an RTFM, it is just that I am a bit short of time, at the moment. The installer said something about setting a path variable, and, sadly, my knowledge of OS X is rather limited, so I have to check the instructions
  2. How much does it cost to use Cincom in an application? Normally, this isn't a difficult question to answer, but with the Cincom smalltalk, it seems as though everything is negotiable. I think the pricing is what put me off trying it in the past. However, now that I am becoming so interested in the language, I really should find someone who can explain the pricing model. My ideal is that it would be a bit like the Gemstone approach, i.e. free for small applications, then you pay for bigger ones. Who knows. However, when I find out, I will note it down here :-)

Seaside learning resources

This presentation by Lukas looks very useful. It provides an overview of Seaside, whilst ,at the same time, showing some code examples. I think I will come back to it in a little bit.

21/09/2008

Icons in OmniBrowser

So, it turns out that what I had been referring to as OmniBrowser isn't really OmniBrowser. OB is actually a framework for building browsers of all kinds. Various people have built new browsers and the version that ships in the latest Dev build is called OmniBrowser Enhancements (except when people just call it OmniBrowser!).

Anyway, there is some good documentation - including an explanation of what the icons mean, here

Turns out I was doing my unit testing all wrong!

I thought - based upon a couple of examples that I had read - that SUnit worked like this:

self should: [some condition].
self shouldnt: [some condition].


Turns out that the should and shouldnt messages are for checking whether errors have been raised or not. I need to learn a bit more about them. However, I now know that the right messages to send are assert: and deny:

You can read a bit more about using SUint, in a practical way, here

18/09/2008

Huh, Test Driven Development, not such a crazy idea after all ;-)

Well, my new image is beginning to pay off. I started writing my first semi-serious webapp today. And, given everything I have been reading, plus my experience from my first attempt, I decided to try to apply TDD. So far, so good. The system actually caught some bugs within the first few minutes of using it.

I haven't got to the stage of writing my tests before I write the code, but I think I will do that next, because I can really see the value.

What do all these little symbols mean?

Many of the methods in the SystemBrowser (my current default), have symbols next to them. As far as I can tell, they relate to whether a method is inherited, overridden, or something else! The rules seem to be:


  • Nothing: new method in this chain, i.e. the method could exist in other classes but not in this particular chain of inheritance.

  • Upward orange triangle: method is inherited and overridden in this class

  • Downward orange triangle: method is overridden in a subclass

  • Two orange triangles (up and down): overrides and is overridden in a subclass

  • Green up arrow: calls the same method in its super class

  • Blue triangle: Self should not implement or subClassResponsibility

  • Green plus: don't know, can't work this one out

  • Red flag: has a halt message in the code

  • Spanner: shows that the code needs to be returned to, i.e. under construction



Need to check this stuff on the beginners' list

Hmm, OmniBrowser!

The new Squeak Dev image is great. Much less clutter, nicer fonts, altogether a good experience. However, it has also introduced me to a whole new set of tools. The main one being, OmniBrowser. I am now feeling a bit lost.

OmniBrowser looks like the old system browser, but it behaves in different ways. Not hugely different, but enough to make me feel uncomfortable. So, today I went in search of documentation that would explain how to use the new tool. Not surprisingly, the documentation exists, and also unsurprisingly, it is scattered all over the place. The best I have been able to find so far is here. I am going to read through the PDF and see if it helps.

 Update: 

Looks like this article is a better place to start if you want to understand how to use the browser.

And another update. The article - although very helpful - seems to be slightly out of step with the current Squeak Dev image I downloaded. In particular, there is no ' SmartGroup' Browser in the World menu. However, the SmartGroup feature seems to be built into the main browser, and if you use that - and follow the instructions in the article - it seems to work in the same way.


I am beginning to think I should rewrite this whole post instead of adding updates!

Anyway, I have found some useful help text. It doesn't really explain how to use the browser, but it does tell me a bit about switching between browsers and what the various versions do. I think the SmartGroup browser must have been removed from this dev image. Also, it seems as though the SqueakSource package idea is gradually becoming an organising principle for Squeak - it is now being built into the tools more directly.

17/09/2008

Getting the development image - I should have done this from the start!

I was reading through Ramon Leon's blog and I came across a reference to the Squeak Developer image. I had read about this before, but obviously not followed it up. There again, perhaps I did and it just got lost in the sea of images I have downloaded over time!

Anyway, if you are starting to develop in Squeak, get the developer image - you know it makes sense!

14/09/2008

Subscribing to teh Squeaksource rss feed

I noticed, browsing around squeaksource today, that it has an RSS feed. Out of curiosity I subscribed, not expecting many changes. Boy, was I surprised. If the feed is correct, i.e. it isn't reporting old changes, then there is a real blizzard of activity. I haven't worked out whether any of it is useful yet, but it is interesting to see what people are working on.

Getting dangerously ambitious!

The other night I worked out how to rotate a matrix. Well, to be more precise, what I actually did was take an Array of OrderedCollections - that held the result of the CSV parsing - and collect up the columns, and write them into a new Array of OrderedCollections.

The code, which is a little messy because it is coming straight from my workspace, looks like this:

newArray1 := Array new: ((oldArray1 collect: [:each| each size]) max)
(1 to: newArray1 size)do: [:count| newArray1 at: count put: OrderedCollection new]
oldArray1 do: [:each| (1 to: each size) do: [:count|| oc2| oc2:= (newArray1 at:count) . oc2 add: (each at:count) ]]


Looking at the code now makes me realise the importance of giving my variables 'intention revealing' names. I must pay closer attention to how the rest of the squeak code is written.

Anyway, having got this code to work, I now want a way to package into something reusable. There are various options, I could add it to Array, I could add it to CSVparser, I could try to add it to either Matrix or Array2D. However, I don't 'own' any of those classes, so although I could subclass them, I really don't know if that is a good way to do it. So, instead, I am going to try to write a CSV Browser. Yes, I am going to delve into Morphic, or Seaside, or perhaps both.

12/09/2008

New day, new problem ;-)

So, after having learned about the CVSParser, I am now becoming more interested in the various squeak repositories. I say, 'various', because there do seem to be a lot of them. And, I don't really understand how the various package management tools in Squeak work.

Monticello, as far as I can tell, is a version management system, and I suspect that I would use it to manage my own code, as well as pull down other people's. The Monticello browser allows me to access numerous repositories. However, there is also a Package Universe browser. This lets me download packages (which seem to be Monticello files) from various sources. It doesn't seem to offer any upload capability, and therefore seems to be a 'consumer' tool. The problem is that this leaves me with several unanswered questions.
  1. Which respositories is the package universe browser accessing?
  2. How is that list kept up to date, and can I/should I add new repositories to the list?
  3. Is this now the preferred way of getting code (a bit like app-get on Linux)?
  4. What about the squeakmap browser, that I stumbled across as well?
  5. Finally, is there any kind of quality control in the packages that package universe lists? I don't mean it in a formal sense, after all no one is really 'in charge' of squeak, but rather is there any kind of rating system, because it seems as though squeaksource and squeakmap contain more items than are listed in the package universe.
Answers must be found!

11/09/2008

Maybe I am beginning to understand this stuff ;-)

This should probably be filed under the heading of "famous last words". However, I have actually succeed in doing something useful with Squeak. I think this is quite an important milestone. Up to this point I have been scratching my head and trying to understand individual methods, whilst all the while feeling that things weren't quite making sense. This evening, however, was different.

After I loaded Avi Bryant's CSV parser, I was able to create a stream from a file, figure out to how process the contents and ended up with an array of OrderedCollections. I wanted to pull the first item from each collection (basically, I was rotating a matrix), and display it in the Transcript. So... I typed in:

(CSVParser on: (FileStream readOnlyFileNamed: 'ifadqs.csv')) rows do: [:each| Transcript show: each first; cr].

And it worked :-)

Starting to use Monticello

Loading Avi's CSV parser, nudged me into using the Monticello browser. I had played with it before, but this time I had to work out how to 'hit' a different server - turns out you just click the +Repository button.

One strange thing about the browser is that I can't work out how to remove repositories from the list. Probably not important at the moment, but curious none the less

Characters != String

I am sure it makes perfect sense but...

The fact that:
$a = 'a'
returns false is a bit unhelpful. Still, worth noting for the future. Also

$a = ('a' at:1)
returns true.

Parsing CSV files and thinking in objects

I have a google spreadsheet that contains the answers to a questionnaire. I wanted to do some simple processing on the responses, so I thought it would be a good idea to use Squeak to munge the data around. However, that raised the question of how to get the data into the system. CSV to the rescue!

Google can export the file as CSV, so I thought it should be reasonably easy to convert it to some sort of OrderedCollection. The question was how to do it? I played around with some methods for a while, and then decided to ask on the beginners' list. The reason I wanted help was that I had the feeling that I was still thinking in far too procedural manner.

Zulq was kind enough to offer this solution
I ususally do something like this:

(((FileStream readOnlyFileNamed: 'file.csv')
contentsOfEntireFile " read and close "
findTokens: String crlf) " split into lines "
reject: [:e | e isEmpty]) " lose empty lines "
collect: [:e | e findTokens: $,] " split into fields "

Regards,
Zulq.


Squeak is so powerful, it is just amazing. It also highlights that I am still nowhere near getting the OO thinking right. Ah well, time enough. However, when I dug into the CSV a bit more I realised that the solution wasn't complete.

The CSV spec covers the situations where:
  1. data fields don't contain embedded commas
  2. where they do
  3. where they contain double quotes
This is important because - basically - if a field contains a comma then that field must be enclosed in double quotes e.g.
this is data,"so, is this"
So the findToken solution wouldn't be quite correct because it would split the line at every comma.

I was pondering this for a while, largely thinking how to solve this in the most elegant way, when it dawned on me that probably I should find the point in the existing solution that would produce the new solution, and create the least disruption - maybe a new heuristic? It seemed to me that if I could subclass (or perhaps replace) the findToken routine, then I would have changed the least amount of code, and still solved the problem. I am not really using the Test Driven Development approach yet - don't understand how to do it at a practical level - but that should be my next move.

Time to write some code

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!

30/07/2008

Learning to read smalltalk

Smalltalk has a very simple grammar (it must be true because all the books say so). However, just because the syntax is easy, that doesn't mean it is necessarily easy to understand the code. Take this as an example


renderContentOn: html
html table: [(self sortBlock
value: (self filterBlock value: self items))
do: [:item | html tableRow: [self renderItemBlock
value: item
value: html]]].


I struggled with this for a while, mainly because I was trying to read it left to right. Whereas, what I should have been doing is reading it in unary, binary, keyword order. When you look at it that way the central block becomes more like this:

1. get the list of items
2. filter them by passing the complete item list to the filter block
3. sort the item list that is returned by the filterblock
4. iterate over the sorted list and render them.

It all makes perfect sense, once you get the hang of it.

Things are so much clearer in the morning

I don't know whether this is true of all programming languages, or whether there is something odd about Squeak, but it is amazing how things that made no sense the night before, are suddenly blindingly obvious the next morning!

Objects and messages - that's your lot

I had a problem, yesterday, trying to work out what -> meant. I came across it in the Seaside tutorial and couldn't find any reference to it in my various Squeak books.

Fortunately, the Beginners list offered an immediate answer. It is an infix operate for creating an Association. It is a bit like typing 1 @ 1 would return a Point. The answer is obvious, after the fact, but I was confused at the time.

Thinking about why I was confused made me realise that I still hadn't fully understood the concept of objects and messages, or perhaps to put it more accurately, I hadn't understood the fact that there really isn't anything else in Squeak. So, if what you are looking at is not an object, then it has to be a message. And, if it is a message, try typing it into a method finder window and see what it returns.

Seaside - wow that really is clever stuff

I had held off experimenting with Seaside because I - wrongly - thought that I needed to learn Squeak first. What changed my mind was a brief exchange I had, on the Beginners mailing list, about Morphic, Tweak and other UIs. I suddenly realised that Seaside was - in part - another rendering platform and therefore equally good for learning Squeak with.

Wow, having installed the system, I am really impressed. I will detail the impressive bits as I go along, but if you have been waiting to learn Squeak before tackling seaside, don't hold back.

And, we are back :-)

I decided to give myself a present. I have carved out some time - over the summer - to dive into Squeak. I finally realised that it just wasn't going to happen otherwise. So, this blog will now contain a lot more 'notes to self' and 'ahh, so that's how it works'.

13/02/2008

Lively - Squeak for Javascript?

Dan Ingalls gave a really interesting presentation about his work on Lively. You can see the video here.
I have been following Lively for a while - as a side point, running it in Safari makes a heck of a difference to performance (not sure whether that also applies to Safari on a PC). You definitely don't want to judge the product based on Firefox.

Anyway, what really struck me about the video was the way Dan could execute javascript in the environment. Anyone who as played with Squeak will be immediately struck by the similarities. In fact, when you dig down into the code, the whole object model looks amazingly similar. I am going to have to find the time to play with this!

11/02/2008

Getting a handle on objects from the Flaps

one of the things I really like about the Squeak environment is the flaps. Being able to pull tools straight into your project really fits the environment I want to create. However, I couldn't work out how to get programmatic control of the objects. Thanks to the Squeak beginners list, I now know the answer.

There are three ways to solve the problem:
1. Halo the object and choose inspect. You can then send messages to the object via the bottom pane of the inspector window. That's good, but it wasn't quite what I wanted because it didn't let me use the workspace to build up some code (although I could have done the coding in the inspector window, that wasn't really how I wanted to work)

2. Assign self to a global variable. This occurred to me as I was doing something else. The basic problem was how to get a reference to the object into the workspace I was using. The object must exist in the current project, but I didn't know where to start looking for it. So, if I did something like this Temp1 := self. in the inspector, then the object had just been assigned to a global and I should be able to reference it from anywhere - works nicely. However, I then started worrying about my Smalltalk dictionary getting filled up with rubbish. I am a minimalist at heart, and don't like 'stuff'. After some digging around I found that remove: object won't work in a dictionary, but removeKey: #symbol does. So that's useful to know too.

3. Finally, the way suggested in the list was to turn on the feature in the workspace (click on the menu item in the window bar) which supports "textual reference to dropped morph" or something like that - don't have the image in front of me. This means that when you drop the morph on the workspace, the morph's 'name' e.g. textbox3012 is written into the workspace. This reference can then be used as the object handle. This is a great solution except for the fact that if the morph name has a space in it, then the reference won't work. I must find out a bit more about this at some time.

10/02/2008

E Toys - pointless distraction or pure genius

The problem with Squeak is that it looks like a rather poorly designed system for kids. This impression is reinforced by the E-Toys system which - on the face of it - looks like a very simple colouring book.

However, as I begin to understand the system a bit more it is gradually dawning on me that E-Toys is actually a very interesting prototyping/programming tool.

Have a look at this while I go and do some experiments ;-)

Which version of Smalltalk?

I started playing with Smalltalk years ago, and although I was always intrigued by the system, I never seemed to have the time to really get to grips with it.

I realised that a big part of the problem was that I hadn't found a good guide book to help me along the way. Well, the Squeak by Example book is excellent, and that means that Squeak is now my version of choice. However, I don't plan to stop there. I am gradually switching over to using Macs as there is a wonderful language called Fscript which is basically Smalltalk for OSX. So, once I have got a better understanding of Squeak, I plan to jump into Fscript.

Getting started - Squeak by Example

Hello and welcome to my new blog. I am planning to use this space as a way of capturing my thoughts and experiences as I attempt to learning Smalltalk.

If you would like to follow along with me, I strongly suggest you download a copy of Squeak by Example, as that is the main text I am using. You can get a copy of the book here