2. THE OBJECT-ORIENTED APPROACH
 
 
INTRODUCTION
 

The aim of this report is to study ways to design reusable model components for the Visual Simulation Environment (VSE). Its technology is truly and fully object-oriented based. However, as every object-oriented language, some concepts of this approach are missing as well as some of them are completely integrated into the software. This means choices have been done for the design of the reusable model components proposed in this report, according to the restrictions imposed and the new possibilities offered by VSE. In order to discuss more easily these choices, it seems important to bring a state of the art of the object-oriented concepts, based on the work of Grady Booch, [Booch 91], who presents a general method for object-oriented design of software. We also base our presentation on the work of David R.C. Hill, [Hill 96], who brings together the techniques of object modeling, software engineering and simulation, underlying that the analysis and the design of software and a simulation model have important similarities. Finally, we use the book of John W. Satzinger and Tore U. Orvik, [Satzinger 96], who presents a clear and progressive introduction to the object-oriented design of information systems. Before going in the details of the object-oriented concepts, let us make a brief presentation of the evolution of computer science to the object-oriented approach, underlying the principal ideas that progressively make this new vision emerged.

 
THE PROGRESSIVE EVOLUTION TOWARDS THE OBJECTS
 

The power of computers is steadily growing. Hence, humans try to design software, model and simulate systems more and more complex. However, the capacity of humans to apprehend this complexity is limited. Hence, in order to manage it, humans have progressively developed concepts. We will see here their evolution, leading finally to the notion of object ([Hill 96], [Satzinger 96]).

 
Subroutines
 

Because machine and assembly languages are definitively difficult to maintain over a certain low number of lines, the first structured languages like COBOL or Fortran rapidly appeared. Before them, programs were seen as a single sequence of instructions. Based on the fact that a same part of the sequence can be rewritten several times in a program and that a single sequence of instructions is difficult to manage, the need in structuring the programs occurred. The notion of "subroutine" was introduced, regrouping instructions in a same entity to form a more sophisticated operation. Hence, structured languages offer the possibility of decomposing a program in operations more elaborated than simple instructions, and regrouping similar operations in parameterized operations. A subroutine is finally written only one time in a program even if it is used several times.

It was the first step towards reusability. By the mechanism of subroutines, a programmer is able to reuse parts of a program written by another programmer. Moreover, he does not need to know the details of how a subroutine works. He only needs to know how to use it, in other words, what are the parameters to give to the subroutine.

Finally, the fact of hiding information, i.e. a programmer does not know how a subroutine works, allows the design of more complex software, because the study can be done by abstracting the details of the subroutines. The first step of analysis concentrates on the organization of the subroutines, which allows the dispatch of the work between several programmers to design each subroutine.

 
Modules
 

But the hiding of the information is incomplete. In fact, subroutines are not always totally independent. Some of them have particular relationships. For instance, a subroutine can use another one to perform its global role, but any other subroutine will never use this subroutine. So, why not hiding it from these other subroutines ? In a same way, subroutines can share data. To do so, the data must be common to all the subroutines. Why not define an area where some data is only visible by a given set of subroutines ?

To complete the concept of hiding information, the notion of "module" is introduced. The subroutines working towards the same kind of service and sharing data are regrouped to form a module. Data and the subroutines of each module are basically hidden from the other ones. Then the programmer can choose data and subroutines to be visible from the other modules. That introduces the notion of "interface", the visible part of the module.

This grows the possibility of abstraction. A program can be seen first as a set of modules with certain relationships. Then, separate analysis of each module can be done before design each subroutine. Moreover, the integrity of the data is also increased because the hiding of data avoids the manipulation of it by other ways than those specified by the subroutines of the module.

 
Abstract Types
 

In some cases, it occurs the need to duplicate the data of a module. D. Hill gives the example of a stack of elements to illustrate that. The data structure of the stack is part of the hidden data of the module. Subroutines are used to add, access or remove an element from the stack. But, how can different stacks be in the same program ? Because the languages implementing the notion of module do not allow this kind of duplication.

