These conventions are documented under the following subsections:
The defobj library documents the full details of special processing performed on a module. For simply using a library defined as a module, the key fact to keep in mind is that the entire public interface to a module is declared in the one header file having the same name as the module itself, plus a trailing .h suffix. Additionally, the header file of a library module normally documents only the public interface to a module, in a way that is completely separated from the implementation of the objects it specifies.
The separation of implementation means that a library module publishes its interface entirely without reference to any Objective C classes which implement its objects. Even though classes are often thought of as separating the interface of an object from its implementation, this separation is far from complete. Not only do classes typically contain many internal methods not intended for external use, but they also define a particular storage format for an object defined as instance variables.
A library module instead publishes its interface as a set of public object types. These object types may also be supplemented by global object constants called symbols. Both these kinds of definitions normally appear only in the header file of a library. The remaining source files in a library normally contain the classes which implement the object types.
In a library module, the files which implement classes (including class header files), need not ever be referenced simply to make use of the implemented capabilities of the library object types. Documentation for the library is normally expressed entirely in terms of the types and symbols published in the library header file. If a feature does not appear in the library header file, it should not be considered part of a supported public interface.
Individual class header files are required to subclass from existing implementations, but interfaces for subclassing are an entirely separate issue from normal public use of an object library. Class inheritance can be a powerful implementation technique, but extension of an existing class framework is typically safe only if performed in explicitly permitted ways. If a library supports subclassing at all, it must carefully state which classes may be subclassed and in what ways. For a library module, this information is supplied outside the library header file. The library header file specifies only the interfaces by which objects are intended to be used, whether implemented by a local class or an external subclass.
Remaining sections of this document explain the declarations which appear in a library header file, and end with a suggested structure of documentation to be provided for a library module. The library modules of Swarm mostly follow this structure.
Multiple classes may all implement the same messages belonging to a type. The independence of types and classes means that different classes can provide alternate implementations of the same object type. For example, a particular implementing class might be selected to optimize the implementation for a particular case.
Object types are similar to protocols defined by Objective C, and the declarations appearing in a library header file are a minor adaptation of Objective C protocol syntax. A key difference from protocols is that object types are published as real external objects that may be used at runtime to create instances of a type. A futher difference is that the object types of the defobj library are divided into separate interfaces that define distinct phases of an object's life cycle.
Following is a complete library header file for a module which defines such an object, called GridTurtle:
/* Name: GridTurtle.h Description: object type for Swarm example programs Library: grid */ #import <defobj.h> @deftype GridTurtle <Create, Drop, CREATABLE> CREATING - (void) setXLocMax: (int)xLocMax; - (void) setYLocMax: (int)yLocMax; SETTING - (void) setXLoc: (int)xLoc; - (void) setYLoc: (int)yLoc; - (void) setXLoc: xLoc setYLoc: yLoc; - (void) setDirection: direction; USING - (int) getXLoc; - (int) getYLoc; - getDirection; - (void) move: (int)distance; - (void) turn: (int)angle; // angle measured in units of pi/2 (90 deg.) - (void) print; @end id <Symbol> North, East, South, West; #import "grid.xt"An object type is defined by an @deftype declaration. The syntax of such declaration is identical to that of an Objective C @protocol definition, except for the entirely uppercase keywords (CREATABLE, CREATING, SETTING, USING) appearing in the GridTurtle example above. All these modifications of Objective C syntax are accomplished by simple preprocessor macros; no extensions to the language compiler are involved.
When this library header file is processed (by a special rule in a make file), an external object id with the name GridTurtle is automatically published. The name of a defined type becomes an ordinary object that accepts specific messages defined by the defobj library. The defobj library explains the details of such messages; the only purpose here is to explain the basic sections of a deftype declaration.
deftype declarations follow the syntax as Objective C protocols for inheriting messages from each other: a list of names enclosed in angle brackets (e.g., <Create, Drop, ...> above) gives the names of other declared types containing messages to be supported by the new type as well. (These types referenced here are defined by the imported file <defobj.h>.) Like protocols, full multiple inheritance of types is supported. The same messages may be inherited any number of times through any path with no different effect than if inherited or declared just once, so long as no conflicts occur in any of their argument or return types.
The CREATABLE tag appearing in the inherited type list above is a special type which defines no messages of its own, but merely marks the type as one which supports direct creation of instances of the type. Without this tag, the only role of a type is to define messages for inheritance by other types. With this tag, the global type object has a particular implementation that supports object creation using standard messages defined in defobj.
The declared messages of the type may be separated into sections marked by the special uppercase tags such as CREATING, SETTING, and USING above. (Currently, these are the only such tags which may occur.) These sections each define messages belonging to a particular defined "interface" of the object type, which are further combined into distinct "phases" of an object lifecycle supported by defobj messages. Further explanation of the interfaces and phases defined by this example are provided in the Usage Guide of the defobj library.
The following line at the end of the
If declared as a Symbol, as in the case here, the generated objects have
no particular behavior of their own (other than the character string of
their name), but only serve to define unique global id constants which may
be used as distinct named values in messages. In this example, the
current direction of a GridTurtle object is represented by one of the
symbol names North, East, South, or West. These values are like the
enum constants of the C language, except that they are defined as full
Objective C objects, and may be used with further restrictions. An EventType, or a Warning or Error, defines a further subtype of a Symbol constant with
further specialized messages documented in defobj.
Complete, concise summary of all features of a library. Fills the role
a Unix "man page" in providing comprehensive definition of library services.
Little or no concern to provide path of tutorial introduction. Does not
contain extended examples, at most only fragments of examples which serve
needs of specification.
Tutorial introduction to a library. Focuses on the most common uses
in an order reflecting the needs of a first-time user. Most explanation
by means of progressively elaborated examples. Serves as a guided tour of
major library capabilities. No attempt at reference-style
completeness.
Continues overview of all significant capabilities of a library, including
those which might be needed by advanced users customizing or extending
built-in capability. Provides examples of specialized uses extending
beyond normal, basic usage, but still using built-in features of the
library framework. Helps to simplify the
Usage Guide by providing a location for overflow of more advanced
features.
Documents the rules for writing new classes which subclass from classes
that implement the library. Because a library might use complex
combinations of classes to implement the range of behaviors defined by its
types, the classes in a library are not automatically usable as superclasses
of user-defined classes. Each library documents which classes are
available for use as superclasses, and the specific rules that must be
followed when subclassing from these classes.
Explains why choices were made the way they were in the design of the
public interface to a library, including other alternatives considered.
Serves as a "Rationale" document for the documented interface. May
include historical background deliberately left out of the preceding
sections. May also include references to other work.
Explains the structure of classes by which the types of a library are
implemented. Summarizes the status of implementation if still incomplete
and lists items of possible future work. Provides overview and high-level
structure of the implementation in whatever ways would best guide a reader
of implementation source code. May also discuss tradeoffs considered
along with references to related or supporting work.
#import "grid.xt"
Global Object Symbols
The
id <Symbol> North, East, South, West;
Lines that declare global id variables of type Symbol, EventType, Warning,
or Error (using the angle bracket syntax of id variables conforming to
a protocol) are processed somewhat like deftype declarations in that they
also produce global id variables initialized to support particular messages
defined by defobj. These global variables, however, are not used to define
or implement other message interfaces, but only to define certain fixed
capabilities referenced through their global object names.
Interface Design Conventions
A variety of rules on naming and declaration of object types, symbols, and
messages are followed by many of the Swarm libraries. These rules help
establish a basic consistency on the library interfaces. Following is a
list of such conventions that apply to a public library interface, some
but not all of which are derived from standard Smalltalk or Objective C
coding practice:
Documentation Structure
The following standard sections of documentation are suggested for
libraries that follow the strict interface vs. implementation separation
of library modules, each with purpose and typical contents as given:
Roger Burkhart <rmb@santafe.edu>
Last modified: