Twitter icon.
Random notes on software, programming and languages.
By Adrian Kuhn

Archive for the ‘Smalltalk’ Category

Superpowers in Library Design


Wednesday, November 25th, 2009

When designing libraries, using superpowers can be for the good.

Superpowers are language features, so powerful that even seasoned developers are likely to used them for the evil … wreaking havoc on maintainers and co-workers alike. Just think of hooking into calls to missing methods, modifying classes at runtime, or even rewriting the call stack of a runnning program!

I have first heard the term superpowers being used in 2008, at an OOPSLA workshop by Martin McClure and Travis Griggs. In a room full of hackers and language designers, everyone would tell about their most spectacular use of obscure languages features and then get voted whether their use was for the good or for the evil—most were voted for the evil!

Some languages ship without superpowers at all. The fear that programmers are gonna use these superpowers for the evil is understandable. However, excluding superpowers from a language may fatally limit the power of library features.

Just think of object serialization: deserialized objects from a binary stream would be impossible without the superpowers to allocate objects without calling any constructor, to call private methods, and to change the value of final fields. And in fact, even Java’s ObjectInputStream wouldn’t get along without exactly these superpowers. They are all available to Sun’s engineers (and everyone aware of sun.misc.Unsafe, go figure) but not to Joe Average programmer.

In this post, I’ll show how Niko and me are using Smalltalk’s superpowers for the good of Phexample users.

The initial design of Phexample, boolean expectation matchers had a somewhat awkward syntax, which got soon nicknamed “lolcat syntax” by users

#(Lorem ipsum dolor) should be isEmpty.

the rational for this design was that we saw no other way to provide users with an error message whose text refers to #isEmpty by name! If we change the syntax to #() isEmpty should be true the name of the boolean property is out of reach (ie, not on the stack) when the matcher fails.

RSpec, by the way, does not suffer from lolcat syntax because Ruby’s boolean properties use a question mark rather than starting with a verb. Users can write %w{Lorem ipsum dolor} should be empty? without getting caught in the uncanny valley of DSL design.

The way out of the uncanny valley is to allow user to put the boolean property first, as in

#(Lorem ipsum dolor) isEmpty should be true.

and then, whenever an expectation fails, walk back in both stack and bytecode to recover the property name. There is two challenges here,

  • to walk back in the stack, from where the expectation fails internally to the method’s stack frame where should be true was sent,
  • to walk back in the bytecode, from the current program counter to the call-site that is lexically before the initial #should call.

To make things more complicated, there can be an arbitrary number of domain messages between #true and #should, as for example in negated exceptions.

The first challenge, ie getting back to the stack frame of the DSL call, is solved by walking back the stack until we are outside of the current matcher instance

frame := thisContext.
[ frame := frame sender.
  frame receiver == self ] whileTrue.

thisContext is a pseudovariable, like this and super, that provides access to the current stack frame. That is the stack frame of the above code snipped. Then, we use #sender to walk up the stack until we reach the latest frame outside of the current matcher instance. In the above comparison frame receiver refers to the value of the “self” of the stack frame, and self to the value of the “self” of the code snippet itself. No one said Superpowers ain’t confusing.

The second challenge, ie recovering the property name, is solved by recovering all message sends (ie method call-sites) from the bydecode of the method where should be true was sent

scanner := InstructionStream on: frame method.
sent := Stack new.
scanner scanFor: [ :bytecode |
    sent push: scanner selectorToSendOrSelf.
    (frame pc - 1) <= scanner pc ].

So, frame method now refers to the method where should be true was sent. In this method, we scan from the begin of the bytecode up to where we are, and push all sent messages (ie method names) on a stack. As Niko already mentioned in his “no more lolcats” post: bytecodes in Smalltalk have different sizes, thus we cannot just walk backwards from where we are.

Scanning bytecodes with #scanFor: stops when the last line of the block evaluates to true. Since the current program counter points to the bytecode just after the send-site of true, with subtract minus one when comparing the counter of where we are and the scanner’s counter.

So now we’ve got all message sends on a stack up to true. We keep dropping messages names from the stack, up to and including #should

