Dissecting the GTInspector

The number of lines of code used to be the software metric. Engineers counted software size based on it. Managers counted productivity based on it. We now know better. Lines of code is not a real relevant measure for software systems. Unless, of course, it is relevant.

One situation when it can be highly relevant is when you want to convey tinniness of code.

For example, let’s look at the implementation of the GTInspector. In its current state, it is tiny. How tiny?

The implementation of GTInspector can be found in the GT-Inspector package. To count the lines of code in a Pharo package you can use the following snippet:

package := RPackage organizer packageNamed: ‘GT-Inspector'.
(package definedClasses sumNumbers: #linesOfCode) +
   (package allDefinedExtensionMethods sumNumbers: #linesOfCode). 

As you can see, we counted both the lines in the classes defined in this package and from the method extensions from this package. Evaluating the snippet raises 661. 661 does not sound like much, but perhaps it can sound even less if I tell you that a significant part of these lines of code also represent custom presentations. How significant?

The GTInspector customizations to various objects are provided directly in the corresponding classes as method extensions. Of course, there are some base extension methods that are essential for GTInspector, but those are all in Object. Thus, to learn the size of the extensions, you can execute the snippet below:

(package allDefinedExtensionMethods reject: [:each | each methodClass = Object])
   sumNumbers: #linesOfCode.

The result is 348 lines of code (these measurements include comments as well).

Would you not say that these numbers denote tinniness? Let’s look at the numbers again.

Base Extensions Total
313 348 661

Let's put them in perspective: suppose you can read one line of code in two seconds, if you would want to read the base implementation, it would take you about 10 minutes. And, if you would read the extensions, it would take you another 11 minutes.

Why would you want to read this code? You might want to read the base code just to see how an inspector can work, and you would want to read the extensions to see examples that can inspire you to extend the inspector for your own objects.

Both of these exercises take less than the magical 15 minutes, so you can do it just before going to lunch.

But, how would you go about reading the code? In particular, how would you read the code related to the inspector extensions?

One possibility would be to use the code browser. This would imply, clicking on each extended class from the GT-Inspector package, then finding the extension methods and then reading that code. This would be rather tedious, error prone as you would lose the other extensions that are not in the package and it would certainly lead to more than 15 minutes.

Looking closely at these methods, you can see that they are annotated with a annotated with #gtInspectorPresentationOrder:. So, another approach would be to look for the senders of the #gtInspectorPresentationOrder: symbol, but this would give you a couple of extra methods you do not need:

  • the extensions defined in Object (those are part of the default implementation and thus they are noise when you want to look for extensions only), and
  • the inspector method that looks up the pragma in order to construct the presentations.

What you want is a dedicated browser for this task. To find all methods annotated with this pragma that are below Object, you can simply use the snippet below:

Object
   deep: #subclasses
   flatCollect: [:each |
      (Pragma allNamed: #gtInspectorPresentationOrder: in: each) collect: #method ]

(Note how the use of DeepTraverser makes the expression readable)

Now, you can simply inspect the result and browse the code directly with the inspector.

Extensions.png

The inspector solves the dedicated browser problem with a code snippet and two clicks (one on the items tab, and one on the source tab). It might not appear to be a fancy tool, but it does the job solidly.

But, let’s go back to our original topic. We learnt that the inspector is tiny. Both the base implementation and the extensions are tiny. Really tiny.

Why should you care? Well, if you want to customize the tools for your objects, cost matters, and tiny translates into inexpensive. Of course, you still have to learn how to do it, but here too tiny plays a crucial role because you can actually read the code.

It now depends only on you to find those first 15 minutes.

Posted by Tudor Girba at 22 December 2013, 11:42 pm with tags tooling, analysis, moose, pharo link
|