© Alexandre Bergel 2022
A. BergelAgile Visualization with Pharohttps://doi.org/10.1007/978-1-4842-7161-2_4

4. Agile Visualization

Alexandre Bergel1  
(1)
Santiago, Chile
 

Visualization is central to many domains, including data analysis and artificial intelligence. Nowadays, it has never been so easy to write a visualization. Most programming languages come with several libraries dedicated to visualizing data. As such, the technical aspects necessary to implement a visualization engine and to build a visualization are now largely understood. Despite all the experience gained by the software engineering community in building efficient visualization engines, there are still some challenges that have been poorly addressed globally. In particular, one of the challenges that needs to be properly addressed when designing a library to visualize data is being able to integrate visualizations in an existing production environment. Connecting and integrating one or more visualizations in a given environment is an important and non-trivial challenge. Agile visualization, as promoted by the Roassal visualization engine for the Pharo programming language, provides a solution to that problem, which is the topic of this book. This chapter develops the idea of Agile visualization.

All the code provided in this chapter is available at https://github.com/bergel/AgileVisualizationAPressCode/blob/main/01-04-AgileVisualization.txt.

Visualizing Classes as a Running Example

This chapter incrementally builds visualizations of a software component source code. From a data point of view, a software source code is a complex piece of data: source code does not easily fit in a .csv file and standard data analyses techniques cannot be run on software source code. Visualizing software source has many applications, ranging from software quality assessment to reengineering the software architecture. As such, visualizing software source code is a reasonable and non-trivial task.

Let’s begin with a simple example. Consider the following code, executable within the Pharo Playground:
"The variable classes contains the classes we would like to visualize"
classes := Collection withAllSubclasses.
"A canvas is a container of graphical shapes"
c := RSCanvas new.
"Each class is represented as a box"
classes do: [ :aClass | c add: (RSBox new model: aClass) ].
"The width of each class indicates the number of variables defined in the class"
RSNormalizer width shapes: c shapes; from: 6; to: 20;
    normalize: #numberOfVariables.
"Height of each class represents the number of methods"
RSNormalizer height shapes: c shapes; normalize: #numberOfMethods.
"A class color goes from gray to red, indicating the number of lines of code"
RSNormalizer color shapes: c shapes;
    from: Color gray; to: Color red; normalize: #numberOfLinesOfCode.
"Vertical lines indicate the inheritance relationship"
RSLineBuilder orthoVertical
    canvas: c; withVerticalAttachPoint; color: Color lightGray;
    connectFrom: #superclass.
"Use a tree layout to adequately locate the classes"
RSTreeLayout on: c nodes.
"We make all the classes draggable and with a contextual popup window"
c nodes @ RSDraggable @ RSPopup.
"The whole visualization is zoomable, draggable, and shapes may be searched in it"
c @ RSCanvasController.
After typing this code in the Playground, execute it and inspect its result using Cmd+G (macOS) or Ctrl+G (Windows/Linux). The result is shown in Figure 4-1.
../images/489192_1_En_4_Chapter/489192_1_En_4_Fig1_HTML.png
Figure 4-1

Visualizing classes

Figure 4-1 represents the class hierarchy of the Collection component of Pharo. The Collection component is an essential part of Pharo and consists of a set of classes to build collections, lists, and arrays of Pharo objects. The visualization uses a simple metaphor in which each box is a class. Lines indicate inheritance, and in particular, a superclass is located above its subclasses. The height of a box indicates the number of methods defined in the represented class, while the width represents the number of variables. The color of the boxes ranges from gray to red, indicating the number of lines of code of the represented class. A tall and large box indicates a class with many methods and is defined by many lines of code. Conversely, a small gray box indicates a class that doesn’t have many methods or variables and has only a few lines of code. This visualization gives an overview of the source code distribution over the class hierarchy. It also enables you to spot exceptional entities (i.e., classes that are visually very different from other classes).

We will now detail the script. The classes variable refers to a set of Pharo classes. Each class is represented as an RSBox object, added to the c canvas. One important feature of Roassal is support of the connection between a graphical shape and the object model represented by the shape. This connection is expressed using the model: message, as in the expression RSBox new model: aClass. The use of the model: message makes the connection explicit between an arbitrary object (e.g., a class in this case) and the graphical shape.

To define the shape and color of each box, you use normalizers, which use the model object. A class in Pharo answers to many different messages. For example, the String numberOfMethods expression gives a number greater than 300, which is the number of methods defined in the String class. The number of methods defined in the String class depends on the considered version of Pharo. Similarly, you can send the numberOfVariables, numberOfLinesOfCode, superclass message to a class to obtain the number of instance variables, the number of lines of code, and the superclass, respectively. Lines are built between classes to indicate inheritance using a dedicated object, the RSLineBuilder. The classes, positioned in the canvas using the tree layout, are draggable and the class name appears as a popup when the mouse cursor hovers a class.

Example in the Pharo Environment

The provided code example looks relatively standard, and the same visualization can easily be built using any modern visualization engine. If you are familiar with a library such as D3.js or Matplotlib, you might say: “Well, I can do the same”. This is true up to a point. The real benefit of Roassal is not the API. Beneath the surface, Roassal offers a number of features to make the visualization navigable and facilitate the integration within the Pharo environment.

A graphical shape in Roassal is linked to an object model. The simple expression RSBox new model: aClass makes a box a façade of a class, and this way of representing data is very different compared to the way other engines operate. By having the connection between a graphical shape and the object model explicit, you can click a shape to inspect the object model. In this case, you can click that box to open an Inspector on the clicked class. The Inspector provides a number of built-in visual representations for the inspected object.

You will now define a new visual representation of the call graph of methods defined in a class. Consider the following method defined on the class named Class, itself contained in the 'Kernel-Classes' package :
Class>>visualizeCallGraph
    "Visualize the call graph of the class' methods"
    | c eb shapes |
    shapes := RSBox models: self methods forEach: [ :box :cm |
        box color: #blue ].
    RSNormalizer size shapes: shapes; normalize: #numberOfLinesOfCode.
    shapes @ (RSPopup text: #selector) @ RSDraggable.
    c := RSCanvas new.
    c addAll: shapes.
    eb := RSLineBuilder arrowedLineWithOffset: 0.2.
    eb moveBehind.
    eb shapes: c nodes.
    eb canvas: c.
    eb withVerticalAttachPoint.
    eb connectToAll: #dependentMethods.
    RSTreeLayout on: c nodes.
    shapes @ RSHighlightable withLines.
    ^ c @ RSCanvasController
This method can be invoked on any class. For example, inspecting the String visualizeCallGraph expression visualizes the call graphs of String’s methods. The visualizeCallGraph method first creates a box for each method. Lines are then added to indicate invocations between methods. You now have to notify the Inspector framework to call visualizeCallGraph when inspecting a class. The Inspector framework can easily be extended with the following method:
Class>>>inspectorVisualization
    <inspectorPresentationOrder: 90 title: 'Callgraph'>
    ^ SpRoassal3InspectorPresenter new
        canvas: self visualizeCallGraph;
        yourself
The inspectorVisualization method creates a visualization showing the call graph when a class is inspected.
Class>>>inspectorVisualizationContext: aContext
    "Remove the evaluator pane"
    aContext withoutEvaluator
Now that a visualization is defined for classes by extending Class, clicking classes rendered by the very first script of the chapter shows details of the call graph. This connects the two visualizations. Similarly, a method can be selected to display a wide range of information, including the byte code and source code. Consider the example in Figure 4-2.
../images/489192_1_En_4_Chapter/489192_1_En_4_Fig2_HTML.png
Figure 4-2

Visualizing classes

In Figure 4-2, the most-left pane represents the visualization of the classes given in the initial script. In this first visualization, the Interval class is selected. The selection displays the method call-graph at the center. In the call-graph, the collect: method is selected, and it shows the method source code on the right side.

To summarize, you have independently built two visualizations. The Inspector framework exposes them in a very convenient way while supporting their navigations. You can jump from the first one to the second one, even their scripts are independent.

Closing Words

Imagine being empowered with a tool to easily prototype visualizations and to embed them in your work environment. If the cost of building visualizations and their integration is low enough, you would likely write more visualizations more frequently. As soon as visualizations are easy to write and use in daily tasks, visualization will pop up like mushrooms in your production environment. We define the notion of agility in data visualization as lowering the production cost of a visualization, and lowering the cost of integrating visualization in a production environment. Agility turns a beautiful picture in a tool to enable practitioners to act upon a valuable domain and enjoy immediate feedback.

Roassal3 is the result of more than ten years of hard work. The Pharo and Smalltalk communities have played an important role in shaping the API and identifying the key aspects of what Agile visualization is.

What Have You Learned in This Chapter?

This chapter illustrated connecting two independent visualizations, a cornerstone of Agile visualization. In particular, the chapter covered:
  • Visualizations can be defined for any object, by simply defining visualization methods on a class. A visualization is hooked into the Inspector framework using the pragma inspectorPresentationOrder:title: and using the SpRoassal3InspectorPresenter class. Several visualizations can be defined in a class.

  • Clicking a shape opens a new pane in the Inspector and offers a visualization defined in the class of the selected object.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.119.167.87