[ sent isEmpty ifTrue: [ ^'<unknown>' ].
  sent pop == #should ] whileFalse.
sent top isSymbol ifFalse: [ ^'<unknown>' ]
^sent top

which leaves us with the name of the boolean property that was sent before the should be true sequence. Of course, we guard against running out of stack elements while doing so.

Thus now, when executing

#(Lorem ipsum dolor) isEmpty shoud be true.

we get the message text

TestFailure: expected #isEmpty to be true

IM OUTTA YR LIBRARY.ST
KTHXBYE

One-letter method names, good design?


Friday, November 20th, 2009

Sometime short one-letter names are to be preferred as method names.

Don’t get me wrong. Naming conventions are one of the most important achievements of programming culture in the recent decade. No doubt, generalMatrixMultiplication is more readable than dgemm, but sometimes a simple p just beats the hell out of clumsy System.out.println and friends.

Akira Tanaka refers to this as the “Huffman coding” of API design.

The library design also utilize the usage frequency. For
example, Ruby defines p method which is usable anywhere.
It prints arguments for debugging purpose which is easy to
understand for programmers. The method name p is inconsistent
with other methods because it is too short in the sense
of Ruby naming convention. It is intentional because debug
printings are very common. In general, too short names are
incomprehensible and tends to conflict. But p has no such
problem because almost all Ruby programmers knows it.

This kind of naming convention, assigning short names
for features frequently used, are called “Huffman coding”
which term is borrowed from data compression.

He goes on to provide more example. In particular he proposes an API design life cycle, where method names start with full-length English terms and get shortened as they raise in popularity. There is two ways to shorten method names, either down to a single letter, or even more powerful, to pick an operator as its name.

I’ll gonna apply the same to Smalltalk now. For the full story of Ruby’s core API design, please refer to Akira Tanaka’s recent paper “Language and Library API Design for Usability of Ruby” from the PLATEAU workshop at this year’s OOPSLA.

First we define p as follows

Object >> p
    Transcript show: self; cr.
    ^self

the implementation is taken from Travis Griggs’s Out package. Now we can insert a print statement wherever we need debug output.

Printing is not the pinnacle of debugging, so let’s do the same with breakpoints

Object >> h
    self halt

If you are using Pharo, add h to the methods listed in OBInheritanceFilter >> icon:forNode: to make sure our new breakpoint command is marked with a red flag in the class browser.

Next let’s rename OrderedCollection to List

Smalltalk at: #List put: OrderedCollection.

And introduce the << operator for addition

OrderedCollection >> << element
    self add: element.
    ^self

which allows us to write concise code such as

List new << 'Lorem' << 'ipsum' << 'dolor

Next is string concatenation. Such a basic feature that many languages include string interpolation at their very core. Alas, Smalltalk is a bit dated to that regard (at least unless Pharo includes Lukas’s awesome Helvetia one day) and we are left with String >> #expandMacrosWithArguments:, which shall be Huffman encoded to

String >> e: argument
    ^self expandMacrosWith: argument
String >> e: first e: second
    ^self expandMacrosWith: first with: second
String >> e: first e: second e: third
    ^self expandMacrosWith: first with: second with: third
String >> e: first e: second e: third e: fourth
    ^self expandMacrosWith: first with: second with: third with: fourth

And welcome to Phexample’s expectation failure message

'Expected <1p> but got <2p> (using <3s>)' e: value e: expected e: symbol

And eventually, regular expressions. Again such a basic feature that most languages include regex literals at their very core, and again we have to wait for Lukas’s Helvetia until we get the same awesomeness in Pharo. Until then, let’s pirate Groovy’s r syntax

String >> r
    ^self asRegex
String >> =~ regex
    ^self matchesRegex: regex
RmMatcher >> asRegex
    ^self

And, “Hup hup hup, barbatruc”

| regex |
regex := 'a*wesome'r
'Regex are aaaaaaaaaawesome!' =~ regex

Well then

Gofer new
    squeaksource: 'akuhn';
    addPackage: 'Akuhn-Huffman';
    load

Gofer it!

Shoulda use this in Pharo


Wednesday, November 11th, 2009

Phexample is the new black in unit testing for Smalltalk. It extends SUnit with two features: test dependencies, and RSpec-like expectation matchers. Test dependencies are covered on Niko’s blog, who’s developing Phexample with me, as well as on the JExample website. I shall thus focus on expectation matchers here.

Expectation matchers let you set expectations on your object. Expectations are also useful if you just use plain old SUnit test cases. They throw the same test failure as SUnit’s assertion, but are more readable in the source code as well as throw more readable failures messages.

Let’s start with an example.

Get yourself the latest Pharo image and

Gofer it
    squeaksource: 'phexample';
    addPackage: 'Phexample;
    load

then open a workspace and evaluate

stack := Stack new.
stack size should = 0.

this creates a new stack and asserts that its size should be zero. For the sake of the example, let’s evaluate a failing expectation

stack push: 42.
stack top should = 4711.

which raises TestFailure: expected 4711 but got 42 (using =).

There are expectation matchers for all basic comparisons: greater than, less than, et cetera. If you need to negate a comparison just write

stack top should not = 4711.

There are special matchers to set expectations on boolean return values.

stack isEmpty should be true.

alternatively you can write

stack should be isEmpty.

which often reads like LOLCAT SPEAK, but works quite nice with selectors that do not include a verb such as

42 should be even.

Note: matching of boolean expectations is an open issue. We would love to allow you to write stack should be empty, which is not only be more readable but would also allow us to provide better failure messages since we know that you wanted to test isEmpty. However, we fear that breaking Pharo’s senders-of feature as well as rename and other refactorings might not be worth the added value in reabability.

We welcome your feedback on this issue. For example, Oscar suggested to use

stack isEmpty wouldyaknow

however, we are not sure how serious this suggestion is to be taken :)

