Umeå UniversityTo support software design one needs languages to describe the components of the design and their interrelationships in a suitable notation. In addition, tools are needed to simplify the creation, analysis and manipulation of designs. Finally, reusability not only plays an important role in the development of software from pre-existing components, but also in the development of languages and tools for design itself. In language development one searches for notions to describe common aspects only once and to make them (re-) usable in other places. In tool development one implements mechanisms to make available knowledge and experience to different kinds of (re-) users.
Compared to other design languages EMIL has a slightly different notion of module, which builds on the new concept of export components. These export components are the basic elements for the encapsulation of design decisions. An export component contains a cohesive set of resources. Different kinds of export components are provided to support different kinds of abstraction. EMIL modules make available export components on their (export) interface to be used by other modules. This new level of indirection allows for a natural and uniform notion and treatment of modules and subsystems.
Modules and subsystems both provide (lists of) export components in their (export) interfaces. In the case of modules, there apply some restrictions concerning the composition of this list. The real difference between modules and subsystems lies in their implementation. Module implementations are atomic in the sense, that they are realized by single units, which are not further decomposed into modules and subsystems. Subsystems have complex realizations, which are described by separate (sub-) architectures. The unification of the notion for module and subsystem is of great help in the development of large software systems. First, one can abstract from the complex realization of a subsystem. Second, one need not even care about a component being a module or a subsystem before it has to be realized.
EMIL supports non-strict multiple inheritance. Since we distinguish between different modes of parameters for operations, we can support co- and contravariant redefinition in restricting their applicability to the appropriate modes.
The concept of genericity is defined independent from inheritance. This has two advantages compared to solutions connected to inheritance. First, it allows for greater freedom in the definition of formal generic parameters, i. e. they need not necessarily be types. Second, it does not restrict the actual generic parameters to concrete subtypes of the formal ones. The first point enables more generic components to be defined. The second point enables more generic components to be used, since it frees the generic component from name space dependencies and actual type systems. EMIL supports unconstrained as well as constrained genericity.
EMIL is statically and strongly typed. Together with its support for universal polymorphism, in the form of genericity and multiple inheritance, this allows for great flexibility in the definition of the components of software architectures and their interconnections, but still facilitates extensive consistency control.
With its introduction of export components, the unification of the notions of module and subsystem, and its independent definition of genericity and inheritance, EMIL provides support for the definition of reusable components already on the language level.
The second part of the thesis describes the use of EMIL to define adaptable and extendable software architectures. Using a running example we examine the use of inheritance in the literature. We discuss which purposes inheritance is claimed to serve, can serve, and should serve in our opinion. We also discuss under which circumstances genericity should be preferred over inheritance to express commonalities. We therefore point out which problems different usages of inheritance can cause with respect to (sub-) typing and (re-) usability. We discuss typical patterns for subsystems and how such subsystems can be described using EMIL. The integrated design environment for EMIL, its tools, and its user interface are also described.
To support effective retrieval of components, they need to be represented by some kind of formal or informal specification. In feature-oriented classification components are represented by sets of features, called descriptors. Each feature describes a property or an attribute of the component. To support the understanding and construction of descriptors all features are organized in a classification scheme to show their interrelationships. We support different kinds of relationships between features which are used to guide the search through the library.
A similarity metric is defined between features. Using this similarity metric we can compute a similarity measure between descriptors and thus the components represented by the descriptors. With each feature is associated a set of references to all documents containing this or a similar feature in their descriptors. Retrieval results can then be obtained by computing weighted unions of reference sets. This storage organization results in short retrieval times, even for complex queries.
One general problem with all classification approaches is reclassification. A classification scheme captures some well-organized knowledge on a domain. Since there is a rapid evolution in all software areas, the knowledge on this domain is a subject to change. To reflect the growing knowledge, the classification system has to be changed accordingly. Such changes may set a lot of descriptors into inconsistent states, e. g. because a feature contained in the descriptor was deleted.
In FOCS we allow for arbitrary changes to the classification scheme. Descriptors affected by these changes can be identified easily due to our storage structure and then adapted to the new situation. We describe how this adaption can be automated in many cases.
In an example session we describe how the FOCS tools are used to develop a classification scheme, how components are classified (stored) according to a given classification scheme, and how a query to the library is constructed and processed.