5 CASE tools for object-oriented analysis and design

 

5.1 General presentation

The appearance of the analysis and design methods presented in the previous chapter is one of the solutions offered, the one referring to the methodological framework. After 1985, a significant part of research carried out was concentrated towards the automation of the software "production" process. In this framework, tools that can support, (partly or entirely), the construction stages of any medium or large sized system (specification, analysis, design, implementation, testing, use and maintenance), known under the generic term "CASE tools", have been designed and built.

CASE tools were built around a repository that memorizes the information used in the analysis, design and code generation stages.

Definition 5.1.1

Repository - A complex data structure, allowing an efficient storage of the information characterized by a great number of semantic links. The repository's architecture is object-oriented. Consistency preservation and the possibility to obtain information quickly through a natural and simple way is a basic requirement for any repository.

Considering the support given to the object-oriented paradigm, CASE tools can be classified in:

In the following we will deal exclusively with object-oriented CASE tools. The object-oriented technology and the CASE tools complete each other happily. Object-orientation is not only an analysis, design or programming tool - it is a manner of thinking. The purpose of the OO CASE tools is to help system designers, end users or decision factors to visualize the system by the agency of constructed models. Using CASE tools allows quick building of systems with robust, checked structures, easy to change and maintain.

 

5.1.1 Classification criteria for object-oriented CASE tools

From our point of view, in order to classify the OO CASE tools, we have to analyze at least the following features:

5.2 ROCASE's position relative to the classification criteria

The tool specified, designed and implemented by us:

 

5.3 ROCASE Architecture

The tool is splitted in modules, each having a well defined main functionality. The central element of this architecture is the repository. A great part of this chapter is reserved to describing the ROCASE architecture and functionality. As you can see from figure 5.1., practically all the tool's components exchange information with the repository one way or another. In the module design and implementation we have intended to achieve a maximal independence. Thus, the reverse-engineering module, called Phoenix, is practically entirely independent from ROCASE. The only link with the tool is made for exchanging the information obtained in the code analysis process. The diagram editor and the text editor have, in their turn, a high degree of independence. The same goes for the syntactical component of the OCL analyzer. Obviously, the semantic component is dependent on the repository's architecture. The code generator and the ROCASE browser are in the same situation.

 

Figure 5.1 - ROCASE - General architecture

5.4 Analysis and design of the ROCASE repository metamodel

The ROCASE repository metamodel:

The grouping of the modeled entities in subsystems is different in ROCASE from UML. ROCASE subsystems are: Types architecture, Project Management (Module diagrams), Classes and relationships (Class diagrams), States and transitions (State transition diagrams), Objects, bindings and messages (Object diagrams). Less detailed compared to UML, this division takes into consideration the use of entities in diagrams. The "basic module and composed module" concepts described in the Module diagrams subsystem support a project management which, in our case is more rigorous than in UML. Another fundamental feature that distinguishes the ROCASE repository metamodel from the UML metamodel is the formal annotation support, materialized in the possibility of declaring: invariants (at the classes and states level), preconditions and postconditions at the methods and events level. From this point of view, the tool also satisfies the Syntropy Method, proposed by S. Cook and J. Daniels [Cook94].

The type system is similar to those implemented in strongly typed object-oriented languages (Eiffel, C++, Ada, etc.). It considers that a class determines a type. A particular attention was given to generic classes modeling ("templates" in C++ terminology). This concern was materialized in modeling the concept of "generic derivation" (instancing template classes) and in the implementation of a semantic checking system. Initially, the solution adopted was closely linked to the genericity implementation in Eiffel, the most complete object-oriented programming languages known to us. The difference from the Eiffel type system consists in the fact that standard types (predefined), called in the ROCASE metamodel RCSBasedTypes, cannot be inherited. Thus, we achieved the necessary concordance with the implementation language type system, in which we generate code at present - C++.

Figure 5.2 - Architecture of ROCASE metamodel subsystems

 