Back on topic.

If you expect some code to raise an error, just write

stack := Stack new.
[ stack pop ] should signal: Error

and to check the error message

[ stack pop ] should signal: Error withMessageText: 'this stack is empty'.

or even

[ stack pop ] should signal: Error withMessageText: [ :m |
    m should beKindOf: String.
    m isEmpty should not be true.
    m should endWith: 'is empty' ]

which leads us to more matchers, such as

stack should beKindOf: Collection.

which sets an expectation on the type of an object.

Note: it seems sensible to add more expectations that match the dynamic type of objects, such as duck typing and responds-to. We plan on doing this, please let us know if you have a specific use case.

string should startWith: prefix.
string should endWith: prefix.
string should matchRegex: regexString.

are some expectations that you can set on strings.

Certainly there are more common expectations on basic types such as strings and collections. Again, please let us know if you have a specific use case. One of the things we want to do with Phexample is to be driven by user needs rather than planning upfront which features you might need (and nevertheless always guessing wrong…)

A last one, suggest by Lukas. If you expect some code to run within a given duration, just write

[ ... ] should runWithin: 20 milliSeconds.

which aborts with a failure if the given code takes longer than 20 milliseconds to run.

You can find the full list of expectation matchers in the expecting protocols of the PhexMatcher class. All matchers are well covered with tests, thus for plenty examples of their use just refer to the ForExampleMatcher class (which, of course, sublcasses the Phexample class, thus all its test methods start with should..).

PS: current versions of Omnibrowser do not display a test icon for Phexample test methods. This bug has been reported and a fix provided and will thus soon be fixed in your Pharo.

Cyclomatic Complexity in Languages with Closures


Tuesday, November 10th, 2009

Cyclomatic complexity is the number of paths through a program. In programming languages with fixed syntax, this corresponds to the number of IF and FOR statements plus one. If your language of choice features closures, however, things get messier.

Kent Beck twittered this problem today and as I referred him to my implementation in Moose, a Smalltalk analysis tool, I’ll quickly discuss here how Moose deals with it. Since Smalltalk and Ruby are similar, what I discuss might also help to analyze Ruby code.

Note: cyclomatic complexity was first introduced by Tom McCabe in 1976 (the classic paper includes quite some nice graph visualization) and is thus sometime also referred to as McCabe measure or McCabe complexity.

Smalltalk and Ruby both support the definition of user defined control flow constructs through closures. In Smalltalk, even the most basic control IF construct uses closures. However, things are not as simple as just counting the number of all blocks plus one. Closures are either executed for sure (+0), not executed now (+0), maybe executed (+1), or executed xor another (+1 for both taken together).

Let’s consider a bunch of examples:

expression ifTrue: [ ... ]

the block passed to #ifTrue: is only maybe executed, which introduces another code path and thus increases the complexity by one.

expression ifTrue: [ ... ] ifFalse: [ ... ]

either the first block or the second block is executed, which introduces two mutually excluding code paths and thus increases the complexity by one even though there are two blocks.

collection do: [ :each | ... ]

the block passed to #do: is executed for sure except if the collection is empty, which introduces an exceptional code path and thus increases the complexity by one.

[ ... ] on: Exception do: [ ... ]

the first block is executed for sure while the second is only executed if the first block raises an exception, which introduces an exceptional code path and thus increases the complexity by one even though there are two blocks.

collection detect: [ ... ] ifNone: [ ... ]

combines looping with a conditional and thus increases the complexity by two, since it has a total of three paths: the empty case executes the second block, the successful detection case executes the first block, while the failed detection case executes both blocks.

