Searching for a morph glitch, or how assessment at the speed of thought looks like

Recently, I discovered that Glamour, the Moose browsing engine, ships with a little UI glitch: when rendering a table, the splitter between column overlaps with the column content. For example, in the screenshot below, the F in False cannot be distinguished.

Glitch.png

I noticed this problem inadvertently after I switch the splitters color from transparent to gray when working on the Whitespace theme for Pharo. I wanted to influence only the splitters between panes, but somehow the table drawings were impacted as well.

The question was how to find the root of the issue. The straightforward solution would have been to start reading code and hope to stumble across the problematic snippet. Obviously, given that I am writing about this experience on the humane assessment blog, I chose a different approach.

So, let's start with the data I had at my disposal. I had an easy way to reproduce the problematic rendering, but I did not know much about the internals of the morphs. To learn the class of the problematic morph, I used the halos and inspected the morph. I found out it was that the class was MorphTreeResizerMorph. While inspecting the morph object, I also noticed that its width was 3 pixels.

Glitch-object.png

Essentially, with these simple actions, I learnt that I should likely look at some morph objects that use the literal 3 somewhere in the code. Armed with this intuition, I wrote a little script:

allMethodsWithLiterals := Object withAllSubclasses flatCollect: [ :class |
  class methods select: [ :method |
    method parseTree allChildren anySatisfy: [ :each |
      each isLiteralNode and: [each value = 3 ] ] ] ].

This raised 2313 methods. To make it easier to browse, I grouped them by classes and I chose to focus on the Morph classes.

(allMethodsWithLiterals groupedBy: #methodClass) associations
  select: [ :each | each key isKindOf: Morph class ]     

This got me to 44 classes. I went through the names, and saw that I have four MorphTree* classes. I chose to focus on these. Out of the six methods, one looked striking:

Glitch-method.png

MorphTreeMorph>>resizerWidth
  ^ resizerWidth ifNil: [ resizerWidth := 3 ]

Looking at the senders of resizedWidth raised three hits, of which one was the obvious root problem:

Glitch-root.png

Taking a step back, I encountered a problem from the unknown territory of the underlying technology, and I could within a space of minutes to identify its cause. The solution still requires some thought. However, now all the pieces are in place and I can focus my energy on the building part rather than on the figuring out part.

To achieve this, it was critical to be able to inspect the object that exhibited the problem exactly when it exhibited the problem. In other words, it was important to have the inspection tools available at runtime. It was also important to be able to query the system, instead of relying on clicking tools. And finally, it was important to browse the results of querying and iterate.

Reading code should never be the first option for scenarios like this. First, this should be the development environment should focus on providing the right tools precisely so that developers should not have to read as the main means for assessment.

Programming at the speed of thought must include assessment at the speed of thought. When it does, you truly get live programming. That is how Pharo and Moose change the programming landscape.

Posted by Tudor Girba at 20 September 2013, 8:40 am with tags pharo, moose, assessment, story link
|