GT Documenter is a moldable tool that makes creating and consuming code documentation and tutorials a beautiful experience directly in the IDE. It enables:
- documentation of existing code
- interactive data notebooks
This article explores the use of GT Documenter for creating live tutorials.
Tutorials are part of a developer’s daily life. We rely on them to present others the features of our libraries, learn how to use APIs, or document what our software systems are doing. More often than not, reading tutorials tends to happen outside of our IDEs, mostly within web browsers, given that the vast majority of tutorials are shared using blog posts or various notebooks.
On the one hand, this makes them easily accessible. On the other hand, it makes it difficult, if not impossible, to experiment and follow tutorials directly within our IDEs. And having tutorials available directly inside the IDE can be valuable: there is where our code lives; we can deviate from the tutorial and experiment; we can incorporate and use our code. If we need to go outside of the IDE every time we want to follow a tutorial, the “I” in IDE has failed.
Tutorials outside the IDE
Bringing tutorials within our IDE involves, most of the times, copy-pasting. Often the code might be incomplete, may require some kind of setup, or need more utility methods and classes. Even if we get the code in, there might not be a direct way to execute code snippets and explore the values they return.
As an example, we can look at Exemplifying software, a tutorial covering GT Examples framework, using an application for face detection within pictures. Like most other tutorials from the web it embeds pictures, code snippets and textual narratives. The two screenshots below show two parts of the tutorial.
Following this tutorial step by step, requires readers not only to move code from the tutorial to the IDE, but also know how to define test methods (place them in new classes that subclass
TestCase) and use the Test Runner, steps not explicitly covered by the tutorial. While these missing details are obvious to some readers, they can hinder others. Tutorial authors can easily introduce assumptions that readers will not know about.
Modifying the code of the tutorial to experiment with other scenarios can also be cumbersome. If readers change the code, unless they save the code before using a versioning system, they will have to do some work to find how their current code differs from the one in the tutorial.
Last but not least, tutorials where code is expressed in static documents cannot be automatically tested. Hence, they can get broken, with the actual readers being the ones to find that out. Screenshots manually generated can also get out of sync with what readers will see when following the tutorial, as libraries, applications and environments evolve.
Live tutorials within the IDE
To change the way developers experience tutorials we can make them interactive and available directly inside the IDE through notebooks. This integration should go beyond just embedding the web browser into the IDE, as then the aforementioned limitations are still there.
GT Documenter is a tool from the Glamorous Toolkit that aims to deeply embed notebooks inside the IDE. We use it next to show an example of transforming part of the tutorial Exemplifying software mentioned earlier into a notebook. This notebook can be opened from Glamorous Toolkit using the menu entry GToolkit Scenery → Examples Tutorial — Face API.
Commonly when following tutorials developers need to write new code. For example, the two code snippets from the previous section show an initial version of the method
faceEinstein and a slightly changed version. We can embed the code of this method in the notebook through a dedicated widget that allows us to directly add the code to our workspace. Using two snippets we can embed the initial code of the method and the changed version.
The widget displays the code using multiple views. The Diff view shows us the difference between the current state of the code from our workspace and the code contained by the notebook. If we switch to the Diff view in the first snippet and expand it before starting, we see all the code that will be added to our workspace when clicking Apply. This includes all the boilerplate code needed to make the tutorial work, but not relevant for a reader of the tutorial.
If we apply these changes and switch to the Diff view of the second code snippet, we see that the refactoring consists in adding two lines of code.
Now if we go experiment and change the code of the tutorial we can at any time come back and use the Diff view to see how our code differs from the tutorial. Getting the diff right inside the notebook is possible as the notebook lives inside the IDE instead of being completely unaware of our environment.
Notebooks also include code snippets that can be executed by the reader. For example, as the tutorial Exemplifying software uses a system for face detection, we often need to create objects representing faces that have attached landmarks (position of nose, eyes, mouth, etc.). We can do that by having the code directly contained by the notebook. When the code is then executed, the created object is embedded directly in the notebook and displayed using an object inspector.
For the above code snippet, apart from detecting thrown exceptions, it is not possible to verify that the snippet works as expected. Also reusing this snippet in another part of the notebook requires us to duplicate it. To improve this, instead of embedding directly snippets, a different way to bring code into the notebook is to reference an example method containing that code. Below, the code of the method
faceEinsteinWithLandmarks is embedded in the notebook. When executed, the object returned by this method is shown next to it.
Examples methods are similar to test methods, with the difference that they return an object. As they contain assertions, we get a mechanism to help detect errors in the code of the tutorial.
Example methods do not live inside the notebook. They are only referenced from the notebook, but live within our workspace, just as test methods. As the notebook is deeply integrated within the IDE, it can access those methods and execute them. Furthermore, as the notebook lives inside the IDE it can reuse its tools. The result of executing the two previous snippets is displayed using an object inspector. This is the same tool used by the IDE within the debugger.
In many cases notebooks limit readers in their explorations as they require them to navigate through the notebook exclusively from top to bottom. If developers find interesting code snippets, data or objects in the notebook, their possibilities for further interacting with them directly in the notebook are limited. To facilitate for impromptu explorations GT Documenter allows users to dive deeper into any object present in the notebook.
For example, the next screenshot shows a list of example methods that are displayed using a list. If readers encounter this list and would like now to view the code of one of these examples, they would need to go and open it in a code browser, leaving the notebook.
A different solution consists in allowing readers to continue the exploration by selecting any example and opening it in a new pane to the right. This opens in the new pane an object inspector showing the code using a dedicated view.
The dive in does not have to only be limited to a single step. Readers can execute that example method and inspect the object that it creates in a third pane. As the object is a picture that has several face objects attached, the exploration can be continued by selecting a face object to inspect in more details. This impromptu exploration can have as many steps as needed.
Tutorials are pervasive during software development. In spite of this they are quite often consumed outside of IDEs, the tools that developers use on a daily basis to shape the code of their systems. To make IDEs truly integrated, we need to place the creation and consumption of tutorials deeply into their core.
Notebooks opened the way to live documents that bring together, among others, code, pictures, diagrams, and textual narratives. They are an ideal medium for making interactive tutorials for our software systems. Still, to make them the go-to choice for creating and consuming tutorials we should integrate them deeply within our IDEs, beyond just adding another tab with a tool completely isolated from the rest of the environment.