SortedCollection sortBlock: [ ... ]

the block is not executed now and does thus not impact the complexity, there is only one path through above code.

html head: [
  html title: 'Example' ].
html body: [
  html heading: 'For Example'.
  html paragraph: [
    html text: 'Lorem ipsum dolor...' ]].

here blocks are used as part of Seaside’s HTML rendering DSL and are all executed for sure. Thus this example, even though looking the most complex so far, does not increase the complexity – there is only one path through above code!

Furthermore, if you are using selectors as blocks you might even get multiple path without a block, as for example

collection do: #selector

which has a complexity of two but does not contain a block at all!

If counting blocks does not do the job, what then?

In the Moose analysis, we ended up using a predefined list of selectors that increase cyclomatic complexity. Computing the complexity is then just a matter of counting the occurrences of listed selectors in the method body plus one. Since users can add their own control flow constructs such a list of selectors is never complete. There are two options to keep the list up-to-date: manual or automated. Moose currently offers neither option.

An automated detection of complexity-contributing selectors could work as follows: For each new method, if that method passes one of its formal parameters as an argument to a selector that is already in the list, add the selector of the new method to the list. It seems likely that we need further refinement for selectors with more one argument. If there is more than receiver argument, we should keep track of their complexity contribution such that we can tell whether the formal parameters are passed to contribution or non-contribution (or even xor-contributing) receiver arguments. In practice however, manually updating the list (as for example, adding Seaside’s #callback: method) might just be good enough for your analysis.

In Moose we predefined the following list of selectors

branches := #(ifTrue: ifFalse: ifTrue:ifFalse: ifFalse:ifTrue:
  ifNil: ifNil:ifNotNil: ifNotNil:ifNil: ifNotNil:
  at:ifAbsent: at:ifAbsentPut: detect:ifNone:
  on:do: and: or: xor:).
loops := #(whileTrue: whileTrue whileFalse whileFalse:
  timesRepeat: to:do: do:separatedBy: do: collect: select: reject: inject:into:
  detect: detect:ifNone: anySatisfy: allSatisfy:).

and then compute cyclomatic complexity as follows

1 + (selectors intersection: branches) size + (selectors intersection: loops) size

NB, please note how we count occurrences of #detect:ifNone: twice.

Well then, complexity of methods covered.

If we are to compute the complexity of classes or packages, polymorphism messes things up again. About 5% of all message sends are polymorph, ie there is more than one possible receiving method and thus more than one possible path between sender and receiver.

However, polymorphism is not limited to languages with closures but more a general problem of object-oriented languages and shall thus (and because someone needs to bring my son to bed) not be covered here.

ZIP Code Map of Switzerland


Wednesday, October 15th, 2008

Inspired by Robert Kosara’s US ZIP Scribble Map as well as Stefan Zeiger’s ZIP Code Map of Germany, I’ve done a small script that renders Switzerland as a ZIP code map.

Edit: obviously, Robert Kosara has also done a ZIP scribble map of Switzerland, but it is broken. On the US original he explores the correlations of 1000-blocks of ZIP codes and state boundaries. On his Swiss map however, he directly groups the lines by cantons! Which is obviously not the same since we have 26 cantons but only nine blocks of 1000 ZIP codes.

In particular interesting is how the red and brown ZIP code blocks are dividing the canton Valais by its two languages: French and German! (For foreigners: the valais is the huge valley in the south-east which is covered half by red lines and half by brown lines.)

The script is written in Pimon, a small visualization framework for VW Smalltalk. Of course, Pimon has a DSL! The layout- and drawing DSL of Pimon offers a fluent interface that targets the end-users of common Desktop applications. Figures are grouped, aligned and positioned as you would do it in an Desktop application, rather than forcing the programmer to wrap his head around vector algebra with all its x’s and y’s.

The following bunch of Pimon code specifies a tree layout (the same in Java):

TreeLevel >> arrange
    | group |
    group := Group new
        addAll: self treeChildren;
        horizontalWithGap: 4;
        alignTop.
    Group new
        add: self treeParent;
        add: group;
        verticalWithGap: 16;
        alignCenter.
    self resizeToElements.

I started porting Pimon to Java last year, but only got 80% done and thus never released it to the public. However, it is sad to let code decay without being used and maybe the parts that are working turn out to be useful for your projects, thus I published it today:

Method Namespaces for Smalltalk?


Monday, October 6th, 2008

