A Declarative Model
for Defining Smalltalk Programs
24003 SW Baker Road
Sherwood, OR 97140
Allen Wirfs-Brock has been a leader in the industrialization and commercialization of Smalltalk since 1980. He was the architect of the Tektronix 4404 Smalltalk system, the first widely used commercial Smalltalk-80 implementation. He is a founder and Chief Technologist of Instantiations Inc. Previously he was Vice President of Technology for Digitalk Inc. and Chief Scientist at ParcPlace-Digitalk. He is an active participant on X3J20, the ANSI Smalltalk standardization committee.
Smalltalk programming has traditionally been performed through the imperative execution of reflective Smalltalk expressions within a development environment. A Smalltalk "program" is essentially an accumulation of side-effects upon the development environment. There is no "objective" description of what constitutes such a program. A record of the sequence of expressions may be maintained but their actual effect is highly dependent upon the initial state of all referenced entities within the development environment. The problem is compounded because of the polymorphic nature of Smalltalk. The actual operations performed by a Smalltalk expression are only determinable at the actual time of execution when polymorphic operations are resolved in the context of actual objects.
This style of program definition is a source of significant program maintenance and delivery problems for Smalltalk programmers. Once a program is created, it exists as an extension of the development environment. The most basic problem is the inability to actually identify which program elements are part of an application and which are part of the development environment. This makes it difficult to extract an application from its development environment for delivery, archival, transport, or even collaborative development purposes. Even if a complete record is kept of the expressions used to create the program, initial state dependencies may result in the inability to recreate the program within a different version of a development environment.
Most other programming languages describe programs in a declarative manner. A declarative program description is a sequence of declarations which define the program elements in an objective manner, independent of a development environment context. Declarative descriptions of programs permit them to be easily transported between programmers and language implementations.
We have successfully adapted Smalltalk to use a declarative model of program definition. The declarative version of Smalltalk preserves the essential characteristics of Smalltalk as used by application programmers, but eliminates the principal source of Smalltalk’s maintenance, delivery, and portability deficiencies. This declarative model has been used as the basis for a commercial Smalltalk development environment [Digitalk93, Parcplace95] and it has been adopted by the X3J20 committee for use in the Smalltalk standard [X3J20-96] that is currently under development.
2. Imperative and Declarative Models
An imperative model is a description of an entity that consists of a set of commands (operations, functions, "imperatives", etc.) that, when executed in sequence, will reproduce the entity. Lisp and Smalltalk have traditionally used an imperative model for describing programs. A program is described by a set of commands that will, when executed, reconstruct the program. In traditional Smalltalk implementations the imperative commands that create a program are executed in the same environment as the program that is being created. The commands are expressed in terms of reflective operations upon the data structures that implement the executable program.
A declarative model is a description of an entity that consists of a set of existential statements that enumerate the distinguishing characteristics of the item. FORTRAN, ALGOL, C, COBOL and most other programming languages use a declarative model for describing programs. A program is a set of declarations that define the procedures, functions, variables, types, and other elements that make up the program. The declarations for program elements express the characteristics of the elements in terms of abstractions that are independent of the algorithms and data structures used to implement the language. It is possible to fully understand the meaning of such a program by reading it. The reader does not have to know anything about how the compiler works, the runtime representation of variables, or even what computer will execute the program.
A declarative model describes an entity in terms of "what it is". An imperative model would describe the same entity in terms of "how to build it". For example, in the domain of geometry an imperative description of a geometric element might be: "Place a pen at the origin of the coordinate system; move the pen 5 units to the right; move the pen 5 units straight up; move the pen 5 units left; move the pen 5 units straight down." The declarative description of the same figure might be: "A square with sides 5 units in length with its lower left corner at the origin."
This example illustrates many of the advantages of a declarative model over an imperative model. With the declarative description the type of geometric figure is explicitly stated, while with the imperative description the side-effects of executing the commands must be examined in order to recognize the geometric figure. The imperative description unnecessarily constrains the implementation. There are many different ways to create the square as described in the declarative model, the choice is up to the implementation. There is only one way to draw the item from the imperative model. The declarative description is also shorter and easier to modify.
3. Imperative Definition of Smalltalk Programs
Smalltalk program construction has traditionally been performed in the context of a "virtual image" [Goldberg93]. A virtual image consists of a set of objects. These objects include not only those that define a class library that is intended to be used and extended by application programs, but also objects that implement the interactive Smalltalk programming environment itself. In such an environment, a Smalltalk application program is constructed by directly or indirectly executing imperative Smalltalk expressions that extend and modify the objects within the virtual image to include the classes and variables necessary to implement the functionality of the program. Smalltalk does not include the concept of a program as a distinct entity. In practice, a Smalltalk program is the state of a virtual image when work is declared completed.
The image contains the objects that are the implementations of classes, global variables and pools, but not the imperative expressions that created them. Therefore, to transfer a program to another virtual image, it is necessary to synthesize and externalize expressions that will recreate the program elements. However, the types of some program elements may not be readily discernible by examining their implementation artifacts. For example, in some implementations it is not possible to distinguish a pool from a global variable whose current value is a dictionary with strings for keys. More generally, it is not possible to synthesize the original initialization expressions for global variables. It is only possible to produce expressions that reproduce their current values.
Lack of a program definition in traditional Smalltalk environments leads to an undue reliance on the virtual image. Images can become obsolete or broken. Because the program is encoded in the image, the program is in danger of becoming inaccessible if the image becomes outmoded or corrupt.
Smalltalk’s imperative program construction model also requires that the same virtual image be used both for program creation and program delivery. This makes it very difficult to support situations where the development must be performed in a computing environment that is different from the target execution environment.
The imperative expressions that extend the virtual image into an application program are either entered interactively using programming environment tools or read from an external file. There are two primary tools used for interactively creating Smalltalk programs: a browser and a workspace. A browser is used for defining classes and methods.
Browsers typically do not include provisions for defining global variables, pools, or pool variables. Instead the appropriate expressions to create them are usually entered using a workspace. Workspace expressions are also used to initialize classes and to set the initial values of global and pool variables. These expressions are often discarded and not captured as a permanent part of the program. The manual and unreliable nature of the initialization of Smalltalk programs leads to a number of program errors. Especially prevalent after reconstruction of a program in a new image are errors where program elements have an initial value ofnil instead of some other value as originally intended by the programmer. It is also common for a program execution to start with variables initially set to values that were unintentionally retained from a previous invocation.
4. Declarative Smalltalk Programs
Because of the issues identified above we have chosen to use a declarative model to define Smalltalk programs. This requires the introduction of additional declarative abstractions to the language for program elements that previously had only been defined in terms of implementation artifacts. All elements of a Smalltalk program are described existentially at a level of abstraction that does not overly constrain implementations of the language. The meaning of such a Smalltalk program should be understandable solely from the definition of the program without actually executing a program construction processor or making use of a pre-initialized execution environment.
The use of a declarative specification model has little direct impact upon Smalltalk programmers. Even though Smalltalk has traditionally been implemented using an imperative program description model, the perception of most Smalltalk programmers is of a declarative model. This is because Smalltalk programmers typically create and edit programs using a browser that presents the classes that make up the program in a declarative style.
The definition of the declarative model of Smalltalk programs consist of two parts. The first part defines the computational model for Smalltalk programs. The second part defines the declarative structure used to specify such computations. Taken together the two parts are intended to define the semantics of a Smalltalk program, but avoid requiring any specific implementation techniques. In addition, the use of reflection is not required in order to define a Smalltalk program. The following are a few traditional assumptions made about the traditional execution environment for Smalltalk programs that are eliminated using this declarative model:
·A system dictionary exists.
·All classes, globals, and pools are in this system dictionary.
·Pools are realized using dictionaries.
·Global and pool variables are represented as associations.
·Each class has an associated metaclass.
·Each class is an object.
·Methods are objects.
·Reflection is required to define a program.
Although our current implementation contradicts none of these assumptions, the goal of the declarative model is to convert Smalltalk programmers to thinking about a program as a specification of a computation and to lay the groundwork for language standardization and further implementation evolution.
5. Reflection and Interactive Development Environments
Smalltalk development environments are known for their high degree of interactivity and functionality. They support fine grained incremental creation of Smalltalk programs with immediate feedback and executability. They also support interactive programming aids such as immediate cross-referencing and non-linear access to program elements using browsers. It was the reflective implementation of the imperative definition model that originally enabled Smalltalk environments to provide this level of functionality.
Incremental program creation and immediate execution is possible because the individual program elements are added reflectively to an already executing program. Each new class or method immediately becomes part of the currently executing development environment program and hence can be immediately executed. Similarly, any modification of an existing program element also has immediate effect. Interactive debugging is also implemented through reflection upon the objects that implement the program.
Higher level services such as browsing and cross-referencing are also implemented using reflection upon the objects that implement the program. Browsers locate classes by navigating the data structures that implement inheritance (subclass references within class objects) or by directly accessing the "symbol table" (the system dictionary) that stores global names. Cross-referencing is accomplished by scanning method dictionaries to determine which classes implement particular methods or by scanning compiled methods to see if a particular method is used to send a message.
What traditional Smalltalk development environments are actually doing is using reflective operations upon the implementation data structures as an "object model" of the program. The existence of such a directly manipulatable object model means that the programming environments can directly operate upon the logical elements of the program and avoid time consuming parsing and editing of a textual representation of the program in an external file. Arguably, it was the existence of a directly manipulatable program model that enabled implementors of Smalltalk and Lisp to create the first highly interactive development environments.
Usage of a declarative model of Smalltalk program definition in no way precludes use of such a reflective program model. A programming environment may translate the declarative specification of the program into implementation objects that it then directly manipulates. Similarly, an implementation may provide runtime access to implementation objects to enable reflection from within application programs.
Adoption of the declarative model provides an opportunity for development environments to use a new form of program object model, one that models the declarative specification of the program rather than its implementation artifacts. Such an object model has objects that directly correspond to the elements of a declarative Smalltalk program definition (classes, methods, pools, variables, etc.) rather than the implementation artifacts (CompiledMethods, MethodDictionaries, Associations, Symbols, etc.) Typical operations upon the model include declaring a class or variable, removing a method definition, or querying to find all definitions that reference some other definition. These operations upon the object model are also expressed in terms of manipulations of the declarative program specification abstractions rather than the direct manipulation of the runtime implementation of the program elements. However, an operation may, as a side-effect, translate changes to the abstract program model into changes in the executable form of the program.
Such a declarative object model has a number of advantages. Its enables tool builders and end-users to write code to programatically manipulate Smalltalk program definitions without having to understand all the details of the underlying implementation. More importantly, it decouples the model of the program used by the development tools from the actual executable implementation of the program elements. This permits the technology for executing Smalltalk code to evolve without requiring changes to the implementation of the programming environment tool set. It also permits a tool set to support alternative execution environments or technologies. Finally, it permits the execution environment for a Smalltalk program to be completely separate and distinct from its development environment. Such a separation has the potential to enable or greatly simplify the implementation of capabilities such as cross development or remote debugging and to significantly increase the robustness and reliability of the Smalltalk development environment.
6. Experience and Application of the Declarative Model
A declarative model of Smalltalk program specification was first used in our design of Modular Smalltalk [Wirfs-Brock88]. Subsequently, this approach was explored and refined for more conventional Smalltalk dialects in the context of developing advanced development environments for the Smalltalk-80 and Smalltalk/V dialects of Smalltalk. Team/V [Digitalk93, Parcplace95] is a comprehensive commercial Smalltalk development environment that is based upon the declarative model.
The advantages of the declarative model for specifying Smalltalk programs have also been recognized by the X3J20 committee which is chartered with developing an ANSI standard [X3J20-96] for the Smalltalk programming language. The use of the declarative model is expected to result in a language standard that precisely specifies the meaning of conforming programs while allowing implementors wide latitude in implementing conforming implementations.
We believe that the adoption of a declarative model of Smalltalk program definition is an important step in the maturation of the Smalltalk programming language. It is a key component of the emerging definition of a Smalltalk standard and will further solidify Smalltalk’s emerging status as a "mainstream" application development language.
Many of our colleagues at Tektronix, Instantiations, Digitalk, and ParcPlace-Digitalk have participated in the development of the declarative model of Smalltalk and programming environments based upon it. Juanita Ewing and Brian Wilkerson were key contributors to the development of the declarative model. Harold Williams, John Wiegand, Dale Henrichs, and Carl McConnell have all been instrumental in the creation of an object model for manipulating declarative Smalltalk programs. Steve Messick, Tim O’Connor, and Pat Caudill have contributed to the development of development tools that exploit this object model.
We would also like to acknowledge the organizational and individual participants in the X3J20 Smalltalk standardization process. They have been exceptionally receptive and supportive of the adoption of this declarative model.
[Digitalk93] Digitalk Inc., Team/V Programmers Reference Manual, 1993
[Goldberg83] Adele Goldberg and David Robson, Smalltalk-80 The language and its Implementation, Addison Wesley, 1983.
[ParcPlace95] ParcPlace-Digitalk Inc., Visual Smalltalk Enterprise Tool Reference Manual, 1995
[Wirfs-Brock88] Allen Wirfs-Brock and Brian Wilkerson, "A Overview of Modular Smalltalk", in Proceedings of OOPSLA ’88, San Diego, CA, September 1988, pp. 123-134.
[X3J20-96] X3J20 Committee, Working Draft Smalltalk Standard, March 1996.