To solve this problem, an extension of the module was proposed in languages like Ada, allowing this wanted copy of data. The notion of "abstract type" completes the notion of module. This allows the definition of a new type in a program by defining a structure of data and a set of operations to manipulate it. Then elements of this customized type can be created and can be manipulated only with the set of operations provided with their type.

 
Objects
 

The need to find general solutions for simulation problems introduced a new language, SIMULA, and a set of new concepts in the mid-sixties. The notion of abstract type was reinforced in the notion of "class" that unifies the data and the operations in a same entity. A class forms a model for the creation of objects in a program, just like a type. The concept of "inheritance" was also introduced, allowing the classification of the classes according to their similarities. A class is able to give its particularities to another one.

Soon, other languages followed. In the seventies, there was Smalltalk, which introduced the term of object in the programming context and formalized the interaction between them by the notion of "messages", which is in fact the request of an object to ask another object to perform one of its operations.

In the eighties, several existing languages were extended to incorporate object-oriented features. There were C++, object-oriented versions of Pascal... In the late eighties and early nineties, graphical user interfaces (GUIs) became increasingly common and packages were provided allowing programmers to create a graphical interface without programming, only by assembling graphical objects. Finally, in the beginning of the nineties, the Java language appeared. It is a general object-oriented language supposed to be extremely portable, supporting international use and offering facilities to be used through networks like the Internet ([Niemeyer 97]).

 
MANAGE THE COMPLEXITY OF SYSTEMS: CONCEPTS
 
 
Introduction
 

The complexity of software or any other systems in generally too important to be understood clearly by humans. Moreover, a team of analysts and programmers is usually needed to analyze or design complex systems. Hence, the communication between them grows the difficulty of understanding the whole problem. To be able of manage this complexity, analysts and programmers have developed different concepts: the "abstraction", the "encapsulation", the "modularity" and the "hierarchy" ([Booch 91], [Hill 96]). Their presence in the notion of object we will introduce soon forces us to present them briefly.

 
Abstraction
 

A way humans use to apprehend the complexity of a system is the abstraction. As we seen before, the programmers progressively develop this notion through subroutines, then abstract types. They abstract the functions of a system by defining this system with operations more conceptual than the basic instructions of a language. They forget for a while the implementation of the functions to concentrate only on their role. With abstract types, the programmer isolates his mind from the data structure of the types he manipulates. He only needs to know what kind of information this type can provide to him, but not how it is implemented in the language.

 
Encapsulation
 

As we briefly seen before, the notion of object is more powerful than the concept of abstract type, in the way it completely encapsulates the data and the operations upon them in a same entity, an object. A maximum of information is hidden from the user of an object. Only a partial but sufficient view of the object, called the "interface", is provided to him. The notion of encapsulation is important to avoid a user of an object to know details about the implementation. The presentation of only the interface allows him to concentrate only on the global functionality of an object. Hence it reinforces the notion of abstraction.

 
Modularity
 

Another way humans usually use to study a problem is to decompose it. The whole system is too complicated to be analyzed directly. But parts of it are simpler and may be more easily understood. In software programming, we call these parts "modules". However, the decomposition of a system in modules must be chosen very carefully. The different modules must be as independent as possible, whereas the elements of a module should be strongly related by a sharing of data or functionality ([Booch 91]). Then the capacity of abstraction of humans may allow the understanding of the isolated modules.

 
Hierarchy
 

We saw before that a system, by the mean of abstraction, is decomposed in entities. But usually they are numerous and the complexity of the system stills a large problem. To simplify our view of the system, the classification of these entities is usually necessary. G. Booch underlies the need of two kinds of classification during the study of a system. They are independent but totally complementary. G. Booch qualified the first kind of classification as "part of". Some entities of a system can be considered as parts of a bigger entity of the system. The other kind of classification is qualified as "kind of". Entities can be regrouped by category due to their similarities. In other terms, a category represents a kind of entity. Then, relationships between categories can be established. Some categories of entity can also form a more general kind of entity. Hence, these two kinds of classification form two separate hierarchies that help understanding a system.

 
CLASSES AND OBJECTS
 
 
Introduction
 

