Discover code contracts by visualizing objects in the GTInspector

Understanding a software systems can be a daunting task in particular when many intricate objects are involved in the setup.

In this story, I look at the Rubric text editor in Pharo, and I try to understand what it takes to build a live syntax highlighting and editing for various syntaxes.

I knew where the code was (in the Rubric package), and I knew that it has support for Smalltalk editing and that for highlighting Smalltalk syntax it uses the Shout library. Essentially, I needed to figure out how Smalltalk is being handled to have a basic understand of what needs to be done for other languages. But, how are the pieces put together?

The video below recorded my journey.

By reading the code, I found that Rubric has decorators, and in the hierarchy I even found the RubShoutStylerDecorator class which seems to be what I was looking for. However, the problem was that nobody seemed to instantiate this class. Was this dead code? Then how is the syntax highlighting working? I was stuck.

I then chose another route: look at a real example. Rubric comes with many examples (in the RubTextAreaExamples class) of how to use the editor in practice. I found the example for setting up a Smalltalk-specific editor, and inspected the object. Browsing a bit in the inspector revealed that there are too many instances to look at.

Thus, rather than continuing to browse manually through all instances to find the instances that look to handle Smalltalk-specific use cases, I chose a less conventional route: visualization. Because I knew that all objects I cared about are likely to be in the Rubric package, and that all those classes start follow a Rub* naming convention, I wanted to limit the visualization only to these classes.

Essentially, I needed to build the graph of all objects that could be reached from the current morph. For this purpose I used the DeepTraverser infrastructure, and mapped it on a Roassal visualization.

| view |
view := ROMondrianViewBuilder new.
self
     withDeep: [ :each |
          (each class withAllSuperclasses) flatCollect: [ :cls |
                    (cls instVarNames collect: [ :iv | each instVarNamed: iv ])
                         select: [ :obj | obj class name beginsWith: 'Rub' ] ] ]
     do: [ :each |
          view shape label.
          view node: each ]
     relationDo: [ :from :to | view edge: from->to from: from to: to ].
view horizontalTreeLayout.
view 

Visualizing-objects-in-the-gtinspector.png

Through the picture, I discovered that RubShoutStylerDecorator actually does get instantiated. This could only mean that some reflection mechanism was being used. Going back to the code with the new hypothesis in mind I could easily find that the class was indeed looked up via reflection.

Traditionally, IDEs offered much more support for navigating code than navigating objects. As a consequence, developers tend to assess the system mainly by navigating static code, even though much of the contracts are only apparent in the presence of real objects.

Objects are your friends. It’s time to redefine the assessment patterns.

Posted by Tudor Girba at 6 February 2014, 7:21 am with tags assessment, moose, pharo, analysis, tooling, story, spike link
|