5.4.1 Architecture in ROCASE

Figure 5.3 -- Architecture of ROCASE type system

The repository's architecture sets the upper level of the type hierarchy, RCSType but leaves open the lower level to be extended depending on the specific features of the object-oriented programming language in which the application code will be generated. In ROCASE, type architecture is flexible as it captures both existing relationships in strongly typed languages (C++, Eiffel, Ada) and those in untyped languages (Smalltalk, etc.).

The direct descendents of the abstract class RCSType are grouped in two basic categories. On the one hand, inheritable types, represented by the abstract class RCSInheritableType (and its descendents) and on the other hand, uninheritable types, modeled with the help of the RCSStandardTypes classes (and of its descendants RCSEnumeratedType, RCSSubdomainType) and RCSDummyType created for modeling formal generic parameters. Another distinctive feature for the two categories, as they have been modeled, is the fact that while inheritable classes can be abstract, all the classes from the second category, RCSStandardTypes, are concrete. In the case of the RCSInheritableType classes, this information is stored in the boolean attribute m_abstract.

Modeling generic RCSTemplateClass classes led to the apparition of two other classes: RCSDummyType and RCSInstantiatedClass. RCSInstantiatedClass models classes obtained by instancing at least one formal parameter of a generic or incompletely instanced class. Instanciation can be partial or total. Only completely instanced classes can have objects.

 

5.4.2 Architecture of module diagram entities

The project is made up of one or more composed modules, instances of the RCSComposedModule class (which, in their turn, can contain other composed modules or based modules instances of the class RCSBasedModule). Each instance of RCSClass is defined in only one based module, but it can be used in different based modules if the class' and module's visibiliy is interface. In ROCASE, the concept of module is equivalent to that of UML subsystem. The module's functionality must be, as much as possible, independent from the other modules functionality. Use relationships can exist between modules.

In ROCASE the module's role is double. It favors the increase of the project's intelligibility and imposes a discipline in the classes' management. ROCASE, through the feature called visibility, fills in the lack of the package concept in OOLs other than Java and Ada. As modeled in ROCASE, the module can also be used for managing design patterns.

Figure 5.4 Architecture of the "subsystem's" project management entities

The use relationship between two modules can be explicitly specified by the designer or automatically detected by the tool and rendered at module diagram level after the materialization of a client-server type relationship between two entities belonging to different basic modules. A special use relationship refers to the modules called BasicTypes and CollectionTypes. They are at the user's disposition from the beginning of a new project. The BasicTypes modules contain "based types" if the user declares attributes', methods' and parameters' type. The CollectionTypes instances are used if the module contains multiple associations, implemented in ROCASE by the Collection classes specified in OCL, or if the module contains generic Collection classes or classes instanced from them.

Further on, the thesis presents the subsystems' architectures:

and explains the solutions adopted for modeling.

5.5 Performing semantic checking in the CASE tools

Keeping the project's semantic consistency eventually leads to the reduction of an important part of compilation and/or execution errors, depending on the type of the language used. Moreover, checking is important in application's incremental development - removing of some system components should lead to automatic exclusion of all entities dependent on those eliminated or updating the references towards the eliminated entity. Lack of checking can lead to unpleasant situations, having as consequence the impossibility of using the model built.

There are two possible approaches with regard to the checking time:

Each of these two approaches presents advantages and disadvantages:

Implicit checking has the advantage of being distributed in time, therefore avoiding a long checking operation. Besides, this approach does not allow the designer to introduce errors that could propagate afterwards in such a way that after their detection it would be too late to correct them easily. On the other hand, it has a disadvantage: the lack of flexibility - sometimes, imposed restrictions can become annoying. The reason that determined us to impose this rigor was the desire to stop as much as possible the introduction of a chain of errors difficult to detect later. On the other hand, this type of approach increases the tools' teaching qualities. Moreover the chosen variant greatly simplifies operations that must be carried out in the event of a global checking.