Numerous object-oriented languages have been developed since SIMULA. The notion of object has evolved and has been adapted for various purposes, each new language proposing a different implementation of the concepts. Hence, around the basic notions of the object-oriented (OO) approach, there are different variants. We try here to present these possibilities of interpretation of OO and discuss them. First we will introduce the terms "object" and "class of object". We will see that objects interact with each other through messages and are organized in classes. Then we will discuss the relationships existing between objects and classes.

 
Object
 
 
Definition

Until now, we briefly defined an object from the point of view of programming, as an entity encapsulating data and operations. But the notion of object is more general like that. This notion is supposed to be natural. Everybody agrees to say that our perception and representation of the world is based on this concept. Lots of definitions for an object are given. We finally choose the following definition from [Booch 91].

"From the perspective of human cognition, an object is any of the following:

  • A tangible and/or visible thing.

  • Something that may be apprehended intellectually.

  • Something toward which thought or action is directed."

We just add that in the context of software design or system modeling, an object is considered as such only if it presents a certain interest for the study.

 
State

An object naturally has characteristics, properties that defines what it is. In the context of OO, these are called "attributes" and form the "structure" of the object. The set of properties an object possesses is usually static. It rarely changes, contrarily to the values, qualitative or quantitative, of these attributes that are usually dynamic. The properties of an object and their values at a given time characterized the "state" of this object at this time. An object evolves only by changing its state.

 
Behavior and Message Passing

Usually objects are not isolated. They are acted upon or/and they act upon other objects. For this, the notion of message is introduced. An object can act upon another one by passing it a message. According to Booch, "the behavior of an object is how an object acts and reacts, in terms of its state changes and message passing" ([Booch 91]). Hence, a set of actions, called "methods" in this report, is associated with each object and forms its behavior. The passing of a message from an object to another consists in an order. The sender object asks the receiver to perform one of its methods. As the attributes, the set of methods is usually static. Few languages allow the dynamism of the set of attributes or the set of methods.

Booch classifies the methods in five kinds of operation. The three first are common to most of the object-oriented languages and the two last ones are more specific to some languages such as Smalltalk or C++.

  • "Modifier" method that changes the state of the object.

  • "Selector" method that only accesses the state of the object.

  • "Iterator" method that accesses attributes of the object in a well-defined order.

  • "Constructor" method that is performed when the object is created.

  • "Destructor" method that is performed when the object is destroyed.

 
Identity

In the reality, concrete objects are always distinguishable because they never have exactly the same state. For instance, the position of two objects is different. In a computer, two objects can be also distinguished for instance by their location in the memory. This particular property that distinguishes an object from another is called "identity".

This innocuous statement raises an ambiguity illustrated by the following example. In a computer program, programmers use to distinguish temporarily different objects by giving them a name. For instance, imagine a program with two objects. Two names are declared, each one referencing an object, for instance Object1 and Object2. If the programmer writes the following kind of line, using the assignment symbol of the language:

Object1 = Object2;

What does that mean ? Does the name Object1 reference the second object or does it always represent the first object with its state replaced by the state of the second one ? Of course, it depends on the language. But in the first case, we talk about "structural sharing", it is the identity that is duplicated, and in the other case we talk about "copy", it is the state that is copied. The same kind of question arises when comparing two objects. Are the identities compared or the states ?

That just raises the question: In the modeling of a system, must the identity of objects be explicitly defined or is the mechanism of the language sufficient for the purpose of the problem ? For illustration, just imagine you want to store objects in files and conserve the identity of the objects when you load the objects back from the files. More details on this last problem are discussed further in this section, in the paragraph about the persistence.

 
Class of Object
 
 
An Abstraction

In complex systems there can be really a lot of objects. But the number of different kinds of object in it is more limited. That is why the notion of class of object is introduced. A class is an abstraction that represents a kind of object. In fact, objects that have the same structure and the same behavior belong to the same class. Hence the designer or the analyst will not at first define each object of the system, but will concentrate only on the classes of object.

 
Instantiation

A class is a template for the objects its represents. The objects will really be created according to this template. This creation is called "instantiation" and the objects created are qualified as "instances" of the class. There is a real difference between a class and an object. An object can not be a class but a class can be an object. This last particularity is discussed in details further in the relationships between classes and objects, with the notion of metaclass.

 
Public, Protected and Private Parts

