Rails Test Prescriptions Blog

Keeping Your Application Healthy Since 2008

Getting Back to Smalltalk

This week I wound up trying to put together a sample “real-world” problem suitable for use in an automated web thing aimed at potential new hires. Of course, any actual “real-world” problem would be have too many extraneous details to make it suitable given the constraints of the web thing, but trying to create the illusion of real-world-ness was kind of fun.

Since this seemed like sort of a weird way to spend a day or two, I decided to make it weirder by implementing both my solution to the problem and the code to generate test data in a language I don’t use every day. Just for the heck of it, I picked Smalltalk (Specifically, Pharo), the first time I’ve written Smalltalk code in anger for… hmm. Let’s see… I wrote the intro chapter to this in about 2000, and even then it had been a couple of years since I really wrote something in Smalltalk. (For the record, my other choice was Clojure, but I seem to have some weird mental block about getting started on a Clojure project. Someday soon, though.)

Anyway, Smalltalk was interesting because the environment is so different from anything else going and because I really haven’t used it in so long, I was curious to see whether my reactions to the Smalltalk environment would be any different given how long it’s been. For example, the last time I worked in Smalltalk, SUnit and TDD wasn’t a thing.

Overall, successful experience. I was able to actually write the program. It probably took me a little longer than it would have in Ruby, just because I was a bit rusty and the Pharo UI was a little unfamiliar. But it works, and most of the code isn’t bad – it got a little ragged toward the end. Here are a few random notes about the experience:

Language Structure

Whatever the line between a “scripting” language and a “normal” language is, Smalltalk is on the “not a scripting language” side of it. Smalltalk is very much a purist language with a small, consistent syntax, and not a lot of the sugar that you get used to in the Ruby/Python/Perl neighborhoods. Method names tend to be longish, and although the environment encourages short methods, basically there’s more typing in Smalltalk than in the equivalent Ruby.

Smalltalk was created almost completely outside the C/C++/Java family of programming languages, which combined with its pure structure makes it feel somewhat alien. And I say that as somebody who likes Smalltalk and genuinely enjoyed working in the environment.

For example:
* The first element of an array is index 1, not index 0. Which, honestly, makes more sense.
* Smalltalk doesn’t have operator precedence, and is evaluated strictly left-to-right, so a mathematical expression like 2 + 3 * 4 will not give you the result you would get in, say, every other programming language ever.
* Smalltalk doesn’t use the dot-notation for method calls, instead, the dot is a statement separator. It has keyword arguments, as later borrowed by Objective-C. Strings are single quotes, double quoted strings are comments.

Then you get other things like all the boolean and loop logic being managed by the library rather than the syntax. Really, the only thing the syntax manages in Smalltalk is order of operations and a very small amount of literal syntax. There’s a rich set of collection classes, and the names and classes are just slightly off from what you are used to. Takes some immersion to get the feel.

Workflow

The other really unfamiliar thing about Smalltalk is the environment and workflow. Smalltalk source isn’t normally kept in files. Instead, you run a binary image of all the code in the Smalltalk environment. If I’m remembering correctly, a Smalltalker working on multiple projects would have a separate image for each project. (There are mechanisms for teams working together, but I don’t think they are very standard, and I’m not all that familiar with them.)

The thing about Smalltalk is that you are always inside the environment. The idea, for example, that Ruby is super-flexible in what it allows you to do at run-time is a trivial point in Smalltalk. Everything is at run-time, because the phone call is coming from inside the house, so to speak. Of course you can create classes and methods at run-time. If you couldn’t, the whole system would be unworkable.

The image contains your code, the entire Smalltalk system, and the state of all the objects therein. Smalltalk typically also has a mechanisms for export/import of source, and also for internal version control. I think it’s fair to say that dealing with the workspace is at best counterintuitive when you are used to dealing with text editors and files.

Your main interface with the Smalltalk system is the code browser, which allows you to view any class and method in the system. One method at a time. Quick Quiz – what’s the Smalltalk keyword to define a method? Trick question. Smalltalk doesn’t have one. Smalltalk just knows that the things you type into the code browser are methods, and the first line of a method is its name. Code browsers are very neat, but again, using them effectively is a skill – a big step is realizing you can have more than one of them open at a time.