Explicit checking is executed when it is desired to use the project for a certain purpose like: code generation, state chart diagram architecture validation, etc. Such checking has the advantage that error detection is not blocking. The main disadvantage of this approach is the time necessary for correction, greatly influenced by the side effects leading to the domino phenomenon of errors propagation.

 

5.5.1 ROCASE approach -general presentation

The approach adopted in ROCASE is mixed: both implicit and explicit checks are performed. Implicit checks allow the user a certain flexibility absolutely necessary in case some late decisions must be made. The designer can assign entities the "pseudotype" Undefined and postpone the type declaration until just before automatic code generation or even after, if there are good reasons for this decision.

Operations that can be carried out on the ROCASE metamodel are: adding, deleting, modifying (updating) entity properties. Adding and deleting RCSDiagramEntity descendents is carried out exclusively by the graphical editor. Operations referring to textual annotations are carried out with the help of dialog boxes.

Implicit checks - carried out when adding an entity, do not allow the user to execute operations that may lead to conflicts or inconsistencies in the system. For example, we present a few operations that are realized when adding an entity:

 

5.5.2 Checks performed when adding entities to the model

In this paragraph we will refer to the checks performed when adding entities to the model through its interface.

5.5.2.1 Adding a use relationship between modules (RCSModuleUse)

Figure 5.5 - Use relationships between two basic modules

For a correct representation and the complete use of information concerning this relationship, we must specify that it can have two different meanings. If the user adds such a relationship in the analysis phase, this means that permission is granted to the client module's entities to use the server module's entities. Normally, this permission is materialized when a client module entity calls on the services of a entity of the server module. After materialization, the line style used for rendering changes. The solution we have chosen offers another advantage too. If the user declares a utilization relationship that will not be materialized, he can be warned after performing a checking. In the situation when between two modules a use relationship has not been declared, but the user declares a client-server relationship between two entities defined in different based modules, the tool automatically creates the use module relationship, introduces it in the metamodel and shows it on the diagram.

Information referring to an entity visibility is stored into an enumeration type attribute. In UML, the enumeration type instance, the same for all the model's entities, is called VisibilityKind and has 4 values {public, protected, private, implementation}. In ROCASE, we have considered sufficient that modules and classes have only two values {interface, implementation}, that allows representing all situations.

5.5.2.2 Declaring an entity's type

Is one of the most important decisions taken when designing a system and later when transforming the design model into the code written in a typed programming language. In order to take advantage of the project management mechanism implemented with the help of the module concept and of the visibility property existent both at module and class level, the type that can be assigned to a project entity must satisfy visibility constraints. The tool implemented by us provides effective support to the designer, placing at his disposition the set of visible types in each module.

In ROCASE, a type can only be declared at the level of a RCSBasedModule. Because of this, we are interested in the set of visible types in such a module, that we will call viz(Mp)'. Due to the role they can play, elements of visible type sets are also known as potential server types.

We will present the way this set can be calculated in two steps.

In the first, we will not take into consideration generic types. Then the set of visible types in the module Mp will be made up of the conjunction of the type set defined in this module with the type set imported in Mp.

viz(Mp)' = {Tp | Tp.definedIn == Mp} È {Tq | Tq Ì imp(Mp)}

The set of types imported in a module Mp satisfies the following definition:

Definition 5.5.2.2.1

Let: Mp, Mq, Mr be three modules of a system having the following signification:

that satisfy the following relationships:

  1. Mp.isKindOf(RCSBasedModule) == true,
  2. Mq.isKindOf(RCSBasedModule) == true, Mq ¹ Mp,
  3. Mq Í Mr Ì MainModule - Mr Í Mp.containedIn (if Mp and Mq have a common parent different from MainModule, Mn is "the smallest common parent", or any parent of Mq, in any other case),
  4. Mq.vizibilityKind == interface, and Mn.vizibilityKind == interface