Like a module, a class has private and public parts. The last one is also called "interface". Usually, all the attributes and the implementation of the methods are placed in the private part. The interface only contains the name of the methods of the class. Of course, methods can be totally private if only used by the object itself. We will see later that some classes have a particular relationship, based on the concept of "inheritance", called "specialization". Because of this, parts of a class can be "protected", meaning that the classes that are specialization of a class can access directly some data or methods of this class that are not public normally for the other classes. Finally, some languages like C++ allow the friendship between two classes. This means a class can access directly the private part of another class. This is used when two classes are extremely related, like for instance, a collection of objects and the iterator to access them in a specific order.

 
Relationships Between Objects
 
 
Using Relationship

The using relationship is directly related to the message passing. If an object passes a message to another one, we say that it uses the other object. By this way, we can define three kinds of object in a model ([Booch 91]).

  • "Actor" is an object that acts upon other objects but is never acted upon. This kind of object is called an "active" object, whereas the others are qualified as "passive".

  • "Server" is an object that is only acted upon but never acts upon other objects.

  • "Agent" is an object that both acts upon other objects and is acted upon.

 
Containing Relationship

This kind of relationship is related to the classification "part of" we discussed previously with the concept of hierarchy. An object can be a part of a bigger object. This forms a hierarchy of objects that Booch called "object structure". We will see later that this structure is important in the modeling of a system.

 
Relationships Between Classes
 
 
Simple Inheritance

We saw that to define objects, we regroup them in classes according to their similarities. If we regroup objects that have a lot of similarities, we will have a specialized class whereas the regrouping of objects having just some similarities will form a more generalized class. By this way, it is possible that an object of a specialized class also belongs to a more generalized class. This means the specialized class has at least the properties of the more general one.

From this statement, we can organize the classes in a hierarchy where the most general classes are divided in more specific classes, and so on. So a relationship between a generalized class, the "superclass", and one of its specialized classes, the "subclass" is called "inheritance". A subclass inherits the characteristics of its superclass. This means the methods and the attributes of the superclass are given to the subclass. New attributes and methods can also be added to the subclass to define its specific characteristics. Moreover the inherited methods can be modified or replaced. For more information, see further the paragraph about polymorphism.

Booch calls the hierarchy of inheritance "class structure", referring to the concept of hierarchy defined previously. With this classification, classes can not always be instantiated. Figure 5 shows the example of a superclass Vehicle specialized in three subclasses Truck, Car and Bus. It is possible to instantiate objects like a truck, a car or a bus whereas it is impossible to instantiate a vehicle object directly. Such an object has no signification. Classes like Vehicle are qualified as "abstract". Their purpose is only organizational.

Figure 5: An Example of Abstract Class.

The inheritance offers a best abstraction of the classes and also avoids the programming of the same methods several times. Moreover, we will see later that objects of a specialized class can be manipulated as objects of a more generalized class. Hence the analyst can reason with a set of objects without considering the specialized class of each object, but only with the generalized class that characterizes all the objects of the set. This aspect is explained in details further in the paragraph about polymorphism.

 
Selective Inheritance

As [Hill 96] explains, it appears sometimes that all the methods of a superclass are not desired in a subclass. In this case, we talk about "selective" inheritance. The methods and attributes to inherit are selected. This selective inheritance is not a fundamental concept but is provided by some languages such as C++. [Hill 96] proposes a way to obtain the same result with only the classical mechanism of inheritance.

Figure 6: Selective Inheritance.

Figure 6 shows a subclass B inheriting from a superclass A, the method X is excluded from the inheritance. Figure 7 describes a solution to avoid this selective inheritance. Simply, the superclass A has not the method X and two intermediate subclasses of A are defined: the class A' which is here identical to A and the class A'' which is completed with the method X. The class B just has to inherit from the superclass A'.

Figure 7: A Solution to Avoid the Selective Inheritance.

 
 
Aggregation Relationship

This kind of relationship is similar to the containing relationship between objects. The difference is that every object of the class has the relationship with another object of another class whereas with the containing relationship, a specific object as a relationship with another specific object. So this relation, called "aggregation", specifies that an object is composed of other objects, these belonging to given classes.

 
Multiple Inheritance