What’s interesting to me are the places where the Smalltalk environment is still ahead of my regular code environments, and where it’s behind. On the plus side:

  • When you save a Smalltalk method, the code browser verifies that it’s syntactically correct before allowing the save. If you are calling a method or using a variable that doesn’t exist, you have to okay it – in some circumstances, you even have the ability to create the method or variable as part of the save process.
  • The browser has easy access to all old versions of a method that you are looking at.
  • It’s very easy to see places that might call the method you are writing.
  • The browser also has some powerful refactoring functionality built in.
  • Integration is amazing, since everything is running. To give one example, the code browser knows which methods are SUnit tests, and they display in the browser with a red/yellow/green/gray indicator of their current state (error/failure/success/not run). Individual tests can be run separately easily in the browser, and since they environment is already loaded, the tests run in an eye blink.
  • On a related note, the debugger is famously awesome. From a breakpoint, you can see the state of all variables, edit values, edit code, all nice and easy.
  • You also can create workspaces, which are just blank code windows that you can execute arbitrary snippets in, like a iRb loop, but a bit more flexible.

But there are some missing pieces:

  • The code editor itself isn’t as powerful as you are used to if you’ve been using Vim or TextMate or, hell, anything. I’m a big “typing is not the bottleneck” kind of guy, but still, I would have loved some macros or snippets or something.
  • The one-method on display per code browser limitation is, well, limiting. You can have multiple code browsers open, but that takes up a lot of real estate. Tabbed browsers, split windows, that kind of thing would be kind of nice.
  • Intellectually I know that it’s really hard to lose changes in a Smalltalk image, but it still feels fragile to me not to have files readable by an external tool. UPDATE: I could have been clearer about this. Smalltalk doesn’t save changes in the image as such, instead it saves all your changes and lets you play changes back. I was trivially able to recover about 30 minutes of work after a Pharo crash, simply because all the changes were recorded and easily placed back in the image. The Smalltalk setup is effective, but feels different from the way I tend to think about their projects.

One interesting feature of the browser based editing environment is that it’s very easy to create a new method that is based on an existing method. You don’t even have to cut and paste, just browse to the existing method, change its name and save. Smalltalk will create a new method based on the new name.

This is very nice from a getting code in the system standpoint, but it seems to have the side effect of encouraging more duplication in the system than I might be otherwise comfortable with. The effect is confounded by the fact that you can only see one method at a time in the browser, making it difficult to scan for duplication.

What’s not getting across here is how smooth the workflow in the small is when you really get the rhythm going. It’s an environment that really suits a “make a small change, evaluate the change” process. In some ways, it’s not surprising that the test-first movement would have gotten serious momentum in Smalltalk, test-first is just a formalization of the way a good Smalltalk programmer interacts with the system. Plus, I’m a purist in so many ways, and even though the code takes a little getting used to, I like the way it turns out.

So, successful test. Would try again. I still want to try something with Seaside one of these days just to see what that’s like.

Advertisements

