Contextual Playground

’# Context

You have a moldable object, and you are ready to start exploring.

Problem

Where do you start coding?

Forces

An editor for coding new methods typically provides no facilities for testing the code.

When we code new behavior as methods, we must repeatedly change our context to incrementally develop the logic.

Testing the code requires a separate setup.

Setting up code to prototype and test logic can be cumbersome.

Writing tests first for parts of the logic of a complex method may can be overkill.

Solution

Prototype new behavior in the Playground of a Moldable Object, i.e., an Inspector on a live instance of the class. The Playground will be bound to the context of the instance, so self and all slots can be accessed exactly as they would in a running method.

From the moldable object you can navigate to any parts of the instance, to explore the APIs, or to test experimental code.

Code snippets that work as expected can then be copy-pasted to existing methods, or extracted to new methods using an Extract method refactoring.

Steps

The following steps illustrate how the Inspector Playground can be leveraged to explore an object's state, experiment with code, extract methods, extract (test) examples, and add custom views to a live object.

Suppose we are implementing a StackMachine class to simulate an RPN calculator. So far it just holds a stack slot initialized to an empty OrderedCollection SequenceableCollection subclass: #OrderedCollection instanceVariableNames: 'array firstIndex lastIndex' classVariableNames: '' package: 'Collections-Sequenceable-Ordered' , and nothing else. We want to implement operations to perform calculations with the stack machine.

Exploring the object's state

We start by exploring a live instance.

StackMachineV0 new 
  

We would like to push some values onto the stack but we need to explore the API of the underlying objects.

From the Inspector we dive into the stack slot and query its Meta view to see which add operations it has.

We find the addLast: selector, and experiment with it in the Inspector Playground.

We see in the stack's Items view that it has been updated.

Extracting a method

We generalize the code as follows.

We select the code and perform an Extract method refactoring, and name the new (binary) method !.

(For illustrative purposes we have multiple StackMachine classes to represent the different versions. In reality we would just have one class.)

We push two values onto the stack from the Inspector Playground.

Extending the API

It would be nice to inspect the stack and the top of the stack, so we test each of the following snippets in the Playground, and extract them as methods.

        
stack.
stack isEmpty.
stack last "top".
        
      

Our API now looks like this.

Extracting an example method

We rewrite our scenario as an example:

        
example := self class new.
example ! 3.
example ! 4.
example
        
      

And again we extract a method. We add a <gtExample> pragma, with some assertions. StackMachineV2>>#stackWith3and4 stackWith3and4 <gtExample> | example | example := self class new. self assert: example isEmpty. example ! 3. self assert: example isEmpty not. self assert: example top equals: 3. example ! 4. self assert: example top equals: 4. ^ example

We can generate an instance directly from this method ( Play and inspect ).

Adding a custom view

We'd like a custom view for the StackMachine that mirrors the stack slot's Items view.

From the live example, we navigate using the Raw view to the stack's Items view, Secondary-click on the tab and see that the method that implements this view is called gtItemsFor: (implemented in SequenceableCollection>>#gtItemsFor: gtItemsFor: aView <gtView> ^ aView columnedList title: 'Items'; priority: 50; items: [ self ]; actionUpdateButtonTooltip: 'Update item list'; column: 'Index' text: [ :eachItem :eachIndex | eachIndex asRopedText foreground: Color gray ] width: 45; column: 'Item' text: [ :eachItem | eachItem gtDisplayText ]. .

Now we can quickly implement a forwarding view as follows: StackMachineV3>>#gtStackFor: gtStackFor: aView <gtView> ^ aView forward title: 'Stack'; priority: 10; object: [ stack ]; view: #gtItemsFor:

It looks like this:

Consequences

By prototyping new behavior in a contextual playground, you obtain immediate feedback for experimental code.

Related patterns

Start with a Moldable Object, in order to get a live instance to prototype from.

Known uses

The JavaScript console of a web browser can be used to explore and experiment with the behavior of live objects in a web page.

You can also see this process at work in the short video Exploring the GitHub REST API in 7'.