Some languages allow the multiple inheritance. That means a class can inherit characteristics from more than just one superclass. This kind of inheritance is not a standard of OO because it rapidly presents a lot of ambiguities.

[Hill 96] presents the problem of repeated inheritance illustrated by Figure 8. In fact, the class D inherits several times the properties of the class A through the multiple inheritance of B and C. There are three approaches to deal with this problem ([Booch 91]). First, the repeated inheritance can be considered as illegal. Second, the repeated inheritance can be accepted, but to use the methods duplicated, the class from which they are inherited must be specified. Third, when a method of a class appeared several times in a subclass, only one copy is kept.

Figure 8: Repeated Inheritance.

[Booch 91] presents also the problem of name collision. Imagine two classes A and B totally independent with the same name X for a method. The object C inheriting from both the classes A and B will be confused about the methods with the same name X. Like for the repeated inheritance, different approaches are proposed to avoid the problem. First, the collision is considered illegal. Second, a method with the name X must be defined explicitly from one of the two methods X inherited. Third, it can be possible to call the method by specifying explicitly which class to use.

Figure 9: Name Collision in Multiple Inheritance.

Because of these problems and the various possible ways to solve them, some people think it is a bad design using the multiple inheritance. Another reason to refuse the multiple inheritance is that confusion is often done between the aggregation relationship defined previously and the multiple inheritance.

For instance, as [Hill 96] presents, an Awacs, a plane with a radar, can be considered either as an object inheriting the properties of both a plane and a radar or as a plane that possesses a radar. But these two representations are different. In the first case, the Awacs can be manipulated as a plane as well as a radar (see the next paragraph for more details) whereas in the second representation, it can be considered only as a plane. That is why multiple inheritance can be useful in some cases. Hence, a new approach of the inheritance has been proposed in the conception of Java (see further the paragraph about interface implementation).

 
Polymorphism and Dynamic Binding

We saw that a subclass inherits the structure and the behavior of its superclass. Then, it is possible to complete them by adding new data or new methods. But it is also possible to modify or replace completely a method. For that, the programmer is allowed to create a new method that has the name of an inherited method. He writes the code he wants in it, he can even call the inherited method having the same name in the superclass. This new method will replace the inherited method. This action is called "overriding". This means that when a message is sent to the object with the name of an overridden method, this is the last method defined in the inheritance hierarchy that will be executed.

But there is something more interesting presented by [Booch 91] and [Hill 96]. Figure 10 shows a graph of inheritance. The superclass A defines a method X and its subclasses B and C redefine the method X as we explained above. Now, we consider a collection of objects. In the program, we only know that they belong to the class A. But they can belong to the subclass B or C. Imagine we send the message X to each object of the collection, knowing only that they belong to A. If the object belongs just to the class A, the method X of this class will be called, but if the object belongs to the class B or C, the method X of these classes will be called, whereas we do not even know that the object belongs to one of these classes. But an internal mechanism identifies the class of an object and finds the right method to call.

Figure 10: Polymorphism.

Some languages also allow the "overloading" of a method. This means the same name can represent different implementations of a method. The distinction is done with the type of the parameters or arguments the method receives. This is called the "arguments signature" of the method. So for each different signature, a method can be defined. When a message is sent, a mechanism identifies the right method to execute. The following example illustrates this purpose. If we imagine an object having the method Add to add a number to one of its attributes. The method has three different forms, depending on the nature of the number. It can be an integer, a real or a complex number.

  • Add(integer)  Add(3)

  • Add(real)  Add(3.02)

  • Add(complex)  Add(3 + 2i)

These examples illustrate the notion of "polymorphism", the possibility for a method to have several forms. In the first example, the method X called can not be defined during the compilation, the precise class of the object manipulated is unknown at that time. This means that, during the execution, the right method should be found. This possibility of dynamic call of a method is named "dynamic binding" opposed to "static binding" which is a call to a method perfectly determined at the compilation time.

This is an important aspect of inheritance. With the possibilities of abstraction, classification, the notion of polymorphism offers a lot of possibilities compared to classical programming languages. We will see later that the inheritance with all its properties is really useful for the reuse of software component.

 
Interface Implementation Versus Multiple Inheritance