11 responses to “Getting Back to Smalltalk

  1. Sean DeNigris December 29, 2011 at 10:49 am

    Great post! I switched from Ruby to Pharo two years ago, and you really captured the feeling. If you use autotest, next time try “AutotestDashboard showAutotestDashboard: true”, which runs related tests every time you accept a method in the browser! As far as image vs. files, I went kicking and screaming all the way, but now I’m actually annoyed by the unnecessary complication and context switching of files. I’m totally with you on the macro/snippets thing; I’ve been playing with the idea a little, but nothing shareable yet. And boy do I miss my vi bindings! (There is a project that adds them to workspaces and it’s on my todo list to port it to Pharo).

    • fox December 30, 2011 at 12:18 pm

      😀 I really like how smalltalk is based on a few principles and how simple the language is (once you understood OOP). But two things I don’t like are VMs and images. VM are most of the time a large overhaed and images are a intransparent so that you never know how many hidden things you carry along with you. When you compile a file you can always be sure that there is nothing that is not based on the content of the file (humans readable) or on the behaviour of the compiler (mostly stable software).

      • Sean DeNigris December 30, 2011 at 9:27 pm

        Those are two of the things I like best 😉

        But they took me a *long* while to get used to, and of course there are tradeoffs. The VM lets me pop a USB stick with my app into any computer I’m likely to find throughout the world and run it. It also let’s me optimize bottlenecks by writing them as a C plugin to the VM. Also, the new JIT VMs are orders of magnitude faster in some cases, and in any case I’ve never noticed any speed problem. The final cool thing about the VM, especially in Squeak/Pharo, is that it is written in a subset of Smalltalk that gets translated to C, which means it can be coded and simulated in the image.

        As for the image, I can’t live without the live, open, dynamic environment it brings; and enjoy the freedom from files. Also, many Smalltalkers constantly (like every day maybe) load their code into a new image to combat the “hidden things” problem. This is especially easy with Metacello, a recent package management tool; and a menu of easy persistence options to bring the data along with the code.

  2. Christopher Oliver December 29, 2011 at 9:00 pm

    Ocompletion saves a fair bit of typing, and as with emacs, the editor is yours to change. As far as adding a method to a class, it’s not a trick question at all: see http://pastebin.com/ZESQwyZk

    The browsers are invoking methods just like everyone else.

    • noelrap December 29, 2011 at 9:17 pm

      Right — I get that about the browsers, that was my point. In the browser you don’t have to declare a method to be a method, it just is one because the browser knows to compile it to one.

  3. herrorygar December 29, 2011 at 11:01 pm

    Great post – I’ve been wanting to try something in Smalltalk for awhile! It’s nice to hear about somebody using it in a modern context, especially after coming from something like Ruby.

    I have to disagree with you, though, about array indices starting at 1 being more sensible. Even though, in all fairness, most languages that are interpreted or have a significant runtime don’t use the classic memory scheme, I still think of arrays as offsets from a given memory index. No offset = first element. =)

    • Tim Coffey January 7, 2012 at 11:08 pm

      Better to use OrderedCollections and IdentityDictionarys, etc, instead of using simple Arrays w/integer indexes. using symbols/hashes as indexes in IdentityDictionarys is also far more readable and descriptive of what is in that dictionary.

  4. Isaac Gouy December 30, 2011 at 8:33 am

    > but it still feels fragile to me not to have files readable by an external tool

    The changes log is a plain text file – it contains all the code changes and new code you’ve added to the image.

  5. elviejo79 December 30, 2011 at 9:23 am

    Just for some of your readers that might get confused
    SUnit and TDD got started in Smalltalk.
    Kent Beck did it in that environment and later wrote JUnit and from there became popular.

    Some times is surprising to see how many contemporary techniques were invented in smalltalk a couple of decades ago.

    • Ben Meyer December 31, 2011 at 12:23 pm

      If you look at trends in languages many languages are converging on smalltalk.
      I had bought the ‘Patterns’ C++ book, and other self-help programming books a while ago and realized many workarounds are not needed in smalltalk due to closures and other reflective capabilities. If you have a highly reflective language and good unit test coverage, static typing just gets in the way of clean code. I do agree with others that the ‘image’ is something that is hard to become accustomed to (it’s OK for individuals)– but probably hurts smalltalk adoption by smaller teams who’d prefer generic source control.

  6. sebastian January 16, 2012 at 11:53 am

    Nice post!

    It’s true that it needs some immersion to get the feel but once you can feel in The Zone, it’s great.

    About the missing pieces:
    1. Editor. True, why that happens? two reasons (a) we probably need more people that cares about usability and gets it and (b) all methods use to be too short to justify fancy editing so it never gets prioritized
    2. Browser. One usually gets used to have open N browsers as a (pretty decent) workaround. A guy has made a framework to make browsers so if you have a great idea on how to redesign the developing experience its only a matter of design and dedication. This other guy has made tODE, an interesting approach to the problem: http://www.youtube.com/watch?v=FGkdXwGtfd8 he could use the help of a designer but developing a seaside application directly on the browser at least sounds interesting.
    3. Source. The source code you usually save it in Monticello packages (Smalltalk’s Git commits) and, as you mention, it’s also all in the changes file. To be practical, if you save your code in packages, then you save the image and you are using OSX’s TimeMachine, then you are super safe.

    Keep writing and experimenting!

    PS: here is an essay I wrote about why I’m using Smalltalk
    http://sebastianconcept.com/brandIt/10-reasons-why-im-using-smalltalk-for-airflowing

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: