Custom View
Context
You are exploring a live domain model and find some interesting information.
Problem
How do you make it easy to find interesting information?
Forces
— To obtain an interesting view of data, you are generally forced to activate a dedicated tool.
— Navigating to the data you want to reach may entail a sequence of operations, either clicking in views, or evaluating code snippets, to reach the answer you seek.
— The sequence of steps may be cumbersome to follow repeatedly.
— The default view you obtain may not highlight the interesting bits of information.
Solution
Turn interesting data into a custom view. Extract the navigation steps into a new custom view for the moldable object you start navigating from.
Examples
As an example, consider the views of a partially played Ludo game below. We would like to understand which moves have been played up to now. In the first example we are exploring a “raw view” — a generic view of the state of the object. With this view we can navigate to the individual moves and explore them, but it is a clumsy way to explore the object.
In the second example we see a custom Moves view that lists the moves in order, with columns showing each roll of the die, the player who rolled the die, and any token that may have moved. From this custom view we can then dive directly into the Move object, which in turn has a custom view visualizing the change in state.
Consequences
A custom view exposes information about a domain that can otherwise be hard to find.
Custom views become an intrinsic part of a software system, thus turning it into an Explainable System.
By augmenting an object with a custom view, you can navigate directly to interesting information about that object, without having to fire up a separate tool.
You first need a Moldable Tool into which you can dynamically plug custom views.
Known Uses
Clerk is an open-source programming assistant for the Clojure language, which offers moldable, custom views within notebook pages.
Custom views are pervasive in GT. In a standard image from August 2024, there exist over 1800 classes with a total of over 3600 view methods, averaging under 12 lines of code. It is also worthwhile to note that if we take inheritance into account, then the views affect 12000 classes. The treemap below offers an overview of the GT classes organized in packages. A class appears is colored with blue if it or its superclass defines a custom view, and in green if it defines an example method (see Example Object).
Related patterns
A custom view is closely related to a given Moldable Object. Interconnected objects with custom views can form a Composed Narrative. A Moldable Tool is a prerequisite for a custom view to be automatically installed when the relevant artifact (an object, a class, an exception, etc.) is seen by the tool. A custom view should be cheap to implement. Start with a Simple View, and only elaborate it when it is needed.
GT implementation notes
A simple example is the view of the state of the stack of the StackMachine.
In this example, we must navigate to the stack
slot to see the stack items.
By creating a forwarding view, we “lift” the view we want to the StackMachine itself:
Pretty much any view can be seen as an example of this principle. Consider the example of Working with a REST API: the GitHub case study. In the example below, the Repositories view is obtained by navigating to a list of repositories that are created programmatically.
By lifting this code into the GhOrganization
class and creating a dedicated view, we can explore the repositories without having to first navigate to a collection of repositories.
Similarly, in the GtLudoRecordingGame
, many of the views are lifted from collaborating objects to eliminate the need for navigation when exploring. The views for
Players
,
Squares
,
Tokens
and
Moves
all replace the need for navigation.