Multiple inheritance brings a lot of problems. Hence, the Java language has been built with a new approach ([Niemeyer 97]). As we saw before, a class has a public part, the interface, and a private one, the implementation. When a class inherits from a superclass, the subclass inherits its interface and its implementation.

Figure 11: Interface and Implementation with Multiple Inheritance.

As the problems from multiple inheritance are due to conflicts in the gathering of several implementations, Java proposes the following approach. A class only inherits from one superclass. Then, it can implement as many interfaces as wanted. In other words, a class inherits only one implementation and one or more interfaces. The new methods introduced by the interfaces must be implemented.

Figure 12: Interface and Implementation with Java Inheritance Mechanism.

Figure 11 illustrates the traditional multiple inheritance, a subclass C inherits the interface and the implementation of both superclasses A and B. Then, the class C extends its capacity through its own interface and implementation. Figure 12 shows the similar inheritance with Java. The subclass C inherits from the superclass A and implements the interface of the class B. Considering only the interface, the result is exactly the same as with the classical multiple inheritance. But for the implementation, we can see that only the implementation of A is inherited and the implementation of the class C is extended. To obtain exactly the same result, i.e. inherit the implementation of B, we recommend adding an attribute of class B to the class C. By this way, the behavior of the class B can be used.

An interface can be defined independently of a class. Alone, an interface can exist. Figure 13 shows the same example as above but the interface B is defined without the class B. The interfaces have the inheritance relationship, that means an interface can inherits from other interfaces. Moreover, the multiple inheritance of interface is allowed. No particular problem appears.

Figure 13: Interface, an Independent Entity with Java.

An interface expresses what a class can do but does not specify how to do it. Hence, like a class, each interface defines a new type of object. A class implementing an interface matches with the type corresponding to this interface. Hence, an object of such a class can be manipulated as an object of the type defined by the interface, using the methods of this interface. To conclude, the notion of interface is interesting but not fundamental because an abstract class can provide the same service ([Stroustrup 96]).

 
Using Relationship

Like the containing and aggregation relationships, a distinction must be done between the using relationship between classes and the same relationship between objects. In the first case, this relation means that a class uses the services of another class. This means the former class needs to know the interface of the latter one. In the case of objects, the using relationship means a given object sends a message to another given object.

To return to the classes using relationship, a class uses another one in two different circumstances. First, in the declaration of its interface, a class can request an object of another class as parameter or return object of a method. Second, during the definition of the implementation of a class, an object of another class can be manipulated. In the first case, the fact that a class uses another one is public whereas, in the other case, it is private. That implies two different things in term of dependencies illustrated by the following pseudo-code.

Interface of Class_D:
Uses Class_A, Class_B, Class_C;
Has method X with parameters: Class_A, Class_B;
Has method Y with parameters: Class_B, Class_C;
...
Implementation of Class_D:
Method X with Parameter_1 of Class_A, Parameter_2 of Class_B:
...
Method Y with Parameter_1 of Class_B, Parameter_2 of Class_C:
...

Interface of Class_E:
Uses Class_B, Class_C;
Has method X with parameters: Class_B;
Has method Y with parameters: Class_B, Class_C;
...
Implementation of Class_E:
Uses Class_A;
Method X with Parameter_1 of Class_B:
...
Method Y with Parameter_1 of Class_B, Parameter_2 of Class_C:
...

The class D uses the classes A, B and C in its interface and implicitly uses the same classes in its implementation. Whereas the class E uses the classes B and C in its interface and uses implicitly the same classes plus the class A in its implementation. The class D corresponds to the first case of using relationship presented previously and the class E corresponds to the second one. The use of the class D in another class implies that this class depends on A, B, C and D, whereas the use of the class E induces just the dependencies with the classes B, C and E.

In other words, dependencies in the interface of a class grow dramatically the dependencies of the classes using it. This means a failure in the mechanism of abstraction because using a class or a module can induce more than one dependency. Moreover, from a technical point of view, that grows the compilation time, which can be a serious and costly problem for large applications.

 
Instantiation Relationship

This kind of relation is well known for the modeling of collections of objects or for the definition of general arithmetic functions. Here are the problems of these two kinds of modeling.

Imagine a programmer wants to define a class to describe a collection of objects. In other words, a class Collection gathers objects and provides different services to manage them. Of course, the class of the objects (noted A) in the collection is clearly indicated in the definition of the collection class. Hence, a first problem arises when the programmer wants to use his class Collection for another kind of object, belonging to the class B. The idea is to define a superclass for both classes A and B. In this case, the collection can be used indifferently for objects of the class A or B. Usually, if the hierarchy of inheritance has a unique most generalized class, this class is chosen to define objects managed by the collection. But that induces a collection can store objects of the classes A and B at the same time. Maybe the programmer does not want that. A solution is to control the class of the objects that are stored in a collection. But this solution is not really generic and does not avoid errors from the programmer. How to have an automatic control of the class in the collection to be certain of the class of the objects ?

Let us look at another problem. Usually in programming languages, there are different types to represent a number. Generally, we have integer, real and sometimes complex numbers. Moreover, as the memory of a computer is limited, the numbers represented are limited too. Hence, different sizes of representation are provided, like short, long, double in C++. So, we have some different ways to declare a number. This means that when we define an arithmetic function, it should be defined for each kind of number if its purpose is general. To avoid this redundancy, a more generic solution must be provided.

The solution for these problems is to define a parameterized class or function, the parameter being the type of the objects manipulated by the collection or the type of the numbers manipulated by the function in the examples. Notice that such classes or functions are templates of classes or functions. They can not be used directly. From these templates, called "generic" classes or functions, classes and functions will be defined by specifying the parameters. As a generic class represents what is a class, it is called a "metaclass". For the same reason, a generic function is a "metafunction". The kind of relationship between a metaclass and its classes is comparable to the relationship between a class and its objects. It is called "instantiation".

 
Classes as Objects

As we briefly said before, it is possible to consider a class as an object. That means a class can describe what is a class, so a class will be instantiated as an object. We just defined before that such a class is called a metaclass. It is a class of class. Instances of such a class are classes. That also means that a class has a behavior and a structure. Languages like Smalltalk directly support metaclasses, but other languages like C++ do not explicitly support this concept. They introduce the notion of "class attributes" and "class methods" opposed to the notion of "instance attributes" and "instance methods". Class attributes and methods are characteristics of the class whereas instance attributes and methods are characteristics of the objects of the class. Until now we implicitly talked about instance characteristics. In languages like C++, class and instance characteristics are declared together and are just distinguished by the word static in the language. Some other languages like CLOS also consider methods and parameterized functions as objects and introduce the general notion of "metaobject".

 
Concurrency
 

Some kinds of problem and particularly simulation need the use of distributed software. This means a program is not considered as a sequential set of instructions but separated in several entities that can be executed simultaneously and share data. OO is particularly adapted to this kind of system, because its decomposition in objects allows the entities to be executed simultaneously. The message passing represents a way to communicate between the different entities and, by this way, share data.

Of course, this kind of system introduces a lot of problems about the sharing of data and the integrity of the operations. With OO, the share of data is partially resolved, because there is only one way to access the data, it is through the methods of the object encapsulating the data. Then, techniques must be elaborated to guarantee the integrity of the actions realized. It depends on the real nature of the mechanism of concurrency in the software. For instance, the way an operating system operates to execute concurrent actions is different from the way a simulation software operates.

In the first case, the processor will cyclically execute a part of each action to give the illusion of simultaneity. For instance, to control the integrity of the actions, Java offers the possibility of forbidding the execution at a same time of methods of a same object ([Niemeyer 97]). In the case of simulation software, the time is usually a variable managed by the software and is not the real time. By this way, it allows a different way to execute "simultaneous" actions. They can be executed sequentially. But conceptually and according to the time variable, they are executed at the same time. Of course, even if this kind of concurrency is simpler, it stills some problems to guarantee the integrity of the actions and usually this is the programmer of the model who must be careful about that.

 
Persistence
 

Objects in a program can be classified due to their lifetime, also called "persistence", in six categories ([Booch 91]).

  • intermediate results during expression evaluation,

  • local variables of a method or function,

  • global variables,

  • data existing between executions of a program,

  • data existing between various versions of a program,

  • data that outlives the program.

