Outlook

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.

Part of the tutorial Exemplifying software containing two versions of a method that developers need to add to their IDEs if they wish to follow the tutorial.

Part of the tutorial Exemplifying software containing a screenshot with a code snippet and an object inspector. The screenshot is already out of sync with what readers see in the latest version of Glamorous Toolkit.

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.

Loading code

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.

Embedding code for methods in a notebook using widgets that allow developers to add the code to their workspace and see the difference between the code from the notebook and the code from their workspace.

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.

The Diff view shows developers the difference between the code from the notebook and the code from their workspace. In this case all the code from the notebook is not present in the workspace.

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.

The Diff view shows how the method faceEinstein will be changed when the code is added to the workspace.

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.

Executing code

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.

Embedding a code snippet that should be executed by the reader directly within the notebook.

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.

Embedding a code snippet that should be executed by the reader by adding a reference to an example method. The code is not contained by the notebook, but by the method. The notebook displays the method code.

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.

Impromptu explorations

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 list of example methods displayed using a list widget inside an object inspector embedded in 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.

Selecting an examples method in the list from the notebook opens that example method in a new pane. This allows readers to see the source code of the method without leaving the notebook.

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.