Moldable Object
Context
You are ready to start the process of creating an explainable system, either from scratch, or based on some existing software or data, to answer specific questions you have.
Problem
Where do you start coding an explainable system?
Forces
— As a programmer, you want to quickly get feedback about the code you are writing.
— When you write code in a conventional code editor, you are several steps away from seeing the consequences of your coding.
— To write unit tests, you must already know what behavior you want to test and what the results should be.
Solution
Start coding by inspecting a live instance of the class you are coding, not in a conventional source code editor.
Steps
Incrementally pose domain-specific questions, find the answers by exploring and interacting with the object, and then turn the way you reach those answers into custom tools, behaviors and tests.
Examples
Moldable development is about making systems explainable with the help of custom tools, which means that you need to start the process by asking questions that you want to answer. In most cases you can’t immediately start building the custom tools, but rather you need to explore the domain objects to understand how to answer the question. Once you know how to get the answer, you can turn the exploration steps into a custom tool. Starting with a live object means that you can immediately start the exploration process. Turning the exploration of an object into a custom tool is the process of molding it, hence we call it a “moldable object.”
Below we see an Inspector on an instance of a GtLudoRecordingGame with a Contextual Playground where we can write experimental code that we later extract as methods. (Lift the handle at the bottom of the Inspector.) In this case we are prototyping the autoplay feature. In the second pane we see the Moves view of the object, showing the details of all the moves of the game so far.
With the moldable object at hand, we can ask questions like What is the current state of the Ludo game? , or What happened in the last few moves that we autoplayed? As we answer questions we can create small custom tools, such as a Custom View or a Custom Action. The model of the history emerged from the need to answer questions about the evolution of an instance of the game, while the history view was created as a Custom View to enable exploration of a game’s history. Whenever we identify an interesting state of our moldable object, we can extract it as an Example Object that we can use as a test case, or as a starting point for further moldable development.
A moldable object can encapsulate entities at different levels of abstractions. When viewed with a Custom View and connected with other moldable objects we can form various kinds of Composed Narrative. For example, in the screenshot below we see three related objects. On the left we see a CircularMemoryLogger
object that shows multiple signals logged for an asynchronous execution. In the middle we have an instance of BrTextStylerAsyncStylingStarted
. The signal contains the stack and presents it in a Custom View. Selecting an item in the stack shows the related Context
object that displays a view with the
Source
. Essentially, we have obtained a postmortem debugger connected to a logger. There are many such combinations possible.
Consequences
Instead of writing code in a text editor in the context of the source code of a class, you are always working in the context of a live object, whose behavior can be immediately explored. Instead of writing hypothetical code that you must afterward test, you start by prototyping code, and then extracting new behavior. Instead of trying to program custom tools in a vacuum, you first explore and prototype answers to questions, and then extract the code you need to create a custom tool.
Known uses
The core idea of a Moldable Object is to incrementally mold a live object to obtain immediate feedback into code changes. Interactive, or “live” programming has a long history. One could argue that any live programming task starts with a “moldable object”, however the key difference is the focus on molding objects to create an explainable system consisting of custom tools, rather than just live programming in general.
Related patterms
— You already have a class: create a Project Diary notebook page containing a code snippet to create an instance of the class, and start from there.
— You don’t have a class: within a Project Diary page, start instead with a code snippet that instantiates an empty class, and then prototype the behavior.
— You have a test case: turn the test case into an Example Object and start from there.
— You have some data (in memory, in a file, in a database, in the cloud ...): wrap the data as a Moldable Data Wrapper.
GT implementation notes
You can inspect a moldable object in many ways.
You can inspect the result of evaluating a Smalltalk expression in a Playground. This can be a code snippet in a Lepiter page, or a Playground associated with another tool, such as an Inspector or Coder.
GtLudoGame new
If you inspect the code above, you will see at the bottom of the inspect a handle to lift and expose yet another playground. (You can also see the handle at the bottom of the next example below.)
You can also click on an Inspect Object button in many tools, for example at the top right of the Inspector of the Ludo Game.
Another way to get an instance is to inspect a runnable method. This can be a unary class-side method, such as FileLocator>>#imageDirectory
Another kind of runnable method is an Example method, such as GtMemoryGameExamples>>#chooseMatchingPair
You can also get to a live instance by navigating to it from another Inspector instance. Click, for example, on one of the cards of the previous example.
If the class you want to work with does not yet exist, you can still inspect a moldable object with the help of a
fixit
. From the code snippet below, we can inspect an instance of a class MyStackMachine
, after clickibg on the wrench icon and selecting the Create class
fixit.
sm := MyStackMachine new.
Once you have a moldable object, you can incrementally add behavior and custom views, and immediately see the effect on the live instance.
Now you can use the Playground at the bottom of the Inspector to prototype the new behavior. They key point is that the Playground is bound to the environment of the moldable object, so you have access to self and all the slots of the objects. Once you have working code, you can apply an Extract method refactoring, or you can copy-paste the code to a new method.
You can either directly add a new method in the Meta view in the Inspector (see the GtMemoryGame example above), or click on the Browse class button to open an Coder view.