The first three kinds of persistence are usually offered by the traditional languages. But the last ones are more difficult to guarantee. They imply a specific mechanism that gives rise to the object-oriented databases. They requested not only the storage of the data of each object but also information about the class of the objects.

 
Type and Class
 

A difference stills between a type and a class relatively difficult to discern. [Booch 91] gives the following definition of a type.

"Typing is the enforcement of the class of an object, such that objects of different types may not be interchanged, or at the most, they may be interchanged only in very restricted ways."

However, Booch recognizes that for most people, separating the concepts of type and class is utterly confusing and adds very little value. It is sufficient to say that a class implements a type. But with the new approach of interface proposed by Java, the notion of type regains sense. A class as well as an interface can implement a type.

 
CONCLUSION
 
 
Is Everything an Object ?
 

A question remains open: Is everything an object ? According to Booch, there are things that are distinctly not objects such as time, beauty, color... ([Booch 91]), whereas Satzinger and Tore try to show that everything can be, in some ways, an object ([Satzinger 96]). It depends on the point of view. We will not discuss here this philosophical question, but we tend to agree with Satzinger and Tore. It seems possible to find a point of view that considers every "thing" as an object.

 
Modeling Difficulties
 

The previous question illustrates the fact that OO design or modeling is not so easy. Everybody agree to say that the notion of object is a natural approach for humans. [Satzinger 96] and [Booch 91] present the example of a baby who organizes progressively its perception of the real world using the concepts previously presented. So, why software design and modeling are so difficult with the OO approach ?

In fact, the way people model a system with the OO approach is extremely closed to the context of the study and the point of view of the designer. This means the end user of software and the programmer of the same software have different OO views and the difficulty is for the programmer to adapt his view to the user's one. In a same way, different kinds of application will introduce different OO interpretations of the same things. And finally, it appears that people who learn to design with classical methods (other than OO) and mastered them can have difficulties to adapt their view to the OO approach ([Satzinger 96]). Finally, the difficulty is that an object in the real world can be representing in a way completely different from the natural representation. [Satzinger 96] gives the example of the database of a veterinary. Usually, people see a dog as having a name, eating, sleeping... It is the natural OO representation of a dog. Now in the database of the veterinary the dog has also check up results, can be scheduled for an appointment... but the actions of sleeping, eating... are not considered. This last representation is a bit perturbing and illustrates the difficulty of designing with the OO approach.

 
Quality of an Object-Oriented Design
 

To finish with the presentation of OO, we rapidly present the qualities a design should have to guarantee the advantages expressed further. [Booch 91] measures the quality of OO design according to five aspects.

  • Coupling, that characterizes the importance of the relations between modules.

  • Cohesion, that characterizes the importance of the relations between classes inside a module.

  • Sufficiency, that expresses the fact that a class or a module presents enough meaningful and efficient methods for its purpose.

  • Completeness, that expresses the fact that a class or a module presents all the meaningful methods for its purpose.

Booch advises to limit the coupling between modules and underlies that the cohesion of a module should be important. Of course, the sufficiency of a class or a module must be reached and the completeness is an aim that we are never sure to reach. Of course, these qualities are not always compatible with the constraints of speed and memory space. Hence, trade-off must be done, according to the final use of the software.

 
Advantages of the Object-Oriented Approach
 

OO is a powerful way to express complex organizations due to the concepts of abstraction, encapsulation, modularity and hierarchy. So this approach is particularly adapted for the purpose of simulation. Moreover, all these concepts add possibilities of reusability of software components. By this way, time can be gained on the design of further systems. Moreover, it also simplifies the maintainability of the software, facilitating its evolution, and allows the incremental development of software.

OO is a powerful mean of representation, however this approach is not perfect and complete. Jeff Rothenberg presents in an article ([Rothenberg 89]) some possibilities of extension of OO for the purpose of simulation. Although the paper dates from 1989 and by this way some of the extensions proposed have been integrated in some simulation software, it remains interesting about some ideas of evolution for OO simulation and languages, and expresses needs that are not fully satisfied even with the actual OO languages.

 
 
Copyright (c) 1999-2016 - Bruno Bachelet - bruno@nawouak.net - http://www.nawouak.net
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation. See this license for more details (http://www.gnu.org).