Then, the set of types imported in the module Mp noted imp(Mp), is given by the reunion of the set of types with visibility interface, declared in the basic module Mq.

imp(Mp) = È {Tq | Tq.definedIn==Mq and Tq.vizibilityKind==interface }

Figure 5.6 - Imported types defined in a basic module Mq. Mp and Mq have a common parent module, different from MainModule - Mn. (The visibility of Mn and of the modules in which it is contained does not matter)

Figure 5.7 Imported types defined in a basic module Mq. Mp and Mq do not have a common parent module, different from MainModule. The visibility of all modules in which Mq is included must be interface.

In a basic module, are imported all the types with visibility value interface, declared in the basic modules other than the one in which the import is performed, on condition that the visibility of these basic modules and of those composed in which they are included (up to the nested level of the module that is "the smallest common parent" for Mp and Mq), is interface.

 

Taking into consideration generic types

In the first step, we have considered that all generic types are part of the potential server types of each module entity, which is correct only in the situation when the type is implemented through a generic class RCSTemplateClass. In the case when we deal with a type implemented through RCSSimpleClass or through RCSInstantiatedClass (irrespective of whether it is partial or total instantiation), dummy types, generic types and part of the partially instantiated types must be eliminated. We call the types that must be eliminated types introducing dummy dependencies. We will have to compute, for each type T, the set of dummy dependencies, given by:

 

 

Definition 5.5.2.3.1

The set of dummy dependencies of a type T noted dep(T), is given by:

Example:

dep(Set[INTEGER]) = Æ

dep(Set[Sequence[T]]) = {T}

dep(Set[Bag[HASH_TABLE[T,Integer]],G]) = {T, G}

Definition 5.5.2.3.2

The set of potential server types of a Tp type (descendent of RCSInheritableType) defined in the basic module Mp, is given by the equation:

pser(Tp)=viz(Mp)'\{Tp'Ì viz(Mp)'|(dep(Tp')¹ Æ )and(dep(Tp')\dep(Tp)¹ Æ )}

In other words, the set of potential server types of a Tp type is obtained by eliminating from the visible type sets at the Mp module level of the types whose set of dummy dependencies is different from the set of dummy dependencies for Tp.

Example:

Let the type Class1<G> be defined in the module M. If viz(M)' = {T1,..., Tn, Class2<G, H>, Class2<G, Char>, Class2<Integer, H>, Class3<H>, Class3<F, G>, F, G, H}, where T1,..., Tn are implemented through simple classes. Then:

pser(Class1<G>)= {T1,..., Tn, Class2<G, Char>, G } - for simplicity we have ignored predefined types and those defined in the classes Collection.

A similar constraint exists in the Eiffel language, to which we have decided to relate considering it the most representative language for the implementing manner of object-oriented concepts.

We will now present a few examples in which the set of pser(T) types is used for checks performed in ROCASE

Figure 5. 8 Inheritance relationships allowed between classes with different dummy dependencies

Regarding the relationships presented above we must point out that reverse relationships, in which, for example, Class_1<G> would inherit from Class_2<G,H> or Class_3 would inherit from Class_4<G>, are not allowed. There are still client server relationships in the case when in Class_2<G,H> we would have a declaration of the form: "Class_1<G> a". For the same reasons presented above, in Class_3 we cannot have declarations of the form: "Class_4<G>" a; or "G a". All these situations are discovered and forbidden in the semantic checks implicitly performed by ROCASE.

Taking into account the fact that any new ROCASE project must be able to use basic (standard) types and Collection types defined in OCL and used in UML for specifying multiple associations, we have decided that in any project, basic types be implemented in a basic module, named BasicTypes, and the Collection types in another basic module named CollectionTypes. These basic modules have visibility interface and are defined at project level, that is:

BasicTypes.containedIn == MainModule,

CollectionTypes.containedIn == MainModule

The instances of the enumeration and subdomain types, can be defined at the level of each module. If it is desired that some of them be global, to allow their referral from anywhere in the system, they can be defined in MainModule.

 

5.5.3 Checks performed when deleting entities from the system - through the graphical editor

While previous checks support the designer in building a semantically correct system, the role of the checks performed when deleting entities are to ensure preserving system consistency.

A first criterion to be taken into account is that if the entities that are to be deleted from the system are used as servers in other locations, different from the one in which the deletion is to be performed, the user must be warned.

Example:

Let A be a type defined in the basic module M1. Suppose that besides the relationships in which it is involved as server, relationship declared in the class diagram where the modification is carried out (for example: class B inherits from class A, or in the class B we have an attribute declaration of the form A a1; etc), in another module of the project - Mi, we have another similar relationship in which A is server.

In this case, the effect of deleting A will reflect in all the modules in which it is used as server. To offer additional flexibility in the deletion operations category, ROCASE allows the user to change the module in which a class was defined with another module in which the respective class is used. This operation is called Main set. In this case, it is possible to carry out the operation of deleting the class in the module in which the entity was initially defined, its effects being limited only to the graphically represented entities, directly bound with the deleted class.

Figure 5.9 Applying operation "Main set" to the TutorialCom class

5.5.4 Checks performed when deleting entities through dialog boxes

This case refers to deleting attributes, methods, parameters or generic arguments declared in some classes. If the respective attributes or methods are used in formal annotations (class or state invariants, assertions referring to methods), events in state transition diagrams or messages in object diagrams, their deletion involves updating the contexts in which deleted elements are used as servers, either by deleting them, or by replacing them with Undefined. The general rule is respected in this case too, in the sense that when deleting a server is desired, the user is informed about its current clients, in order to take the correct decision.

Figure 5.10 - Deleting graphically unrepresented entities, with the help of dialog boxes

5.5.4.1 Checks performed when deleting generic parameters

Deleting generic parameters can cause some problems when at least one of the parameters that are to be deleted are used as server for declaring the attributes, methods or parameters' type. In these cases, the user must be informed in order to take decisions that would avoid such situations. The checking operation involves determining the respective entity's list of clients, displaying the list and warning the user - if the list is not empty.

5.5.5 Checks performed when modifying entities

All the modifications that can be executed in ROCASE are carried out trough the GUI, or more precisely by dialog boxes. The graphical diagrams editor allows only operations of introducing or deleting components. After carrying out such checks, the tool can automatically update information regarding the modified server in all its clients or forbid performing any modifications (in the event that these should introduce inconsistencies) and to present the user the list of clients of the entity that is to be modified. This way, the user can take the needed decisions so that the modification that are to be carried out on the server be possible.

In most cases, the checks performed depend on the entity on which modifications are to be done. Because of this, the modifications of each entity will be presented separately.

In the thesis, the situations that may arise are presented as well as the solutions for solving them when modifying:

5.5.6 Checks performed in object diagrams

Like in the case of the other kind of diagrams, the most consistent checks that can be effectuated refer to the design stage. Most of them are referring to keeping concordance between information in existing class diagrams and the information in object diagrams. Types that can be assigned to objects in an object diagram are part of the visible and instantiable type set at module level for which the respective diagram is built. Links between objects must be instances of the class diagram associations, for which compliance with the multiplicity order is verified. Messages sent are selected from those available in the receiver's interface. Thus, if methods from the receiver's class are implemented, the tool can automatically render the chain of messages generated after executing a method. If the methods' body will be implemented after the scenario building or if modifications have been carried out in the body of those methods, the object diagram can be automatically updated by the tool. The tool checks the values of the current methods' parameters.

 

5.5.7 Checks performed for the state diagrams

5.5.7.1 Conceptual framework

Building a rigorous framework for performing these checks require:

With regard to the condition previously mentioned, we specify the following:

5.5.7.2 Actions involving keeping concordance between information in the class diagram and in the states transition diagram

Checking state invariants

Checking the syntax of invariants is automatically carried out with the help of the OCL expressions analyzer. A convenient definition of state invariants and of the class invariant should also allow checking the implication invstate Þ invclass. This checking will have to be performed manually, otherwise it would uselessly complicate the analyzer.

Forbidden transitions

It is forbidden to introduce in the diagram:

Name of states, events, transitions and the signature's conformity

To avoid strange situations encountered in other CASE tools, we have decided that each of the above mentioned entities (just like any other entity in the ROCASE metamodel) receives an implicit name. Excepting pseudo-states, the names of the other entities can be changed through the user's explicit intervention. To ensure conformity between events' signature and the signature of the associated method, the explicit name declaration is achieved:

  1. when introducing the transition, by choosing a name from the list of modules included in the class protocol,
  2. later, to verify if all transitions have an associated message.

Checking performed before code generation is intended to eliminate inconsistencies that can appear due to the use of inexistent methods in the protocol of a class.

ROCASE also checks:

5.5.7.3 Checking depending exclusively on the architecture of the states transition diagram

These checks are performed in most cases after the complete description of the states machine or before code generation. They involve building two types of matrices.

Building this matrix invites to finding some answers to the following questions:

  1. regarding states:
    1. When the system is in a certain state, are there other events (except those mentioned in the matrix), that can have a significant effect in the respective state?
    2. Are there additional states (noticeable or internal) except the ones mentioned?

  2. regarding events:
    1. Is it true that the only states in which a certain event has an effect on the system are those indicated in the matrix ?
    2. Are there events that can influence the class behavior that are not mentioned on the diagram ?

The previously described matrices are built for transition diagrams of flattened states (in which all states are on the same level). In addition to this, checks can be carried out referring to the architecture of the states' transition diagrams before their flattening.

For this purpose in the thesis were stated and demonstrated the following lemmas:

Lemma 5.5.7.3.1

If the states machine associated to an instantiable (concrete) class does not have at least one entry state from which starts a transition towards a simple state, then that machine is incomplete.

Lemma 5.5.7.3.2

Let a states machines contain at least one composed state in which at the first level, entry states are not included (not associated to a constructor) or history states, or contain an entry state (not associated to a constructor) from which there is no path towards a simple state. If towards the composed state there is at least one transition and if there is no transition starting from the exterior of the composed state towards a simple state included, the machine is incomplete or redundant.

Further on in the thesis, are presented the algorithm for flattening a state, described with the help of the Harel formalism, and the algorithm used for determining unreachable and trap states.

 

5.5.7 Conclusions

Defining and implementing a consistent check set has a crucial importance for a CASE tool. Ideally all checks would be performed automatically. For the time being, this is impossible. The current situation has several causes. The most important are the lack of a formal framework which would include information for all checks, the complexity and even the impossibility of performing checks even in the event when all the required information were available. However, signaling all "delicate" situations for which the designer has to take decisions is of great help. The checks mentioned and implemented in our tool offer a framework in which systems can be more rigorously implemented than when using other existing tools.

 

5.6 The OCL analyzer

Is an important component of our tool. It supports effectively the use of checks because, as we have shown in the previous chapter, OCL is a language used by UML for describing formal textual annotations.

Our tool is conceived in such a way that only syntactically and semantically correct OCL expressions are accepted for inclusion in the repository. Semantic correctness refers to the visibility and to the operands semantics, not of the expression as a whole. Expressions analysis is a two step process, carried out with the help of two analyzers: one syntactical, the other semantic. If the analyzers detect an error, the user is informed about its type so that the necessary corrections can be made.

Figure 5.11 OCL Expression Analysis and the generation of the associated code in ROCASE

Being supporters of programming by contracts, we have decided to extend the OCL use. OCL annotations are translated in C++ code, thus being used for system validation. Therefore, class invariants are transformed in C++ assertions included both in the constructor body and in the function members capable of modifying the state of the object.

 

5.7 Code generation in ROCASE

In most cases, obtaining an executable system fulfilling the requirements imposed by the system users is the final goal of a project. For medium and large sized projects, and in many cases even for small sized projects it is preferable to automatically generate the code. Two important reasons support this conclusion. One is referring to requirements, the other to implementation:

5.7.1 Code generation possibilities

When operating with static models - (represented by classes and module diagrams), code generation is to a great extent declarative (defining classes, types and modules). But it can also include methods' generation body for access functions and other operations: constructors and destructors.

For reactive objects, the methods' body can be generated starting from the states transition diagrams and the main function code, using information provided by the object diagrams. For transformational (non reactive) objects, the code can be generated using the information from activity diagrams. Another option is using information offered by a formal description (presented in the thesis in the m FOOPS Appendix). The options previously mentioned suppose the translation of the modeling information, expressed in a specification language, into source code. In some situations direct coding in the programming language is preferable. This goes especially for simple methods, whose code is expressive enough.

 

5.7.2 The relationship model - generated code

Generating class structure is not a problem, because most object-oriented languages directly implement the class concept. But the module concept is implemented only in a few languages (Java and Ada, where it is called package). Other important concepts: state, association, etc. are not implemented in programming languages. They must be implemented using other concepts or mechanisms supported by languages.

 

5.7.2.1 The structure of the generated code and the management of #include directives

The code generator implemented in ROCASE uses a set of conventions for placing generated code in files. These conventions are consistent with the structure of the model described in ROCASE and with C++ programming usage, being materialized in the following rules:

Figure 5.12 - Automatically generated code for the structure of the Conference class

 

5.7.2.2 Code generation for class structures, attributes and methods declarations

The concepts of class, attribute and method appear both in modeling and programming. Being directly supported by object-oriented programming languages, code generation for these concepts is performed almost directly, taking into account the following rules:

DECLARE_ATTRIBUTE(attributeName, attributeType, get_visibility, set_visibility)

IMPLEMENT_ATTRIBUTE(attributeName, attributeType, className, get_visibility, set_visibility)

 

5.7.2.3 Generating code for associations

In ROCASE associations are unidirectional. Bi-directional associations are formed of two unidirectional associations the modification of which must respect the requirements imposed for consistency, presented in the thesis paragraph 4.7.2.1.

With regard to the model in which they are defined, features of a project's elements can be: logical features, design features, and specific features of the target language. The project's evolution always takes place by adding new features, and not by replacing. Finally, the implementation model will contain logical features, design features and features specific to the target language.

Design information can be modified without changing logical information. Thus a distinction of analysis decision from the design ones can be made, as well as a significant reduction of the risk of accidental changes of requirements during implementation. On the other hand, if analysis information is changed as a result of requirement modifications, the generated code will be automatically updated with these modifications.

In the thesis are presented the user's options concerning the code generated for associations, and the macros used for implementing simple and multiple associations. For implementing multiple associations our implementation of the collection classes specified in OCL is used. In ROCASE, this implementation also serves as reusable components.

5.8 Examples of using the ROCASE to design and implement applications

For any new tool, its usage for designing and implementing applications is one of the most important validation activities. In this activity takes place a first identification of the tool's strong and weak points.

During 1998, the following systems known from literature were realized: "Home Heating System, Problem Reporting System" [Booch91], "Conference Registration" [Walden95] and "Document Filling" [Derr95] as well as a set of examples that demonstrate the possibilities offered by the code generator.

In Appendix C of the thesis are presented the modeling solutions proposed for these systems and the results obtained (materialized in the generated code).

The conclusions obtained after the completion of the above mentioned projects can be thus summarized:

 

5.9 Conclusions

The uninterrupted activity in the OO CASE tools field in the last four years, the results obtained, entitle us to state the following: