Structured Symbolic Name Spaces and naming service implemented in Squeak
Last updated at 7:01 pm UTC on 4 February 2008
In real life, names are used for symbolic identification of real things which are known under this particular symbol in the particular context. Such things known by name are notions.
The problem is that in the real world, other things may be ment under the same name in a different context. Notions related to a common context (e.g. to all golf players) are grouped into their common vocabulary which they use when talking with each other (i.e. in "their" context). Some of the words used by golf players may have a completely another meaning within an another community. Let us call such "vocabularies" to be categories - a category contains notions and is able to resolve the particular name and return the relevant object.
I.e., a category is that what we call namespace. A category (namespace) is completely different from a class - while the class is used for modelling the kind of things (their common structure and behavior), categories are used for modelling the symbolic identification of localy or globaly known objects. Classes are notions by default. A category can group completely different classes (from different subtrees). Their subclasses can be located in another categories.
In fact, when we are speaking about real world, we have too few words in natural language to describe the variety of the real world things and situations in an unambiguous way. Hence, we have to use categories - namespaces and contexts to be able to communicate what we mean to other people in the "normal way" - by natural language. If a problem arrises ("does not understand"), a "callback" from the receiver to the sender is started in order to get more information about what had been actually ment by that particular name. Most often, this information is provided by explicit naming the "vocabulary" from which the used word had been taken.
Hence, the real world is polymorphic also in naming the receivers, not only in their responses to the subsequent messages (methods). This enables to achieve the description of the variety of things and situation in real life with the limited vocabulary of natural languages.
Also, in real world namespaces are being specialized. If you have a common namespace for al sciences, then it may be specialized by a namespace for mathematic, then for algebra etc. etc. In each of the sub-namespaces, all notions from the super-namespace are valid (unless redefined) + new notions specific to this particular namespace are added. In a neighbour namespace (with common parent), some names may have another meaning.
- super name space - is one of ancestors of particular name space, so our name space inherits symbols from its super name spaces.
- sub name space - is one of children of the name space. It is super name space to its sub name spaces.
- library - set of classes creating one conceptual integrity.
- package - library
When we are speaking about inheritance rules in concept of name spaces we have to realise the difference between modeling real world objects (and their needs) and habits of programmers developing bussiness systems. There will be allways discussion about multiple vs. simple inheritance. When we are to create model inspirated by real world, it is very usefull to use multiple inheritance of properties, attributes and actions of particular object - it's because each object of the reality belong to many sets - classes (e.g. one can be a teacher, business manager, cooker, ... in one person). The word against this concept is, that using of this feature in real development process can be very complicated (compared to simple inheritance). On the other side simple inheritance in its pure concept is very poor tool for modelling, that's why people developed other mechanisms to compensate these lacks (like using of shared pools, and so on).
In our approach we implemented multiple inheritance of global symbols, because of it's generality. So one name space is a collection of names known in that particular name space. These names are registered either in that name space or in its ancestors. As we can see, one symbol can be registered in many name spaces (and can mean there different object). If we create name space which inherits names from two or more such name spaces, in which is known the same symbol there can arise conflict. Therefore super name spaces in our approach are ordered by its priority. More about this is written in part about identification of an object.
The also important fact is that there exists root of all name spaces in hierarchically structured system. This is not the absolute rule, but it is strongly recommended to hold it. It is practical, because of resolving of names in the system of name spaces. If developer needs to break this rule he has to be very carefull.
With possibility of using multiple inheritance we can also use only simple inheritance, if it's better for developer. Another reason for implementing multiple inheritance mechanism to concept of name spaces is that it gives us powerfull tool for using libraries (or packages). In the ideal case we would be able to divide Smalltalk system of classes to independent libraries (creating hierarchy of libraries) and then use only those we need. For example we can some parts of Smalltalk system can be: Graphics, Core, Sounds, Math, ... And these libraries can also be divided to sublibraries (Math = Algebra, Analysis, Geometry, ...). After that developer will be able to construct his own name space by creating it as subspace of Algebra, Analysis, Sounds, ... He can use only those libraries he needs. It can tend to minimize the size of the image.
If we think more about what was written in previous part, we can see some problems which can appear by using libraries in the way we described upper. If Algebra, Analysis and Geometry libraries are sublibraries of Math and someone wants to use Math as a whole, he will naturaly hang his development name space under Math library. But as we said Geometry is sublibrary of Math and therefore library Math doesn't know any of classes and names used in library Geometry. In Math, there are only general concepts of mathematics so it's natural that it is so.
One solution of this problem can be creating development name space by making it subspace of all sublibraries of Math library. But this approach is very unpractical. Also this is one of reasons of existence of mechanisms like shared pools in implementing class inheritance in Smalltalk systems (but it hasn't roots in concept of libraries).
In our implementation of name spaces concepts we also used mechanism like these pools. In other Smalltalk systems there are implemented such mechanisms called imports of names to the name space. If we want to import symbols known in name space A to name space B, we can do it by adding space A to pools of B.
Sometimes we want some global symbol not to be known in some name space although it is know there, because it was registrated in one of super name spaces. It is usefull for example by compiling of some expression in name space where is some symbol known twice (but there exists order of super name space, so returned is value of object with the name, which was first found by resolving of the name).
We implemented mechanism of shadowing of some known symbols in the name space. It is possible to virtually remove some symbol from name space and if we want, in another moment it is possible to publish it again. If symbol is hiden in some name space, it is no longer known in this space and in its sub name spaces (just if it is predefined in one of them).
We used rather mechanism of resolving names by redefining method doesNotUnderstand: than modifing a compiler. Therefore naming is processed by message sends. If name of some symbol known in particular name space is sent to the object name space it resolves the symbol and returns object associated with that symbol. So if we want to identify object with name BookStore in the name space DownTown, we use expression:
If we need to access to one of super name spaces of particular name space, we can use:
Super Super DownTown BookStore
Identification of an objects
Under the term resolving we understand process of searching of identification of an object, which is known by its name. We know two ways of resolving names in hierarchically structures system of name spaces.
Explicit resolving of names means identification of an object by its absolute path from the root of NameSpaces. For example, if we have root name space World, we have to use expression like:
World Europe Germany Bayern Munchen DownTown BookStore
If such path in the hierarchy of name spaces exists, this expression will be resolved and particular object will be returned.
By implicit resolving is used inheritance hierarchy for searching for an object to the given name. If there's no object associated with given name in actual name space, system tries to search in super name spaces in order which is given by priorities. If the search was successfull in one of the super name spaces recursion stops and found object associated with searched name is returned. If this process was unsuccessfull, system tries to search in its pools. These pools (or imported name spaces) are also ordered by their priorities and this is also respected by searching mechanism. If also this process was unsuccessfull, normal standard error message occurs. User can use also symbol Super, which doesn't mean any particular name space but the set of direct super name spaces of the receiver of this message. By this way we can use relative addressing of objects in the structure according to current name space.
Strategies of implicit resolving
There are several strategies of implicit resolving. Searching mechanism can use backtrack rather then recursive wide searching (Breadth-first algorithm). Or we may discuss if it is better, if backtrack strategy is used, to use inorder, preorder or post order strategy. It depends on developer.
In our approach we implemented backtrack - preorder strategy.
Assignments to global symbols
If there's a symbol registered in one of super name spaces of actual name space and requirement of assignment (redefinig of association with given name) to global variable occurs, we can discuss if it is a claim to create new association in actual name space or if we have to use association from super name space.
In our implementation, when such situation occurs, system asks a user which way it has to manipulate the situation.
Compiling of expressions in UndefinedObject
When an expression is evaluated from some kind of editor, in standard Smalltalk system is this expression compiled in Smalltalk SystemDictionary, which is the only name space of Smalltalk system. Than there is dynamiclally created a unary method DoIt in class UndefinedObject, which is class of object nil, and message DoIt is sent to object nil.
This is not an efficient mechanism if we want to use concept of name spaces. It can be usefull if each name space has its own class UndefinedObject and its own instance of this class. Now all expression which have to be compiled in UndefinedObject class are compiled locally in actual name space using its own UndefinedObject (nil).
Class in name space
From one view (standard Smalltalk systems) we can see that each class is one name space with symbols in pools like are instance variables, class variables, shared pools, ... But to have correctly compiled methods of this class we need all of them to be compiled in the same name space. So we need to make Class know in which name space it has to compile its methods. Therefore there exists instance variable nameSpace in class Metaclass, where is stored name space in which class is compiled. It is of course possible to move class to another name space. After this, the given class will be recompiled in new name space.
The core of the name space framework is class NameSpace. It is subclass of Dictionary class and the class SystemDictionary is subclass of NameSpace. It is because SystemDictionary is only special name space which is used to be a root of all name spaces. It is specialization of the class NameSpace.
As it was said upper the most important methods of the class NameSpace are associationAt: ifAbsent:, at: ifAbsent: and doesNotUnderstand:. In these methods is implemented resolving mechanism. We had to use also special subclass of OrderedCollection. It is called NameSpaceCollection. It is important by resolving the symbol names because of using name Super for super name spaces of particular name space.
Every project (MVC, Morphic, ...) has its own current name space (where everything is compiled). It is possible to change the current name space by evaluating expression
NameSpace setTo: aNameSpace,
or by using a menu command in project menu.
It is possible to fileOut all classes which are stored in the name space. By this, developer is able to create something like package (or library) of classes. If there is some actual name space and user wants to file out some classes to the system, these classes will be compiled and registered in actual name space. This violates previous functionality a little bit and there's too much work undone.
When system of name spaces is used, it is neccessary to have powerfull tools for manipulating it. Therefore we need special kind of class browser and workspace. We implemented very simple browser and workspace to manipulate the hierarchy of name spaces. Browser for name spaces has one additional pane for setting actual name space. According to that, some classes can not be found in actual name space. In this point we violated the organization of all classes in Smalltalk system so functionality of our browser is very poor, but it can serve as a basic for better one.
All of these window hold name space in which was set to them. So if you have few browsers or workspaces opened, each of them can work in another name space. If you activate the particular window, actual name space will be set to the one which is held by the window.
We implemented very poor facility of exporting the code from Smalltalk system. There has to be done better manipulating system with exports of code. If someone will export some change set, there will be no word about name spaces in it. So if someone will have some structure of name spaces and he manipulates classes in it, these changes will not be registered. After exporting change set, no one will be able to tell in which name spaces it was done.
Previous part is also connected with organization of classes in the system. After implementing name spaces it seems to us that there are two ways for the future.
The first is to implement each name space to have its own class organization and then it is neccessary to change also the browsers in that way.
On the other side it is possible to remove class organization structure from the system and each name space will contain only its classes. This is possible way if all categories (like they are in Squeak) will be divided into particular name spaces. (for example there should be a name space under the root with the name Collections and it should have sub name spaces like Abstract, Sequenceable, Arrayed and in these name spaces should be stored classes which belong to the given category (PackageBrowser from Squeak goodies archive was good inspiration for this).
This project was only educational project for Peter Novak and Viktor Zigo. It is the first real thing we made in Smalltalk so it has many bugs and many facilities are not fully implemented. We think that in the state of work it is not the best thing to use this work for real purposes. But it may serve as a inspiration for other developers (maybe also for good experienced Smalltalkers) and it may give some usefull ideas in implementing REAL name space service.
- Allen Wirfs-Brock; Subsystems; published at OOPSLA '96 Extending Smalltalk Workshop; ParcPlace-Digitalk; October 7, 1996
- Augustin Mrazik, Structured Symbolic NameSpaces; ArtInAppleS s.r.o.; April, 1992
- Augustin Mrazik; ; Developing Information Systems with Smalltalk; published at ASU '94 Conference Prague; ArtInAppleS; September, 1994
- CORBA Naming Service Specification; OMG; November 22, 1996
- Peter Marman; Environments II, description of technology; Aitecon s.r.o.; August, 1996
- Posts to related topics on Squeak mailing list in July, 1999
- Implementation of naming service in Visual Works 3.0 programming environment by ArtInAppleS s.r.o.; 1992
- Implementation of naming service in VisualWorks 5i programming environment by ObjectShare