Traits Prototype in Squeak

v0.5 from February 2003

Important note: The traits prototype described here is out of date. A new, cleaner and more stable implementation is available on SqueakMap and can be loaded in Squeak 3.7 or later.

This document gives some important information about the traits prototype implementation in Squeak.

1) The traits model
2) About this prototype implementation
3) Overview of the implementation
4) Limitations -- Why is there no changeset yet?
5) Tutorial
6) Download and Wiki page

1) The traits model

The basic ideas and concept of Traits is described by several papers that can be found at on the research page about traits. The concept paper introducing traits has been accepted to ECOOP 2003. A preliminary version is available as a tech report.

Furthermore, there is a tech report that describes the practical experience of applying traits in order to refactor the Smalltalk collection hierarchy. This paper should give a good overview of how traits can be used in practice.

2) About this prototype implementation

Just about a year ago, we started to work on the concept of traits, and because we are convinced that practical experience is a crucial part of any kind of language design, I started to implement a prototype version as soon as we had a first rough idea of the model. As expected, working with the prototype gave us valuable insights for the further development of the traits model, and as a consequence, the traits prototype evolved and changed a lot. However, the purpose of the implementation remained the same: we wanted to have a prototype that allows us to play with the main features of the model.

It has always been the idea that traits should at one point be available for Squeak and potentially also for other Smalltalks. (The VisualWorks team actually plans to implement a first prototype version sometime this year). Therefore, I planned to build a new version of traits that is essentially a refactored version of our prototype with a clean design that addresses the fact that the current traits model is quite different from the one we had initially implemented. This version should then be available as a clean changeset on SqueakMap.

Unfortunately, I just haven't found enough time for doing this and after a while I realized that I need to change my plan: instead of waiting until I have the time for doing a clean version, I just fixed the most common bugs in my protpotype and then put it out. Like that, interested people can play with it, and if someone gets inspired and is interested in transforming this prototype or a part of it into a clean version, I would be more than happy to collaborate and share all my ideas and insights. So, just let me know!

In the meantime, we are going to further develop an extended version of the traits model, and we are of course also implementing it. This new implementation has two purposes: On one hand, it will serve as a research vehicle for the extended model, but at the same time, we also want to make sure that it can be used as s stable version for the current model. This means that we are planning to generate a stable traits changeset based on this new version.

3) Overview of the implementation

The traits implementation can be separated into kernel and user interface.

3.1) Kernel

The traits kernel can again be separated into two parts. On one hand, there is the part that is necessary to represent a trait, to allow trait composition and to make sure that the trait methods are integrated into the classes in a semantically correct way. On the other hand, there are some extension that allow realtime reasoning about the code. This part is basically independent of traits and would already be a valuable extension of a regular Smalltalk system. It provides some of the benefits of strongly typed languages without additional overhead for the programmer. For example, it helps identifing spelling mistakes in methods sends and helps finding abstract classes that should actually be concrete.

Whereas this reasoning is pretty useful in a regular Smalltalk system, it is nearly essential in a system with traits. It has a big impact on the practical usability because it is a key for helping a programmer understand how the different aspects of a class/trait are related to each other.

3.1.1) Traits representation

In order to represent traits, there are classes TTrait and TMetaTrait, which are essentially subclasses of ClassDescription. (It may seem that it would be better to make them subclasses of Behavior, but I decided against it because I wanted to reuse things such as the class organization). Because I didn't want to mess with ClassDescription, I also created a new subcass TClassDescription, which serves as the new superclass for classes that are able to use traits.

3.1.2) Incremental reasoning

This part allows realtime reasoning about the code, which means that it provides the programmer with information that is updated system-wide whenever a method is changed. The information includes things such as required methods (methods that are required in a class but are not yet implemented), unbound super-calls (super calls that refer to an inexistent method), etc. In addition, there are trait specific information. For example, information that shows how two traits are glued together and indicates conflicting methods.

Most of the code necessary for this reasoning is integrated into the class TClassDescription and its subclasses. Since changing a method in a class "high in the hierarchy" may have impact on many classes throughout the system, caching of some data is necessary in order to do the required analysis and updates in real-time. Although the current prototype imlementation uses such a caching strategy, it still can be a bit slow for certain changes in classes such as Object. Unfortunately, I didn't have the time for further optimizations and I also haven't finished the implementation of "smart lazy update mechnism" yet.

