Croquet Microverse & Collaborative, Live Programming
April 29 2022
Hello, this is Yoshiki Ohshima. I am one of the engineers at Croquet, and have been working on Croquet Microverse.
One of the defining features of Croquet Microverse is collaborative live programming. The feature allows a group of users to create and modify a new "behavior" that describes what a card does and how it looks. With this feature, a group of users in the same Microverse session can incrementally refine their world from within the world itself. This way of creating and improving the world is very important when there are multiple users in the world. You certainly don't want to force your colleagues to reload the page just because you made a small change in code or the model. However, in order for this live code updating to work, we need solid ground that is based on well-designed programming language concepts. Luckily, we did not have to invent a whole a lot by ourselves, and we still need to learn from past ideas and adapt them to match well with the Croquet system.
In the following post, I'd like to discuss the influences on the design of the behavior mechanism in Croquet Microverse.
While we use the terminology "cards" for objects in Croquet Microverse, you can think of them as representations of an "object" in the classical object oriented programming (OOP) sense. So the idea of enhancing an object sounds just like a class extension mechanism in OOP languages. And, as some engineers at Croquet, including myself, have been working with Dr. Alan Kay, who coined the term object-oriented programming, designing a class extension mechanism is right up our alley!
In designing the behavior mechanism for Microverse, we were particularly inspired by several ideas. First and foremost, the "PIE"[1] system by Goldstein and Bobrow, built on top of Smalltalk-76, was the most important idea for us. The main idea of PIE is to attach "multiple perspectives" to an object, where a perspective is a set of methods. Another object can send a message to a particular perspective to "view" the object in a context-specific way, or to trigger an action on the object through the perspective.
The clients of the object explicitly specify which perspectives they are concerned with, by writing something like "(anObject as: CircuitElement) location" with the #as: message, which may look verbose, but it certainly avoids accidental name clashes of methods among perspectives.
Another major source of inspiration was Traits[2]. Traits were designed and implemented by Nathanael Schärli and his collaborators, during his time interning at Walt Disney under Alan Kay in 2000. In fact, I was also interning at the same time. I got a chance to see how that work progressed.
This version of Traits was originally conceived in the Smalltalk context, but its clean properties appealed to a wide variety of other language designers[3][4][5]. However, the way Alan told me how it should work was a bit different from what Traits ended up with. Around that time, Alan's group was working on a computer-based media authoring and programming system called Squeak Etoys[6] blocks programming system for children. See the image below.
When the child creates a "script" by assembling the basic features that are provided by the object, the resulting script "uses" the basic features and then itself becomes a new feature. The user scripts are stored in a "script category". Typically a child creates a few scripts for a graphical object, and those interrelated scripts are stored in a category. At the right edge of the image, the categories such as "scripts" for the user-defined scripts, "basic", "color & border", etc. are laid out in the "viewer" for the object.
Alan's idea was that this category, which is visually manifested and nicely laid out in the viewer for the object, should be draggable. Once you drag a category out of the viewer, it becomes an entity that can be attached to another object, and the scripts in the category just work with the basic features provided by that object.
Yes, this pluggable set of methods idea resembled Traits, but there were some crucial differences. Most importantly, it was an instance-based mechanism rather than class-based; it was used to enhance the concrete object that the user cares about (i.e, that was a drawing by the user), not something you'd use to construct an abstract structure and then make an instance out of it.
I heard this idea from Alan and it really struck me. I joined the Etoys team, and then built a few object systems and end-user authoring systems over time, and I always tried to incorporate the essence of this idea into the systems I created. One takeaway for me was, that in order for a class extension mechanism (or I should say object extension mechanism) to be cleanly copied and transferred to other objects and removed from objects, it required embracing the "loose-coupling to the extreme" without compromise.
Here, Croquet offered a unique opportunity for us. Croquet enforces a strong separation between models and views, for example. We simply had to design a mechanism that would work in the context of Croquet. This in turn forced us to design a mechanism where adding and removing behavior to an object was a clean operation.
JavaScript has some nice features to implement these kinds of meta level programs. One is that you can invoke any method on any object by using the call() primitive. Also, with Proxies, we can omit the verbose "perspective selection" when a method of a behavior calls another method in the same behavior. It is worth mentioning that we had an opportunity to try the design and iterate the behavior mechanism in another Croquet-based system called Croquet Greenlight[7]. When we got Greenlight to be a production-level application, the behavior mechanism (we call behaviors the "instance-based expanders" in the technical context such as the paper) had also matured.
Overall, we are quite happy with the behavior mechanism in Croquet Microverse. To unleash the power of the dynamic class extension mechanism, the event routing scheme and all other parts have to work together. As we tend to write all parts of the system by ourselves, there weren't many problems we couldn't solve using packages from other vendors.
In summary, 1) The behavior mechanism of Croquet Microverse draws upon some notable ideas from the past, most notably PIE and Traits. 2) Adapting it to the instance-based exploratory space was inspired by the conversation with Alan Kay when we were working on the Squeak Etoys system. 3) Croquet's model and view separation requirement was a blessing in designing a mechanism that matches with many other constraints we needed to satisfy.
- References:
- [1] Descriptions for a Programming Environment: Ira P. Goldstein and Daniel G. Bobrow, 1980.
- [2] Traits: Composable Units of Behaviour: Nathanael Schärli, Stéphane Ducasse, Oscar Nierstrasz and Andrew Black, 2003.
- [3] Traits in the Fortress Programming Language: https://www.ccs.neu.edu/home/samth/fortress-spec.pdf
- [4] Traits in the Rust Programming Language: https://doc.rust-lang.org/book/ch10-02-traits.html
- [5] Traits in the Scala Programming Language: https://docs.scala-lang.org/tour/traits.html
- [6] Powerful Ideas in the Classroom: BJ Allen-Conn and Kim Rose, 2003
- [7] An Experiment in Live Collaborative Programming on the Croquet Shared Experience Platform: Yoshiki Ohshima, Aran Lunzer, Jenn Evans, Vanessa Freudenberg, Brian Upton, and David A. Smith
Interested in trying out the Croquet Microverse?
Join Microverse Beta Read Docs