Packaging for Smalltalk is in the air. The topic emerged twice today, first at lunch when discussing Pharo with Adrian and Lukas, and later when Toon showed me CaesarJ. In both discussions, I argued that we need method namespaces for Smalltalk.

Class reopening is a well known, that is extending an existing classes with new methods. In Smalltalk classes are typically reopened using a package extension mechanism, whereas Python and Ruby use “monkey patching” (even though modules might be a better solution).

The problems that arise from these approaches are discussed en detail by Gilad Bracha on his blog, I will thus start media res using a simple example. Imagine that two libraries, A and B, both extend the String class with an #asURL method. Two implementations of the same method are provided. Thus the problem: which implementation is used? Or more precise, on what kind of context does the choice among these two implementations depend?

As it is now in Smalltalk, the latter implementation overrides the former, and thus (assumed that the load order is first A then B) the definition of #asURL in B wins and is always used. This is obviously broken, since all code in A and all clients that expect A’s implementation are likely to fail.

As it is suggested in Classboxes, the – take a deep breath – imports of the lexical scope in which the current thread was started decides which version is picked (based on IM conversation with Alex, this was not obvious to me from his thesis). I have never used this solution in practice, but it does not seem to address the problem at hand. First, usage of libraries is typically not separated by threads, that is, we typically want to use both A and B from the same thread. Second, the principle of least surprise is violated, as we can not tell which version is picked just by looking at the code (ie from lexical scope alone).

There is another approach, taken by C#’s extension methods. Each extension method is scoped within its namespace, that said, the #asULR method of A is picked for all calls from the lexical scope of A, and the #asURL method of B is picked for all calls from the lexical scope of B. Whenever some client code wants to call #asURL, it must explicitly import the method either from A or from B. This satisfies both the constraint that neither A nor B break each other or each other’s client code, and the principle of least surprise.

How can this by applied to Smalltalk?

  • The name of all compiled methods is prepended with the lexical scope, that is the name of the enclosing package. For example, #A_asURL if the method #asURL is defined by the package A, and vice versa for B.
  • The compiler prepends all message sends with the name of the lexical scope of the current method, that is the name of the enclosing package. For example, #A_asURL if #asURL is sent from package A, or #Foo_asURL if #asURL is sent from Client Foo.
  • When a client package, for example Foo, imports #asURL from a provider Package, lets say A, a hidden method #Foo_asURL is created that delegates to #A_asURL.

Of course, Browser, Debugger and Inspector should be updated to reflect and properly display this naming convention. For example, a code editor should show the names without prefix, whereas the debugger probably should display the extensions. The latter could also be controlled by a boolean setting. The generated code should run fine in any image.

API Conformance in Dynamic Languages


Wednesday, October 1st, 2008

As the provider of a library or framework, one of your major requirements it to guarantee a stable API from revision to revision. Your clients do not want an API that suddenly changes between two revisions of the same release.

Given a static language, as eg Java, this isn’t a big issue: define the entire API using interfaces, and as long as your classes compile, your API is complete. The same for your clients, as long as they declare all variables using the interface types, their code cannot accidentally invoke an internal method.

Different picture in dynamic languages, there are no means to guarantee API conformance with the compiler. There is no such thing as a dynamic typing system to prevent you from shooting in your clients feet.

End of the story?

Yes, if you are trapped in the taxonomy of typing system: weak, strong, static, lambda cube, duck duck go. Nope not at all, if you known that tests are to dynamic languages what types are to static languages. Just use the testing framework to reject a broken API, in the same way statically typed languages use a compiler!

In Fame (in the Smalltalk version), we check API conformance as follows:

testPublicInterface
  "Test method to check API conformance of Fame."
  self publicInterface do: [ :tuple |
    | class constructors methods |
    class := self class environment at: tuple first ifAbsent: nil.
    constructors := tuple second.
    methods := tuple third.
    self assert: class notNil.
    self assert: (class category startsWith: 'Fame').
    constructors do: [ :each | self assert: (class class canUnderstand: each) ].
    methods do: [ :each | self assert: (class canUnderstand: each) ]].

This method iterates over a list of tuples t = (class-name, constructor-names, method-names) and asserts that a Smalltalk class with the given name and methods exists. If part of the API is missing, the tests fail.

In addition, we have a pretty printer that uses the same list of tuples to generate human-readable API documentation. Furthermore we could make the IDE aware of this list and, for example, issue a warning when clients violate the API.

I am certainly not the first one to use the testing framework for API conformance. If you know of other projects doing so, please leave a comment.

For.example is Digg proof thanks to caching by WP Super Cache!