3.2) User Interface

The user interface mainly consists of the "TraitsBrowser", which is an extension of the regular Smalltalk Browser. The main differences are the fact that the TraitsBrowser has a modified class pane that shows how the selected class is composed from traits and that there is an extended protocol pane that contains "virtual categories". These virtual categories contain selectors that are important for the understanding of how the selected class (or trait) is composed. Furthermore, all panes now use colors to differentiate traits from classes, indicate abstract classes, differentiate between required, provided and conflicting methods, etc.

4) Limitations -- Why is there no changeset yet?

4.1) Why is there no changeset yet?

There are several reasons why there is no changeset for traits yet. The meain reason is that I just haven't found the time yet to create a version that is "finished enough" to be of great value for "real programming" (e.g., there is still no file-in/file-out for classes containing traits).

Another reason is that filing in traits requires recompilation of the whole system. This is because we need to add some instance variables to ClassDescription and because we need to generate some data to fill the caches for the incremental reasoning. Unfortunately, the kernel (resp. the ClassBuilder) of Squeak is broken for at least half of the (inofficial) versions since Squeak 3.2, and it is also broken for the latest version of Squeak 3.4 (state January 31). Thus, it would not be possible to load a traits changeset into such an image even if it would exist.

4.2) Our future plans

As you can see in Section 4.3, there are still many limitations of the current Traits prototype. However, it is not that we wouldn't know how to implement/solve them, it is just that at the moment, we don't have the time to do all the required work. However, if someone is inspired by this prototype and is interested in bringing all or parts of it to a state where it can actually be used in a productive way, I would be more than happy to cooporate and share the knowledge I have gained during my work on this. So, just let me know!

As I already said above, we are also planning to do a stable implementation of traits that will be available as a changeset on SqueakMap. However, since we want to make sure that this stable version can also be used as the implementation basis for the extended traits model we are currently working on, it probably takes some time until we are there...

4.3) Major limitations

The following list contains the major limitations of the current trait prototype implementation. As I pointed out above, I just didn't have the time to do work on them yet. So, if someone is interested in tackeling one of these issues, please let me know.

5) Tutorial

This is actually not a real tutorial, but just a few screen shots showing the different features of the TraitsBrowser. The example code is the same as discussed in the concept paper.

1) The Traits Browser. This is the Traits Browser with now class selected.

2) Creating classes and traits. Use the context menu of the text pane to select whether you want to create a new class or a new trait. You can also create a new trait by generating it from an exisiting class.

3) Generating a trait from a class. When generating a trait from an existing class, the system automatically replaces instance variable accesses through accessor methods. Note that you can specify whether also method in superclasses should be included.

4) Creating a class that uses a trait. Creating a class MyPoint that uses the trait TPoint.

5) A class that uses a trait. The programmer can choose whether he wants to see all the methods available in a class, only the methods that are defined within the class itself, or the methods that are provided by a trait.

6) A class that uses multiple traits and exclusions. The class EColoredCircle is built from 4 traits. The composition clause specifies that the methods #= and #hash are excluded from the trait TEColor.

7) Selectors and methods. The button row above the text pane indicates the status and the different implementations for the selected selector.

Note that left-clicking on any of these buttons allows to see the source code of the method implemented in the respective trait or class.

8) Selectors and methods II. The button row above the text pane indicates the status and the different implementations for the selected selector.

9) Virtual categories and color coded selectors. Virtual categories ensure much easier understanding of a composition.

The color codings of the selectors are related to this virtual categories:

10) Menus associated with the button row. Right-clicking on a button in the button row opens a context menu that provides convenient short-cuts. In the figure shown below, we can for example remove the exclusion of a selector without having to manually edit the composition clause. Other menu features include:

11) Navigating to subtraits. Unfortunately, the current version of the TraitsBrowser does not contain a tree widget that allows easy inspection of deeply nested traits. In the context of EColoredCircle it is for example not possible to see that the trait EColor actually contains several subtraits. In order to compensate a little bit for this limitation, we can jump to the definition of a subtrait by double-clicking on it. Then, we can use the back-button (<-) to go back to the previous context.

The following figure shows the state after double-clicking on the subtrait TECircle in the previous figure.

6) Download and Wiki page