The Visual Simulation Environment (VSE) is an object-oriented language dedicated to simulation. It allows the modeling of discrete-event systems based on a visual and hierarchical representation. This software wants to be as general as possible in the context of discrete-event simulation. Its truly and fully object-oriented and component-based technology allows the creation of reusable components and offers the possibility of developing reusable libraries for a category of system. Hence, progressively, the set of libraries provided with VSE is growing to offer generic solutions for more and more systems. In fact, VSE integrates many concepts of reusability in order to allow the creation of complete models based on libraries with a minimum of programming.
In a first part, we present the VSE software and how the concepts of the object-oriented paradigm, component-based software engineering and software reuse have been integrated. Then, we will see how to create a model of a system using this software. But first of all, here is a brief presentation about the birth of VSE.
The ever-increasing complexity of simulation models creates the need for automated support throughout the whole development life cycle of a model. Such a support can be provided in the form of an environment composed of integrated software tools providing computer-aided assistance in the development of a simulation model.
Professors Osman Balci and Richard E. Nance started a research project in June 1983, under funding from the US Navy, to pursue research in building a discrete-event Simulation Model Development Environment (SMDE) ([Balci 92]). Guided by the fundamental requirements identified by Dr. Balci, incremental development, evolutionary prototyping, and rapid prototyping approaches have been used to develop the prototypes of SMDE tools. The object-oriented paradigm, enunciated by the Conical Methodology, has furnished the underpinnings of this collection of tool prototypes. In 1987, the research project began investigating visualization and increased emphasis on the use of the oriented-object paradigm. As a result, a Visual Simulation Support Environment (VSSE) prototype was developed in April 1992.
Based on the experience gained from the use of the SMDE and VSSE prototypes, the development of VSE started in August 1992. A fully functional research prototype of VSE was developed at Virginia Tech in 1995. Technology transfer, enabled by the creation of Orca Computer, Inc. ([Orca Web]), has produced the first commercial version of VSE in November 1996. Technology transfer is the sharing of technology, developed usually at a government facility, with the public and/or the private sector ([Balci 97b]).
VSE provides different tools to guide the user in the development of a model. Basically, there are three applications, one for each main step of the life cycle of a VSE model. The first is for the design of the model, the second is for the simulation of the model and the last one is for the probabilistic analysis of the results. So, we will see now the main characteristics of each one, but focusing especially on the design part.
The VSE Editor software is used to design a simulation model. It provides different tools, appearing as different windows. We will begin by describing those we can find in every classical object-oriented language and then, we will go on with those that are specific to simulation and especially to VSE.
This window allows the user to define classes for the purpose of his modeling. Like in every object-oriented language, VSE allows the user to define its own classes and allows him to structure them with the concept of inheritance. By default, VSE provides a set of classes that performs the basic operations in the model. From these standard classes, the user must inherit his own ones. As shown by Figure 19, the upper part of the window defines the graph of inheritance. If reading from the left to the right, we see the hierarchy from the most generalized classes to the most specific ones. The classes beginning by the letters VS are classes provided with the standard library of VSE. In this example, we see that the class VSShape has the subclasses VSComponent, VSEntrance, VSExit... Then, the class VSComponent has the subclasses BusArea, BusStop, ExitForPassenger...
VSE does not allow the multiple inheritance. It is justified by the fact that this kind of inheritance can induce different kinds of ambiguity ([Hill 96]). Moreover, the characteristics wanted for the multiple inheritance can be replaced by some well-known patterns we describe in the chapter about the OO approach. Finally, VSE allows the dynamic binding that avoids often using the multiple inheritance. We will discuss this dynamic binding further when we will describe the standard library of VSE.
After a class has been placed in the inheritance hierarchy, its attributes and its methods must be defined. For this, VSE provides an editor, in the lower part of the window. A distinction is clearly established between class and instance characteristics. Attributes can be defined as shown by Figure 19. In a same way, methods can be defined in a language wanted to be as natural as possible (see Figure 20). The methods can be organized by category, which has no effect on the model. The overriding of the methods is allowed. That means the methods inherited can be modified or completely rewritten, which is a powerful concept for reusability.
We can see that importance has been given to the documentation. The editor integrates explicitly areas to put documentation about the class itself and for each of its methods (see Figure 21). This is also an important element for the reuse of the classes, because people who reuse them have a clear access to this documentation.
Finally, VSE integrates explicitly the visual aspect of the objects of a class. As shown by Figure 22, a class can have one or more images to represent visually its objects. There, the user specifies the pictures he wants to represent the objects of a class. One of these pictures can be defined as the default representation. To have a visual representation, an object must inherit from the superclass VSShape. Hence it possesses an attribute image from the class VSImage. It also possesses methods to access this image, change it... Then, during the simulation, VSE will automatically display the object through its current image attribute. The standard classes like VSShape and VSImage are described further in this chapter, when presenting the standard library.
We discuss now about the language used to define the behavior of the classes, in other words, the logic of the methods. This language is wanted to be as close as possible to the English language. In this aim, it provides different forms to invoke methods of an object, for the mathematical statements...
The following examples of the VSE language illustrate the possibility of writing relatively readable programs.
Hence, the user has to choose the most appropriate form of expression. Moreover, it is recommended that the user defines methods and attributes in a way that makes English readable sentences when they are used.
To conclude, unlike most of the classical object-oriented simulation languages, VSE provides a tool that integrates explicitly the documentation of the classes and their visual representation. We will see that these aspects are very important for reusability.
A model is an organized composition of objects that communicate together to make the model dynamic. These objects are instantiated from the classes defined previously. For a visual representation, VSE proposes a hierarchical decomposition of the model in components. We will see soon what is a component in the context of VSE.
The model is composed of static objects, which never move in the model, and of dynamic objects, which move in the model. By moving, we mean changing physically (e.g. a customer in a service area) or logically (e.g. data in a network) of location. A VSE model consists in a static hierarchy of components (see Figure 23) and several dynamic components moving in it. Each dynamic component can be decomposed in a static hierarchy of components ([Balci 97d]).
To illustrate our purpose, we will consider a bus system, in the town of Blacksburg. The buses move between stops, picking up customers and bringing them to another stop. A model of the static part of this system is shown by Figure 24. The main component is the town of Blacksburg. It is composed of stops, between which the buses move. Each stop is decomposed in components representing more precisely the area where the buses stop, the area where the customers wait and a component through which the customers leave the stop. This defines the static hierarchy of the model.
In a same way, we present the dynamic part of the model. There are customers represented by a non decomposed component, called "shallow" component, opposed to a "deep" component. The other kind of dynamic object existing in the model is the bus, decomposed in seats for the customers (see Figure 25). The bus is a deep component, it is a hierarchy of components, like the static hierarchy of the model.
Briefly, we will explain now the concept of component. As we have seen briefly before, an object is visible if it belongs to the standard class VSShape. In a same way, an object is considered as a component if it belongs to the standard class VSComponent, a subclass of the VSShape. The main property of the objects of this class is that they are decomposable. Methods are available to access information about this decomposition. Moreover, methods are provided to manage the movement of dynamic objects in the components. Then, as a component can be dynamic, there is a standard subclass of the VSComponent class, VSDynamicObject that adds the property of moving to the components. These classes will be detailed further in the description of the standard library of VSE.
Based on experiences in using VSE ([Balci 97c]), it is recommended to separate the design of the static architecture from the dynamic one. In fact, the static architecture is usually created one time in the model, whereas there are more than one dynamic object in the model. That means the same architecture of dynamic object is created several times in the model. For that, VSE proposes to build a template of the architecture of a dynamic or static object that can be instantiated several times in the model. Each time an object is needed, a copy of the template is performed. That means the whole hierarchy of components of the object is copied and the attributes of each component are also duplicated. So, an exact copy of the template is performed. But the attributes can then be modified to personalize the new object if it is wanted.
In our example model, the bus object, a dynamic one, and the stop object, a static one, are instantiated several times in the model, so it is recommended to create a template of these objects. Then, a copy of them can be performed, at the design time for the stops, and at the run time (i.e. during the simulation) for the buses.
So, two windows are used to build the architecture of the model: the component hierarchy window and the template window. To build an architecture of components, the user has the possibility of instantiate an object from a class defined previously, place it in the hierarchy, make it decomposable, change its attributes and its aspect. To illustrate this, the result of the construction of a bus is shown by Figure 26. When the user double click on a decomposed component, the view of the "inside" of the object is shown, with all the objects composing it. For the bus, we can see its inside with the seats. The attributes of each component can be consulted or modified just by selecting the object and activating a tool called "Inspector", similar to the tools found in software like Delphi, C++ Builder, Access... This tool gives a full access to the attributes of an object as well as its visual representation.
The components created as templates can be used in different contexts. First of all, they can be used during the simulation to create a dynamic object without programming the complete construction of the architecture of the object. Then, the templates can be used during the design time, due to another tool, the palette. More details about the construction of a graphical representation of a component can be found in [Balci 98a], which presents a taxonomy of techniques for this purpose.
VSE allows the building of a model as well as the design of a library of components. A library is a set of classes and templates of components that the designer can use for the building of different models. He just has to specify that he wants to use a given library in his model and the classes of this library are added in the graph of inheritance of his model. Then, he can instantiate directly objects from them or extend the property of a class by specializing it. In a same way, the templates of the library are added to the list of the templates available in the model.
There are two different ways of using a template. The first is during the simulation. A specific instruction can be performed to make a copy of a template and introduce the new object in the model. Usually, the dynamic objects are created by this way instead of creating the object and initializing each attribute, defining its hierarchy... The other way of using a template is through the "palette". It is a window in which all the templates available in the model are shown. The user can select one, drag it and drop it in the component hierarchy window or in the template window and then, use it as every other object created in the model.
Figure 27 shows the palette for our example model. The templates of a bus and a passenger are available. If we consider only the buses, the user has two possibilities to create them in the model. First, he can drag and drop the template in the static hierarchy at the design time. The current position of each bus will be its position at the start of the simulation. The user can also choose to create them at the run time, during the simulation, by invoking the method cloneTemplateNamed: of the class VSModel with the name of the template as argument. To conclude, the palette is an interface for the reuse of components from a library.
In a simulation model, there are parts of the data that are variable and others that are constant. The constant data is parameters of the model. With VSE the parameters also called "input data", can be simple information as a number, but can also be a complex object belonging to a class defined in the model, like a random variable. The user has to define all these parameters, different sets of values can be defined for them. Each set of values corresponding to a specific environment of an experiment. By this way, the user can prepare the set of experiments he wants to perform (see Figure 28).
Before starting the simulation, the user must define precisely the context of the experiment. In this aim, the following parameters must be specified.
During the simulation, each object of the model having a visual representation is automatically displayed. The user can select different views of the system by selecting an object, go inside it and by this way, go progressively down in the hierarchy of components. The speedup, the slowdown and the pause of the animation are possible to allow the analysis of the state of the model. The inspector tool defined previously is also available and allows the user to see the attributes of each object of the model. The combination of the animation and the inspector is a powerful way to verify a model. It is also a good way to present the simulation to other people, especially to the experts of the system usually non specialists in simulation, who can understand more easily the achieved work and its validity. When the user is confident in his model, he can disable the animation to collect data faster. Results are usually collected in files that are then analyzed by the VSE output analyzer.
In software like VSE that allows developing complex simulation models, tools must be provided to give the user the possibility of verifying its model and having the maximum of information when an error occurs, in order to be more efficient during the design of the model ([Balci 97e]). The first aids for the debugging are the animation of the simulation and the possibility at any moment of consulting the state of an object through the inspector. Moreover, VSE proposes two complementary tools. The first is the tracing of the message passing and the other one is the verification of assertions. The tracing consists in informing the user of each call to a method of an object, specifying also the references of the caller and the receiver of the message. That allows knowing exactly what happens in the model and when an error occurs, VSE is able to find the method where the error occurred, the object using this method and the object that invoked this method. It is a powerful tool that allows gaining time in the debugging. The other concept is the assertion. In the logic of the methods, some assertions can be established. So, the user defines explicitly these assertions. An assertion must always be true. If during the execution, an assertion is false, the simulation stops and the failure is signaled to the user who knows exactly, due to the tracing, where the assertion has failed. The verification of the assertions is normally used during the design and the verification of the model. When the user is confident in his model, he can decide to deactivate the verification of the assertions to gain computing time.
As we saw previously, data is collected during the simulation and stored in files. To be usable by the VSE Output analyzer, each kind of data must be stored in a separate file. For instance, a file contains a set of realizations of a specific random variable. The VSE output analyzer is then able to compute some statistical results as shown in Figure 29 for each set of values.
VSE is a general-purpose simulation environment, which means it has not been developed for a specific kind of problem. But a standard library is provided for the basic operations of the simulator. We will introduce now this library and present the main classes in order to understand the possibilities of VSE and how a model can be built with this software. Figure 30 presents a part of the inheritance graph of the standard library. All the classes the user creates must inherit from one of the standard classes.
As shown by Figure 30, the most generalized class is VSObject. Every object in the model belongs to this class, directly or indirectly by the way of inheritance. Hence, all the objects have the properties we present now.
First of all, this class provides standard methods we can find in most of the object-oriented languages. There are new that allows the creation of an object of the class and initialize used to initialize a new object. This is the equivalent of the constructor in some languages.
VSE has the particularity of considering a class as an object. That means a class is used as any object in the model, it has attributes and methods. The only difference is that a class is the only object of its kind in the model. Hence, with VSE it is possible to ask an object about its class. The method class returns an object that is the class of the object. Then information can be asked to this class about the possibility of the object through the following methods: superclass, inheritFromClass:, name, description, instancesRespondToMessageNamed:... They give information about the position of the class in the hierarchy of inheritance, about its name and its description, about the methods available for its instances...
The methods defined previously allow a lot of possibilities, one of them is the dynamic binding. This means the class of the objects managed in a method can be totally unknown at the compilation time. During the simulation, the object will be asked about its class, its possibilities and dynamically, choices will be made to use the object according to its class.
But to perform that, VSE must provide a way to specify that an object is completely unknown. For this purpose, a reserved word is used to qualify such an object: object. The difference between an object defined as belonging to the VSObject class and an unknown object is that the last one has an unlimited and unknown number of methods. This object can potentially perform every method of every class. Of course, if during the simulation, it appears that the object has not this method, an error will occur. Hence, the user must be careful with the use of unknown objects, and use the class methods of an unknown object to get information about it. Unlike the unknown object, an object of the VSObject class can only use the methods of this class, even if it belongs to a subclass of it. In fact, VSE forbids the down cast of the objects, this means an object defined as VSObject can not be converted to an object of a subclass even if the user is sure the object belongs to this subclass. The only way to do this is using the keyword object. With it, every conversion is possible.
Until now, we saw that it is possible to define classes with VSE, and use them to build a model, by organizing objects that will communicate together. But a point has not been clarified. How the simulation begins ? What is the first thing the objects in the model do to make the model dynamic ? For this, the simulator automatically invokes methods at the beginning of the simulation. In a same way, methods are also called at the end of the simulation, in order to allow the saving of the results.
Two different kinds of event are considered. The first notifies the beginning and the end of the simulation, i.e. an experiment, whereas the other is just about a replication. Usually an experiment is composed of several replications. At the beginning of an experiment, a message experimentStarted is sent to each class. Then, for each replication, the method replicationStarted of each class is invoked. By the same way, the methods replicationEnded and experimentEnded are called.
Not only the classes receive these messages. We will see further that some kind of object, i.e. belonging to a specific class, can receive also these messages. But, in the context of a general object like a VSObject class instance, we can only say that the object usually does not receive the messages.
Every object does not receive the notification messages about the simulation, but all of them receive a specific message when they are created by cloning. The method wasCloned is automatically called after the duplication of the object. It is used to make an initialization of the object that can not be done directly by the template. For instance, the registration of the object to another one to signal it wants to receive particular services from it.
How to define the logic of methods like wasCloned, experimentStarted... ? In fact, these methods have a default logic provided by the superclass that introduces first the methods. The user will create its own classes that inherit from such classes. He will have then the possibility of redefining or completing the logic of these methods in his own classes according to his goal. It is called "overriding".
VSE considers a model as an object of the class VSModel. The user is able to subclass it to give particular properties to the model, usually some attributes that can be considered as global variables for the whole model. A unique global object VSEModel is automatically created by the simulator and represents the instance of the model. Of course, this object is accessible from anywhere.
The model has methods to access its fundamental elements. Among them, there is the first component of the static hierarchy, also called the top-level component. Then, there is the clock, which is a rational number representing the time during the simulation. And finally there are the templates of objects. All these objects are accessible through methods like topLevelComponent, clock, cloneTemplateNamed:...
The model also provides information about the simulation. They are usually used to compute results. Some of the information is the number of completed replications (method numberOfReplications), the number of objects passed through the model (method dynObjDestroyed)...
As all the classes of the model receive automatically some messages notifying the start or the end of the simulation, the object VSEModel receives messages having the same name. See further for more information about the order in which these messages are sent to each class or object.
This class represents the objects that are visible in the animation of the simulation. They are called shapes. For this purpose, the class provides a set of methods to define the representation of an object. We will see further that these objects are used to move dynamic objects from a point to another, they are used as geographical references.
A set of methods is provided to define the representation of an object. It is possible to associate directly an image with an object through the method setImage:. For this purpose, the class VSImage represents image objects. Then, there are methods to define the color, the size and the position of a shape in a layout of a component with the methods setX: Y:, setFillColorRed: green: blue:... A layout is the inside representation of a component. Another attribute of a shape is the rotation angle. In fact, a shape can be a dynamic object as we will see further. When a dynamic object moves, it can be interesting for the visual representation to rotate the image of the object in the direction of the movement of the object.
This class represents a path between two shapes. In fact, VSE offers the possibility of moving a dynamic object from a shape to another. Without a path, the dynamic object follows a straight line to move from an object to another. If a path links two shapes, the dynamic object will follow this path. Moreover, it is possible to specify that the dynamic object rotates automatically to follow exactly the curve of the path, which makes the movement more realistic (method setAutoRotated:). A shape also has methods to know the paths incoming or outgoing from it. It is also able to know the next destination of a dynamic object, or the previous location if there is just one incoming or outgoing path.
All these methods are only for the visual animation of the simulation. These methods could seem useless because of the computing time they request. But, remember that the animation can be disabled, so the time problem can be avoided. Moreover, for a presentation to other people, the animation can be a powerful tool, especially for the validation of the model by the experts of the real system. Hence, a full set of methods for the animation must be provided. Of course, good visual representation needs time during the design of the model, but this time is regain later during the validation, the verification and the presentation of the results.
All the shapes of the model receive automatically messages concerning the start and the end of the simulation. You must notice that in the hierarchy, a parent component receives a message only after or before all its children receive the same message. The following presents briefly the order of the messages. Here is the order in which the message experimentStarted is sent.
The replicationStarted message is sent in the same order, but after the message experimentStarted has been sent. The order of the messages replicationEnded is:
The experimentEnded is sent in the same order, but after the message replicationEnded. Between classes, no special order is defined.
The classes VSComponent and VSDynamicObject are the most important classes of VSE, because they characterize the specificity of the simulator and the way a system must be modeled. These classes have to manage the movements of objects in the model and all the interactions that they induce. We will see that the simulator automatically sends a lot of messages. The user will have to choose which ones to use to capture the events that interest him. First of all, we will see some methods specific to the VSComponent and VSDynamicObject classes. Then, we will present the mechanism the simulator performs when a dynamic object moves in a component.
First of all, a component is a shape that supports the movement of dynamic objects in it. When a component is shallow, this means the component is not decomposed (it is opposed to a deep component), there is no difference with a shape, except the component can be engaged in an activity. This means the time factor can be introduced in the behavior of the component, unlike a shape. But since the component is decomposed, a lot of information is available about the dynamic objects in it. First of all, the number of dynamic objects in the component, directly the level below or in the whole hierarchy below the component can be known through methods like numberOfDynObjsInLayout or numberOfDynObjs. Then, the component can access the dynamic objects directly in its layout by methods like dynamicObjects, which provides the list of the objects or oldestDynObj, which returns only the oldest dynamic object entered in the component.
To allow dynamic objects to go into it, a component must have at least an entrance, an object belonging to the VSEntrance class. It is a shape as we can see in Figure 30. In the same way, to allow a component to leave the component and go into the upper component in the hierarchy, at least an exit must be placed in the component. Different kinds of component or shape can also be placed in the layout of the component. The component is able to access each of its child components through methods like shapeNamed:, componentNamed:, pathNamed:, entranceNamed:, exitNamed:... The component has also access to its parent component, the component just upper it in the hierarchy. The method is naturally called parent.
As we said briefly, a component has the possibility to be engaged in an activity. This means the component has the possibility of waiting a given duration. A component can only be engaged in one activity at a time. Two messages are automatically sent at the beginning (by the method startedEngagement:) and at the end of an activity (by the method stoppedEngagement:). Different kinds of activity are distinguished by giving a number to the activity an object engages in.
When a new component is created during the simulation, it is not automatically introduced in the model. The user must specify this action by methods like enterModelIn: AtX: Y: afterTime:.
The last particularity of a component is that it can be destroyed explicitly when it becomes useless. It is a way to move an object out of the model. The other solution is to have an exit in the layout of the top-level component, the highest component of the static hierarchy and tell a dynamic object to move to this exit. In this case, the object is automatically destroyed.
Of course, there are a lot of methods automatically sent to notify the movement of a dynamic object in a component, but before describing them and to understand better their role, we will see the particularity of a dynamic object.
A dynamic object is a component as we can see in Figure 30. But some new particularities are added due to the fact that a dynamic object can move, unlike any single component. Hence methods to move are provided. We just enumerate them here, because the names are explicit enough to understand what they do. The only remark is that the destination of the movement is always a shape that can also be a shallow or a deep component. In the case of a deep component, the dynamic object goes inside the component and by the same way, go down in the hierarchy. The destination shape of the movement of a dynamic object can also be an exit, in this case the object leaves the component and go up in the hierarchy, into the parent component. Some of the movement methods are moveTo: takingTime:, moveTo: usingPath: takingTime:, moveTo: throughEntrance:... All the variants of these examples are provided. The last enumerated method is used when an object moves to a deep component having several entrances. In this case, the entrance the object will use has to be specified.
A dynamic object can access some information about its location, its next destination (if there is no ambiguity with the paths) or its previous location. For this purpose, methods like component, previousComponent, nextComponent... are provided.
As a single component, a dynamic object, when it is created during the simulation, does not enter automatically into the model. Specific methods like enterModelAt: afterTime: must be used. The only difference with a single component is that there is no need to give coordinates to place the object in the model. The user just has to indicate the shape he wants the object to move to.
After we defined separately the particularities of a component and a dynamic object, let us see now how both of them interact. There are different cases of movement for a dynamic object in a component. First of all, we can separate them according to the fact that the dynamic object moves in a deep component or on a shallow one. The first case is illustrated by Figure 31. Figure 32 represents the other one. Both of them show the messages automatically sent by the simulator.
Let us consider the case of a dynamic object arriving on a shallow component. When it is arrived, the message movedToComponent: is sent to the arrived object and the message dynObjArrived: is sent to the component the object has just arrived on. In a same way, when the object is departed from the component, the message movedFromComponent: is sent to the dynamic object and then, the message dynObjDeparted: is sent to the component the object has just left. Although there is an order in the passing of the messages, this happens without changing the time of the simulation. In other words, from the point of view of the simulation time, the two events appear at the same time.
We will see now the case of a deep component. The situation is a bit more complex because another object is involved in the process. It is the parent component of the deep component. In the case a dynamic object arrives in the deep component, that means it was in the parent component and descends in the deep component. For this reason, a first message descendedFromComponent: is sent to the dynamic object. Then, dynObjDescended: is sent to the parent component. Finally, messages similar to the case of a shallow component are sent. arrivedAtComponent: is sent to the arrived dynamic object and dynObjArrived: is called for the deep component the dynamic object has just arrived in. In a same way, when the dynamic object leaves the deep component and ascends to the parent component, the first message departedFromComponent: is sent to the dynamic object. Then, dynObjDeparted: of the deep component the object has just left is called, and then, the dynamic object receives another message ascendedToComponent:. Finally, the parent component is informed of the ascension by the message dynObjAscended:.
The user must choose between all these methods which ones he wants to use. There is no general rule concerning the choice of a method. It depends on the situation. In complex cases, almost all of these methods are used, whereas in single cases, just one or two methods are enough to specify the wanted mechanism.
We briefly discuss about the class VSStream, which provides output or input streams of data. The main streams are the files and the random variables. So VSE provides classes for input and output files, the VSFileInputStream and the VSFileOutputStream classes. Input files are usually used to get data that we can compare to the input data, the parameters of the model. It is just another way, sometimes easier to initialize the parameters, especially when there is a lot of information. Then, the output files are usually used for the storage of the results of the simulation. Finally, lots of well-known random variables are defined in the standard library, through subclasses of VSRandomVariateInputStream. There are continuous ones as well as discrete ones.
Objects can be grouped in a collection represented by the VSContainer metaclass (see Figure 30). Objects in a container can be accessed sequentially. For that, we must ask a container to give us an iterator, belonging to the VSIterator class. The iterator will point sequentially to each object of the collection, in a given order.
It is also possible to access directly an object. This possibility depends on the kind of container. Two kinds are provided by the standard VSE library: the lists (VSList class) and the dictionaries (VSDictionary class). With a list, it is possible to manipulate the objects of a collection due to a number representing their position in the list. With a dictionary, an object is associated with a key, i.e. a string of characters, belonging to the VSString class.
In this chapter, we saw how the concepts of the object-oriented paradigm and component-based software engineering have been implemented with VSE. Now, we will present the study we carried out and explain how the design of libraries of reusable components with VSE has allowed the achievement of reusability in the modeling of various systems.