C S E Detecting Architectural Mismatches During Systems Composition

2 downloads 0 Views 214KB Size Report
Jul 8, 1997 - Data Systems Corporation, E-Systems, Hughes Aircraft Company, ... Analysis, Jet Propulsion Laboratory, Litton Data Systems, Lockheed Martin ...
USC

C S E University of Southern California

Technical Report USC/CSE-97-TR-506 July 8, 1997 Qualifying Report for partial fulfillment of Computer Science Department requirements

Center for Software Engineering

Detecting Architectural Mismatches During Systems Composition Cristina Gacek

Approved for public release. Distribution unlimited.

Center for Software Engineering Computer Science Department University of Southern California Los Angeles, CA 90089-0781

Acknowledgments: This research is sponsored by the Affiliates of the USC Center for Software Engineering. The current Affiliates are Aerospace Corporation, Air Force Cost Analysis Agency, AT&T, Bellcore, DISA, Electronic Data Systems Corporation, E-Systems, Hughes Aircraft Company, Interactive Development Environments, Institute for Defense Analysis, Jet Propulsion Laboratory, Litton Data Systems, Lockheed Martin Corporation, Loral Federal Systems, Motorola Inc., Northrop Grumman Corporation, Rational Software Corporation, Rockwell International, Science Applications International Corporation, Software Engineering Institute (CMU), Software Productivity Consortium, Sun Microsystems, Inc., Texas Instruments, TRW, U.S. Air Force Rome Laboratory, U.S. Army Research Laboratory, and Xerox Corporation.

Table of Contents Part I: Introduction.............................................................................................1 1.0

Introduction..............................................................................................3

Part II: Related Work..........................................................................................11 2.0

Related Work ...........................................................................................13 2.1 2.2 2.3 2.4 2.5

COMPLEMENT ..............................................................................................13 Shaw and Clements ..........................................................................................15 Kazman, Clements, Abowd, and Bass .............................................................18 Abd-Allah.........................................................................................................22 Architecture Description Languages (ADLs) ..................................................30 2.5.1 ACME................................................................................................30 2.5.2 Aesop .................................................................................................32 2.5.3 C2.......................................................................................................33 2.5.4 Darwin ...............................................................................................34 2.5.5 MetaH ................................................................................................35 2.5.6 Rapide ................................................................................................36 2.5.7 SADL.................................................................................................39 2.5.8 UniCon...............................................................................................42 2.5.9 Wright ................................................................................................44

Part III: Contribution .........................................................................................47 3.0

Approach Description ..............................................................................49 3.1

4.0

Styles Descriptions...................................................................................53 4.1 4.2 4.3

5.0

Revisiting Event-Based....................................................................................53 Blackboard .......................................................................................................54 Characteristics of Other Styles.........................................................................56 4.3.1 Rule-Based.........................................................................................56 4.3.2 Logic Programming ...........................................................................57 4.3.3 Transactional Database-Centric .........................................................59 4.3.4 Real-Time ..........................................................................................60 4.3.5 Closed-Loop Feedback Control.........................................................60

New Conceptual Features ........................................................................62 5.1

6.0

Extending the AAA Model ..............................................................................51

Styles Choices ..................................................................................................63 5.1.1 Main-Subroutine ................................................................................63 5.1.2 Pipe-and-Filter ...................................................................................63 5.1.3 Distributed Processes.........................................................................65 5.1.4 Event-Based.......................................................................................65 5.1.5 Blackboard.........................................................................................66 5.1.6 Conceptual Features Table Revisited.................................................66

Modeling the Styles .................................................................................68 6.1

Updates to the Base Elements ..........................................................................68

6.2 6.3

7.0

Examples of Potentially Found Mismatches............................................83 7.1

8.0

Revisiting the Event-Based Style .................................................................... 75 Blackboard Style.............................................................................................. 77 Composition With Blackboard Systems .......................................................... 83 7.1.1 Combining Two Blackboard Subsystems.......................................... 83 7.1.2 Combining a Blackboard and a Distributed Processes Subsystems.. 85 7.1.3 Combining a Blackboard and an Event-Based Subsystems.............. 87 7.1.4 Combining a Blackboard and a Main-Subroutine Subsystems ......... 90 7.1.5 Combining a Blackboard and a Pipe-and-Filter Subsystems ............ 92

Newly Found Mismatches .......................................................................95 8.1 8.2

Generic............................................................................................................. 95 Style Specific ................................................................................................... 98

9.0

Revisiting the Mismatches Table .............................................................99

10.0

Observations on the Additional Styles.....................................................102

Part IV: Conclusion ............................................................................................107 11.0

Summary of Key Contributions ...............................................................109

12.0

Future Directions .....................................................................................110 12.1 12.2

Short Term ....................................................................................................... 110 Long Term ....................................................................................................... 111

Part V: Bibliography and Appendices ................................................................113 13.0

Bibliography ............................................................................................115

14.0

Appendices...............................................................................................121 Appendix A: Appendix B: Appendix C: Appendix D:

Introduction to the ZSL Notation ....................................................... 121 Abd-Allah’s Z Model.......................................................................... 125 Minor Changes to Abd-Allah’s Model of Styles ................................ 151 Acronyms............................................................................................ 155

List of Figures Figure 1: Figure 2: Figure 3: Figure 4:

Extending the Base entities to Style-specific entities ..................24 Mismatch #2 of Group Operation ................................................27 Horizontal Composition Example................................................41 SGS Reference Architecture ........................................................64

List of Tables Table 1: Table 2: Table 3: Table 4: Table 5: Table 6: Table 7:

A feature-based classification of architectural styles...................17 Temporal features of architectural elements ................................19 Static features of architectural elements ......................................20 Four Instances in an Architectural Style Space ...........................26 Mismatches Related to the Conceptual Features .........................27 Current Instances in Our Architectural Style Space ....................67 Current Mismatches .....................................................................99

Abstract The USC Architect’s Automated Assistant (AAA) tool and method provides a capability for early detection of architectural style mismatches among four architectural styles: Main-Subroutine, Pipe-and-Filter, Event-Based, and Distributed Processes. For these four styles, mismatch detection is based on a set of seven conceptual features distinguishing each style, and a set of eight types of bridging connectors characterizing compositions among the four styles. The work proposed here is to formalize some additional architectural styles---namely Blackboard, Closed-Loop Feedback Control, Logic Programming, Real-Time, Rule-Based, and Transactional Database styles---and to extend the mismatch analysis capability to cover interactions of the original four styles with the new ones. The analysis results will test various hypotheses, such as the sufficiency of the original seven conceptual features and eight bridging connector types to characterize the broader set of styles and their composition. We will also try to provide a more formal basis for detecting and classifying architectural conceptual features, thus providing a formal framework for extending the models. The application of the broadened mismatch analysis capability to a relevant problem will also be included in the future.

v

vi

Part I: Introduction In the following section, we present a description of the problem which this proposed work will be addressing, while discussing a few relevant concepts such as megaprogramming, software architectures, and software architectures styles. We also give a short introduction to Abd-Allah’s dissertation work [AbdAllah 1996] that is used as the starting point for this work.

1

2

1.0 Introduction Megaprogramming [Boehm and Scherlis 1992], the practice of software construction in a component-oriented fashion heavily based on software components reuse, has long been recognized as an important solution for the software crisis [McIlroy 1969] [Radice and Phillips 1988]. It is a powerful means of not only reducing software development costs in the long run, but also reducing the risk of project failure, improving software quality, shortening development time, and greatly increasing the productivity of the individual software developer. One of the major elements that determine the success of an environment using megaprogramming is the actual reuse of available software components with a minimum amount of effort. This involves the software engineer determining the need for a component which is already available, effectively selecting the component that does actually fulfill his/her need, and appropriately using it. Some of the difficulties with past reuse attempts have been in determining the amount of effort it takes to produce reusable components, estimating the number of components to reuse, effectively selecting reusable components, and adapting components originally thought completely reusable to subtle differences in domain and/or architectural assumptions (about timing, synchronization, data forms, coordinate systems, environment models, etc.). Facets were used to simplify the process of selecting reusable components [Prieto-Diaz and Freeman 1987] [Gacek 1995], but still underlying assumptions were ignored. Handling, or

3

rather detecting, the differences in underlying architectural assumptions is the focus of this work. The Domain Specific Software Architecture (DSSA) approach was created with the intention of providing an effective megaprogramming environment, where all components contain the same underlying domain and architectural assumptions. “A DSSA is a process and infrastructure that support the development of a Domain Model, Reference Requirements, and Reference Architecture for a family of applications within a particular problem domain. The expressed goal of a DSSA is to support the generation of applications within a particular domain (also known as a product-line)” [Tracz 1994]. An architecture in a specific domain will identify the domain’s conventions and shared assumptions, the required degree of generality (number of parameters that can change) and integrability (how a component fits within the context of the application). This approach can be very successful, but it is not always feasible considering its very large up front investment required for building the infrastructure. Nowadays, in order to be competitive, a developer’s usage of Commercial off the Shelf (COTS), or Government off the Shelf (GOTS), packages has become a sine qua non, at times being an explicit requirement from the customer. The idea of simply plugging together various COTS packages and/or other existing parts results from the megaprogramming principles. What people tend to trivialize is the side effects resulting from the plugging or composition of these subsystems. Some COTS vendors tend to preach that because their tool follows a

4

specific standard, say CORBA, all composition problems disappear. Well, it actually is not that simple. Side effects resulting from the composition of subsystems are not just the result of different assumptions in communication methods by various subsystems, but the result from differences in various sorts of assumptions, such as the number of threads that are to execute concurrently, or even on the load imposed on certain resources. This problem is referred to as architectural mismatches [Garlan et al. 1995a][Abd-Allah 1996]. Some but not all of these architectural mismatches can be detected via domain architecture characteristics, such as mismatches in additional domain interface types (units, coordinate systems, frequencies), going beyond the general interface types in standards such as CORBA. Another significant source of architectural mismatches derives from mismatches among architectural styles. An architectural style defines a family of systems based on a common structural organization [Shaw and Garlan 1996]. It constrains both the design elements and the formal relationships among the design elements [Perry and Wolf 1992]1. Some of these constraints are common to various styles, for example having explicit data connectors to support data transfers between components is not a characteristic only present in the pipe-and-filter style, but it also occurs in the distributed processes one. The absence of these constraints in other styles is just as 1. One can find various definitions of software architectures in the literature [Perry and Wolf 1992] [Shaw and Garlan 1996] [Tracz 1994]. The one used throughout this work we introduced in a previous paper [Gacek et al. 1995]. Namely, we consider an architecture to be a set of components, connectors, constraints imposed on the components, connectors, and their composition, and a supporting rationale. Such architectures should be presentable in various ways---different views supporting different needs.

5

important, e.g., the main-subroutine and event-based styles do not have explicit data connectors, but rather use shared variables for data transfers by definition. A set of these special constraints was defined by Abd-Allah, and called the set of conceptual features [Abd-Allah 1996]1. Different styles can then be characterized by selecting different options for each conceptual feature. I.e., a style is defined by a set of conceptual feature choices, where individually, each of those choices may also exist in some other style. Once a complete set of conceptual features is defined2, we will be able to use them to differentiate the various architectural styles by concentrating on these abstract characteristics. Abd-Allah’s work on conceptual features was based on the distributed processes, event-based, layered, main-subroutine, multithreaded, pipe-and-filter, and software bus styles 3. The work proposed here will be testing the hypothesis that his set of conceptual features is sufficient to characterize other styles, namely blackboard, closed-loop feedback control, logic programming, realtime, rule-based, and transactional database styles (see section 3.0)---and extending the set of conceptual features where necessary. We would also like to determine the various dimensions that could be used to describe orthogonality of the

1. Other classification efforts do exist, and are covered in the related work section (section 2.0 on page 13). 2. It is not the aim of this work to generate a complete set of conceptual features, specially because there is no way of proving completeness here. 3. See section 2.4 on page 22 for a complete description of his work, as well as how it compares to the work proposed here.

6

various conceptual features, thus providing a more formal description of the conceptual feature space. When actually building systems, people may or may not adhere to a pure architectural style, also the same style name may mean slightly different things to different people. For example, in some pipe-and-filter analyses, [Shaw and Garlan 1996] has found it useful to employ the concepts of colored pipes and parametrized filters. In cases where some variation of an existing style is used, a complete set of conceptual features should suffice for description. Clearly, if some completely new style comes along, using some revolutionary paradigm, the set of conceptual features needs to be revisited, and potentially extended. The use of COTS and GOTS packages brings a slightly different light into the problem. Hardly ever will a COTS vendor be willing to explicitly describe all the intrinsics of their package to the general public. In such cases, the use of conceptual features becomes a facilitator, since vendors may be willing to give out at least general style information on these characteristics---they do describe the system and often help describe API’s, without giving away secrets that could reduce the vendor’s competitive advantage. When composing systems, many potential architectural mismatches can be detected by analyzing their various choices for conceptual features. Mismatches may occur because the subsystems have different choices for some particular feature. E.g., one is multi-threaded and the other isn't, creating the possibility of synchronization problems when accessing some shared data (the single-

7

threaded part assumes there is absolutely no risk). Mismatches may also occur because the subsystems make the same choice for some particular feature. E.g., if two subsystems are single-threaded, we may also run into synchronization problems when accessing some shared data, since both parts assume there is absolutely no risk. However, a few potential mismatches are style-specific (see section 8.2) and need to be handled in an ad hoc basis. It is extremely important to point out that different architectural styles may have different meanings to different people, as well as the fact that occasionally there is a need to use a slightly adapted style (non-pure), specially when describing a previously existing system (either OTS or from a components’ library). Thus, by working at the conceptual feature level for mismatch detection, we can cover a much wider range of systems’ composition than if we dealt with the problem in a style by style basis. The aim of this dissertation will be to formally address software composition at the architectural style level, by addressing a number of open questions in the previous work by Abd-Allah in order to get a greater and more formal coverage of conceptual features, and their relations to architectural mismatches. A concise statement of the problem I propose to examine reads as follows, What is a formal model for detecting potential architectural mismatches during the composition of different architectural styles within software systems? Where must current formal models be further structured and extended to cover mismatches among wider ranges of architectural styles?

8

In order to address the questions above, one needs to understand the complexities of systems composition and its potential side effects. It is also necessary to have a firm grasp on the characteristics of a wide range of architectural styles, and their relevance to composition. As a means of providing a model supporting the concepts uncovered, it is also essential to have a deep understanding of the formalism to be used, and provide some mechanism to analyzing given formal specifications. One should note that this work will not only provide a formal model to support architectural composition, but a tool will also be provided to automate this compositional analysis.

9

10

Part II: Related Work Other researchers have been working on software architectures and their composition, architecture styles and their classification, and systems classification based on conceptual features. The following section describes some of their results, and discusses the deficiencies of these past efforts with respect to addressing the central question of this dissertation. It also includes some discussion on various ADLs and their approach to composition of heterogeneous systems.

11

12

2.0 Related Work There are several related works that should be discussed here. They cover topics such as real-time systems classification while considering a different set of conceptual features by the COMPLEMENT project (section 2.1), architectural styles and their classification by Shaw and Clements (section 2.2), architectural elements classification by Kazman and his colleagues (section 2.3), and AbdAllah’s dissertation work on detecting architectural mismatches during systems composition, while focusing on the main-subroutine, pipe-and-filter, distributed processes, and event-based styles (section 2.4). Some architecture description languages (ADLs) and their supporting tools are also discussed (section 2.5).

2.1 COMPLEMENT The COMPLEMENT project has its focus on technical aspects of developing real-time and embedded systems [Pyle et al. 1993]. In order to understand what particular features make real-time and embedded systems different from other systems, and what differentiates on kind of real-time and embedded system from another, they devised a domain specific system taxonomy (where the domain is simply real-time and embedded). Their taxonomy consists of sets of primary, secondary, and concrete features. Their primary features are: concurrent processing (many or few concurrent events); hardware interface (significant or not); timed reaction to events (hard or soft real-time1); distribution (multiple or single site); and database (significant

13

or not). Their secondary features are: dependability (high or low); reconfigurability (on or off-line); usability--human/computer interface (intuitive or need training); certifiability (essential or not required); constraints--environmental aspects (significant or not); and evolution capability (evolutionary or not). Their concrete features are: target platform; type of external transducers; replication; contractual requirements; and application domain. The COMPLEMENT project uses their system taxonomy as a real-time and embedded systems classification facilitator, and not as the focus of compositional analysis. Still the features they use can give us some insight on characteristics we may need to consider for our compositional purposes. At first glance, their set of primary and concrete features should be a part of the issues considered for composition, whereas their secondary features, which are mainly quality attributes are not as relevant. A closer look at their primary features reveals that whereas having a significant hardware interface may change dramatically a system performance (as opposed to one that has a more significant human interface), this kind of characteristic is not really relevant for any other kind of systems, so it might not be required for the purpose of the work proposed here. All other primary features are very relevant for composition, and should be part of our conceptual features1.

1. Hard real-time requirements are those that if the system reacts too late, it is considered to fail. On the other hand, soft real-time requirements are those that it is undesirable that the system reacts too late, but it is not considered a failure if it happens. 1. Note that in our case, timed reaction to events may take the values hard or soft realtime, as well as unconstrained.

14

Most of their secondary features, being quality attributes could be considered here, but actually go beyond what this work is trying to address. The only one that might be useful to include is the one indicating whether a system is reconfigurable on or off-line. During composition, if one of the systems expects to be able to reconfigure on-line while the other doesn’t, we might run into problems. Whether this will be included or not in the work proposed here is still to be determined. From their set of concrete features, there are a couple that do not apply here, namely contractual requirements and application domain. During composition, one would only consider an existing system to be reused if it was known to conform to the contractual requirements at hand, be them on programming language, standards or any other. As far as application domain goes, the only difference this could bring to a composition consideration is on the quality attributes originally required of the sub-system. As already mentioned above, on the discussion of the secondary features, quality attributes and their detection at the architecture level are very important, but go beyond the focus of the work proposed here.

2.2 Shaw and Clements Shaw and Clements present a classification of architectural styles based on a set of features focusing on control and data issues. They do this by describing the feature categories, and defining how each of several styles handles them. They

15

also provide a few rules of thumb to aid on style selection when implementing solutions to specific problem instances [Shaw and Clements 1997]. The architectural style classification they propose is based on: the kinds of components and connectors that are used; how control is shared, allocated, and transferred within the system; how data is communicated through the system; how data and control interact; and the type of reasoning that is compatible with the style. As control issues they address the topology, synchronicity, and the binding time. Data issues include topology, continuity (how continuous is the flow of data throughout the system?), mode (how is data made available throughout the system?), and binding time. Control/data interaction issues elaborated are whether control and data flow topologies have similar shapes or not, and if these shapes are the same, whether control and data flow in the same or opposite directions. They present their results in terms of a table. Their full classification can be found on their paper. On table 1 one can find some examples of their classification that can already be compared with results obtained by Abd-Allah (section 2.4), and by the work proposed in this document (section 5.0 on page 62). The granularity level of the features considered by Shaw and Clements is lower than the one to be used by this work to classify systems. The information they convey for classification purposes is part of our underlying model, but it is not considered at the conceptual features (more abstract) level. Exceptions are the fact that the model proposed in this document does not include information on types of reasoning supported by the style, nor information on control or data binding time.

16

Styles Features

Main program/ subroutine

Event systems

Blackboard

Components

procedures, data

processes

memory, computations

Connectors

procedure calls

implicit invocation

direct access

hierarchical

arbitrary

star

sequential

asynchronous, opportunistic

asynchronous, opportunistic

write, compile

invocation, run

write

arbitrary

arbitrary

star

sporadic, low-volume

sporadic, low-volume

sporadic, low-volume

passed, shared

broadcast

passed

write, compile, run

invocation, run

write, compile, run

Isomorphic control/ data shapes

no

no

yes

Control/data flow directions

n/a

n/a

opposite

Type of reasoning

hierarchical (local reasoning)

nondeterminism

---

Control topology Synchronicity Control binding time Data topology Continuity Mode Data binding time

Table 1: A feature-based classification of architectural styles To this point, mode of data transfers is the only one of their features that shows as a conceptual feature in our work. Probably the fact whether data flows continuously or sporadically throughout the system will soon be added. The focus of their paper is to classify styles while standardizing the vocabulary and concepts each involves, and discriminate among styles showing their differences and similarities, supporting for the organization of advice on how

17

to select a style for solving a specific problem. Since it is not part of their focus, they do not address compositional issues.

2.3 Kazman, Clements, Abowd, and Bass On a recent work [Kazman et al. 1997], related to the one by Shaw and Clements (section 2.2), Kazman and his colleagues try to support system composition in a manner very similar to the one proposed here. They use behavioral characteristics which they call features to classify architectural elements (components and connectors), not architectural styles nor systems. The behavioral characteristics they considered useful are temporal and static ones. A temporal view of architectural elements describes the behavior of an element over time. The temporal characteristics they address are: times of control acceptance; times of data acceptance; times of control and data transmission; if forks occur; and whether the element retains state information. A static view of architectural elements summarizes their invariants. The static characteristics they address are: what the data and control scopes are; whether the element transforms data; binding time; if connecting to this element blocks the connecting element, does the element relinquish control; are ports in, out, or in/out; and how many elements can connect to each port, both at any one moment in time, and over the lifetime of the element.

18

They give examples of architectural elements classifications. A subset of those can be found below, actually including only the ones that would be relevant for main-subroutine and blackboard systems. Temporal Features Accepts control at other than ts? Arch. Element

Transmits control at other than te?

Singleentry procedure

never

Object

Accepts data

At ts?

At other than ts?

never

always

never

never

Function

never

Procedure call Blackboard

Transmits data Forks ?

Retains state?

At te?

At other than te?

never

not criterial

not criterial

never

same thread

always

never

not criterial

not criterial

never

same or different threads

never

always

never

always

not criterial

never

same thread

never

never

always

never

always

never

never

same thread

always

always

not criterial

always

not criterial

always

never

same or different threads

Table 2: Temporal features of architectural elements

By examining their temporal features (table 2), one can see that some of them are already part of the AAA model and the conceptual feature set (e.g., “forks?”), others are to be included soon (e.g., “accepts control at other than ts?”, see section 10.0 on page 102), and others will require some further thought (e.g., “transmits data at te,and other than te?”).

19

Static Features

Associations Data scope

Control scope

Trans forms data?

Binding time

Blocks ?

Relin quish ?

Ports

Singleentry procedure

virtual address

virtual address

yes

spec., execution

not criterial

yes

1 I;

Object

virtual address

spec., execution

not criterial

spec., execution

not criterial

spec.

yes

Arch. Element

Function

virtual address

Procedure call

virtual address

virtual address virtual address virtual address

yes

yes

no

Per Life conn time 1

n

1

n

1

n

1

1

1

n

mO yes

n I; mO

yes

1 I; mO

yes

I; O

Blackboard

distributed

distributed

no

spec., invocation, execution

not criterial

yes

I; O

Table 3: Static features of architectural elements Their static features are a bit different (table 2), most of these are part of our model, but not all are part of the conceptual features set. Ports information, for example, is part of the model, but does not show up in the conceptual features set. Control scope and relinquishing control (we called termination) do show at both our model and conceptual features level (section 5.0 on page 62). Information on whether data is transformed or not is not part of our model, nor our conceptual features set. There are also some conceptual features that we have found extremely relevant for composition, that are not included in their set of features, some of

20

them are whether there is backtracking allowed, whether components have priorities associated with them, and whether there is preemption or not. These features were not part of the original AAA model, but are being added by the work proposed here (section 5.0 on page 62 and section 10.0 on page 102). Kazman and his colleagues also discuss composition of architectural elements. They mention that when composing two elements some of their features must match, whereas others can be ignored. As features that must match they mention ports and their associations. As features that may be ignored they list state retention, data transformation, blocks, forks, and relinquish. They do not provide a formal discussion on the feature combinations of composing elements that are allowed or not, and the compositional discussion they provide is only of a one element plus another approach (i.e., they don’t discuss problems at the system level). The major difference between their classification and the one being offered here is that they are doing so at the element (component and connector) level, whereas we do it at the system level (percolating to the architectural element level in the model). This means that our classification is a little more abstract than theirs, hence probably more applicable at earlier stages than theirs. Also, they do not offer clear guidelines on how to use their set of features during system composition, nor do they allow for analysis of the composition of several elements together. Which means that as long as the elements agree on a one-to-one basis, they detect no problems. Well, here are a few examples of possible problems:

21

• A blocking data connector connecting control components A and B (3 elements). If control component B does not become (or is not) active after A sends some data, A will be in a deadlock situation. • Two control components in the same thread sharing a blocking data connector (3 elements), creates a possibility of deadlock. • A call to a non-terminating (or non-control relinquishing) component, will leave the caller in a deadlock. Note that the last example also contradicts their assumption that whether an element relinquishes control or not is irrelevant for composition. Summarizing, they offer a very good classification framework for architectural elements, and weaker ways of detecting element to element mismatches. They do not provide a framework for composing system architectures, nor insights on possible architectural mismatches during the composition of systems.

2.4 Abd-Allah Abd-Allah’s work on his dissertation and the Architect’s Automated Assistant (AAA) [Abd-Allah 1996] tackled a significant portion of the problem this thesis is focusing on. He constructed a model and a prototype tool to detect potential architectural mismatches during systems composition, while focusing on the main-subroutine, pipe-and-filter, distributed processes, and event-based styles.

22

He modelled styles and systems using Z [Spivey 1992]. His complete Z model can be found in appendix B. Abd-Allah described some base elements that can be refined and combined in various ways in order to describe architectural styles and/or specific systems (see figure 1). These base elements are: “1. A port is typically associated with a control component, and is the latter’s entry and exit points for data during data transfers. 2. A data component models data that is used to store state or is transferred across data connectors. 3. A control component models data that is executed by the underlying machine and which can initiate (and respond to) data and control transfers. It is assumed to have a single thread of control (from a hardware point of view, a control component has a single program counter). 4. An object is an encapsulation of a set of data components with a set of control components. Not only from a formal standpoint is an object fundamentally different from a data or control component (i.e. {X} is not the same type as X), but there are other reasons for this distinction, • an object can include complex interconnections within itself, forming its own single-threaded minisystem (see the definition of system below) • an object can be instantiated many times, each time introducing a new set of different data and control component copies 5. A data connector models the potential for two or more control components or objects to engage in data transfers amongst themselves. 6. A control connector models the potential for two or more control components to engage in control transfers (possibly with data) amongst themselves.

23

7. A trigger associates an action (a data or control transfer) with the reception of a data component by a control component or object. 8. A system is a non-empty set of interconnected control components or objects satisfying some unique purpose.” “Thing” Port

Data Control Object Data Control Component Component Connector Connector

Event queue Socket

Shared data

Object Pipe

Call Spawn Circuit

Filter Data Process store Procedure

Pipe & Filter Style

Lexical Compiler: Analyzer

Syntax Parser

Semantic Analyzer

Code Generator

Figure 1: Extending the Base entities to Style-specific entities

Abd-Allah also suggested the use of conceptual features as a higher level abstraction for describing architectural styles and/or systems characteristics (see also section 1.0). The conceptual features he used were: “1. Dynamism. Earlier we discussed how the topology of software can be dynamic, adding and removing concurrent threads as it executes. Some styles constrain the topology to be static (i.e. the number of concurrent threads remains constant), while other styles do not. A style is dynamic if

24

and only if it allows non-blocking control connectors (spawns). 2. Supported data transfers. Of the styles we studied, all of them achieved data transfers through one (or more) of three mechanisms: explicit data connectors, an implicit global network of data connectors, or shared data variables. 3. Triggering capability. Hardware has interrupts, and software has triggers. Some styles allow the transfer of data (events) along explicit data connectors or a global network to cause certain actions, e.g. control transfers or additional data transfers. 4. Concurrency. Styles often constrain the number of concurrent threads that may execute within a system. A singlethreaded system is limited to only one thread of control components linked by a chain of calls (blocking control connectors), while multi-threaded systems allow more than one thread to execute concurrently. Note that concurrency is not the same as dynamism. 5. Distribution. A style may or may not constrain the mapping of system entities to nodes. If the mapping is to more than one node, then the style’s systems are naturally distributed. 6. Layering. Styles may or may not impose system layering constraints on its control components. The layers must be specified with respect to a connector, e.g. a set of layers linked by control connectors. 7. Encapsulation. As shown earlier, objects are fundamentally different from data control components. A style may choose to be object-oriented or not.” How each of these features applies to each of the styles he discussed is shown in table 4. Conceptual features get propagated into the Z model as a set of constraints on the base elements that varies from style to style, depending on the choices made for each of the conceptual features. He then continued to show how the combination of the presence and/or absence of certain conceptual features on parts to be composed could potentially 25

Styles Pipe & Filter Conceptual Features

Main/ Subroutine

Distributed Processes

Event-Based

Dynamism

static

static

dynamic

static

Supported data transfers

explicit data connectors

shared data variables

explicit data connectors

implicit network, shared data variables

Triggering capability

no

N/A

no

yes

Concurrency

multi-threaded

single-threaded

multi-threaded

single-threaded

Distribution

unconstrained

single node

multiple nodes

unconstrained

Layering

unconstrained

unconstrained

unconstrained

unconstrained

Encapsulation

no

no

no

yes

Table 4: Four Instances in an Architectural Style Space cause architectural mismatches, depending on the bridging connector1 used between them. These are described in table 5. “An explanation of each mismatch is given below. 1. Two concurrent threads share data, with potential synchronization problems. 2. Two threads have data connectors to 2 different control components in a third thread (it is impossible for the third thread to execute in the two components simultaneously see figure 2). 3. Two control components in the same thread share a blocking data connector, creating a possibility of deadlock. 4. A layering constraint is violated. 5. Different sets of recognized messages are used by two subsystems that permit triggers.

1. Bridging connector is the term he uses to refer to the connector used to compose the parts together. I will also use this term for the same purpose.

26

call spawn

6

15

4

13

15

4 4

data connector

10

2,3

15

shared data

11

1

15

triggered call

12

5,7,9

12

5,7,9

12

5,7,9

triggered spawn

8

triggered data transfer shared machine

14

15

4

15

4

15

4

Encapsulation

Layering

Distribution

Concurrency

Triggered

Bridging connectors

Data Transfers

Dynamism

Conceptual features

16

Table 5: Mismatches Related to the Conceptual Features

thread 1

thread 2

thread 3

data connector

call control component Figure 2: Mismatch #2 of Group Operation

6. A spawn is made into a subsystem which originally forbade them. 7. An unrecognized trigger message is used. 8. A triggered spawn is made into a subsystem which originally forbade spawns. 9. A trigger refers to a subsystem which originally forbade triggering.

27

10. A data connector is made into a subsystem which originally forbade them. 11. A shared data relationship refers to a subsystem which originally forbade them. 12. A trigger refers to a subsystem which forbids explicit or implicit data connectors, hence the trigger may never occur. 13. A spawn is made into a subsystem which is not concurrent. 14. A triggered spawn is made into a subsystem which is not concurrent. 15. A remote connector is extended into or out of a non-distributed subsystem (i.e. a subsystem originally confined to a single node). 16. A node resource is overused (this is actually checked by summing across the subsystems’ usage of that particular resource).” In order to investigate other styles such as blackboard and real-time, the set of architectural base elements he introduced suffice, though their characteristics on the underlying model do need to be evolved (for example to include component priorities). As far as his set of conceptual features are concerned, his model had a considerable coverage for the styles he focused on, but certainly not for some other very commonly used styles such as real-time, and closed-loop feedback control for example. Characteristics such as being a system preemptive, reentrant, and terminating or not are completely absent from his model, even though they are extremely relevant for composition. Furthermore, he considered encapsulation one of his conceptual features, but never showed it had any relevance to architectural mismatches during composition.

28

Additionally, he provided no clear guidelines for determining when to add new conceptual features (i.e., which characteristics are to be considered or not, and why). He provided no discussion on how the conceptual feature space was composed, ways of classifying it, and means of extending it. A decision has been made that the work proposed here will continue the directions set forth by Abd-Allah, yet it is important to note that this is only the starting point for evolution. Major changes will be present: • His set of architectural base elements might remain the same, but their characteristics will change to reflect new conceptual features at the model level, in fact they have already changed at this point (see section 6.0 on page 68). • His set of conceptual features will be evolving considerably. These also have already evolved somewhat (section 5.0 on page 62), and have very clear growth directions to include (section 10.0 on page 102). • The original set of mismatches detected by his model will not only evolve to reflect the new conceptual features, but already do also include considerations about the encapsulation characteristic (section 8.0 on page 95). • Additionally some new bridging connectors must be added. At least shared resources do become major issues when composing any system with a realtime one (section 10.0 on page 102). • We will also try to formalize the various dimensions that can be used to describe the conceptual feature space as a set of orthogonal concepts.

29

2.5 Architecture Description Languages (ADLs) Here one can find a discussion of several ADLs and their supporting tools, while focusing on the problem of composition of heterogeneous systems. For a survey on ADLs and their supporting tools in general, please refer to the work by Medvidovic [Medvidovic 1997]. It is important to note that the observations presented here are just a picture in time. The tool set related to each and every ADL is continuously evolving, as are some of the ADLs themselves (e.g.: ACME).

2.5.1 ACME ACME is an architecture interchange language [Garlan et al. 1995b][Garlan et al. 1997]. Rather than being yet another ADL, it is an interchange mechanism, intended to support transformations of architectural specifications between heterogeneous ADLs. Consequently, ACME has no direct tool support1, but enables the use of support tools from various ADL suites. The approach consists of providing means of describing the structural (or topological) characteristics of architectures, along with annotations containing ADL-specific information. This strategy allows the sharing of common architectural information by various ADLs and their tools, as well as supports the specification of information not present in all ADLs. “This is the essence of ACME. The

1. ACME has no direct tool support, but it does enforce some structural constraints, such as disallowing a connector to be attached to another connector, or the existence of a dangling port.

30

language provides a fixed vocabulary (or ontology) for representing architectural structure. Additionally it provides an open semantic framework in which architectural structures can be annotated with ADL-specific properties. In this way ACME achieves the benefits of both an intersection and a union language: the shared structural core represents an intersection of the expressive capabilities of most ADLs, while the use of annotations accommodates the union of ADL-specific concerns” [Garlan et al. 1997]. In the context of this work, ACME could be applied in several ways: • Specifications written in any arbitrary ADL and then translated into ACME could then be translated into the formalism used here, permitting its use as input for the analysis capability introduced here. • This work could actually use ACME as its native modeling language, making heavy use of annotations for semantic needs not covered by ACME. • Specifications written using the formalism introduced here could be translated into ACME, allowing for further analysis by other ADLs and their tools. Whether any of these will actually be used here is still an open issue at this point, and one to be resolved very soon.

31

2.5.2 Aesop Aesop is a tool kit designed to support the rapid development of “styleaware” software architecture design environments. A style specific environment is achieved by providing style-specific vocabulary of design elements (as subtypes of basic architectural classes), stylistic constraints as methods of these types, and a collection of external tools that perform architectural analyses that are relevant to that specific style [Garlan 1995]. The Aesop tool kit includes a repository for architectural level design elements and patterns called the Software Shelf [Monroe and Garlan 1996]. The Software Shelf supports the classification, storage, and retrieval of architectural elements, namely components, connectors and configurations (or patterns). Design elements stored in this repository are classified by category (component, connector or pattern), style or set of styles for which it was created, and class within the style (i.e., type of component, connector, or pattern within the particular style). It is critical to note that Aesop focuses on homogeneous architectures, so environments are specialized by style, not allowing the use of more than one style at a time. The work we are proposing here tries to handle composition of both homogeneous and heterogeneous systems architectures. It is also important to highlight that the reusable architectural elements provided by the Aesop Software Shelf are abstract or incomplete design fragments, to be further refined upon retrieval. Even though the primary focus of one of their works is to integrate software architecture, architectural styles, and software reuse

32

[Monroe and Garlan 1996], it is not in the scope of the Aesop tool kit to try to accommodate the architecture of pre-existing software. Consequently, their focus is different from the one proposed here. I can see one danger on trying to evolve the work in the Software Shelf to also cover pre-existing software, namely that hardly ever will one be able to find some OTS product whose architecture has been defined in one pure architectural style. Even when addressing OTS components, if we have the developer of the component being the one specifying the architecture style used, his/her definition of the style might be different than that of the (re)user of the component.This would introduce some considerable complexity on Software Shelf’s classification scheme, and consequently on the retrieval as well.

2.5.3 C2 C2 and its design environment (Argo) support the description of user interface systems using a message-based style, enabling the development of GUI architectures with interchangeable and reusable software components [Medvidovic et al. 1996]. The main focus of their work is on reuse of software components, and dynamic changes to run-time architectures for systems conforming to GUI architectures characteristics (this can actually be thought of as a specific style that is message-based, with concurrent component execution, communicating via message routing devices, while being layered and allowing for no shared address space).

33

C2 provides for some type, constraint, and architectural style rule checking. It also has design critics that actively check for completeness, correctness and consistency, among others. Those critics provide feedback in a context sensitive manner during design, or by analyzing an architectural model after a design activity. The reuse focus of the C2 team differs significantly from the one proposed here. They support reuse by allowing for replacement of components in lower layers of the architecture, without impacting the upper layers, and while focusing on their specific style (GUI like architectures). That is all components share the same architectural characteristics, hence architectural mismatches are completely avoided.

2.5.4 Darwin Darwin allows distributed and parallel programs to be structured in terms of groups of process instances which communicate by message passing. In addition to expressing static structure, Darwin can be used to express structures which change dynamically as execution progresses. Darwin uses Π-calculus as its underlying semantic model. “Darwin supports software composition through the description of generic software architectures which can be elaborated and instantiated to form specific executable architectures” [Magee and Kramer 1996]. Components on the style supported by Darwin interact solely by accessing services. During system

34

architecting, a component does not need to know the global names or locations of external services it will be interacting with. This allows for component specification, implementation, and testing independently of the rest of the system, which in turn allows for plug-and-play of various components conforming to the specific style supported. This is the extent to which megaprogramming is supported by Darwin, which is to say that they do not deal with heterogeneous software architectures, and hence have no need to worry about architectural mismatches during systems composition.

2.5.5 MetaH The MetaH architecture description language has been developed to provide specific guidance for designers of real-time avionics control software. The tools check a system description for schedulability and other properties and generate the “glue” code that handles real-time process dispatching, communication, and resource synchronization [Vestal 1997]. MetaH allows a specification of system components and connectors, and their attributes which are relevant to real-time, fault-tolerant, secure partitioning, and multi-processor facets of systems. Tools are available to perform a software/hardware binding, real-time schedulability analysis, reliability analysis, and safety/security analysis. A tool is available to generate the “glue” code needed to provide the scheduling, communication, event handling and fault containment behavior specified in MetaH. The

35

tool set also includes a “make” facility to manage change propagation and automatically perform compilations and links as needed. “Objects in a MetaH specification have separate interface and implementation definitions, where multiple alternative implementations can be defined for the same interface” [MetaH 1996]. This is the only megaprogramming support provided by the tool set. As by the work of Abd-Allah (see section 2.4) we already know that the simple conformance to some specific interface does not prevent architectural mismatches from occurring. MetaH and its tool set provide very strong support for real-time systems, but none for composition of these with systems or parts using different underlying styles.

2.5.6 Rapide Rapide is an executable ADL intended to model the architectures of concurrent and distributed systems by defining and simulating their event-based behavior [Luckham and Vera 1995]. It allows one to specify systems behaviors in terms of partially ordered sets of events. Component computations are triggered by received events, and in turn trigger other computations by sending events to other components. “The result of executing a Rapide model is a set of events that occurred during the execution together with causal and timing relationships between events” [Rapide 1996].

36

The Rapide language framework is divided into 5 sublanguages, aiming to facilitate the reuse of parts of Rapide in other languages, as well as for easy language evolution [Rapide 1996]. These languages are: •Types Language - describes interface types and function types, and supports deriving new interface type definitions by inheriting form pre-existing ones. •Pattern Language - describes patterns of events with causality, independence, and/or timing relationships. •Executable Language - contains control structures to describe behaviors of components. •Architecture Language - describes the flow of events between components, by defining their synchronization and communication interconnections.1 •Constraint Language - defines formal constraints on the behavior of components and architectures, where constraints are posets patterns that are either required or forbidden. The Rapide tool set permits simulation of architectural descriptions, animation of those simulations, and analysis to check for anomalous behavior. A Rapide model simulation results in a poset showing the causal history of events in the specific execution, independent activities, timing, and dataflow. Based on these, various kinds of analyses can be performed. Tools supported by Rapide are constraint checkers (analyzing for conformance to constraints described in the 1. Connectors are not considered first class entities in Rapide.

37

model1), poset browsers (supporting event visualization, while providing for filtering of events for scalability purposes), and animation tools (graphically display the execution using real-time animation for ease of visualization of posets). Rapide’s strengths lie on the use of its various analyses tools. The type of analyses they support are all based on improper event ordering and/or timing during some simulation2. Their literature shows a fairly detailed example on detecting deadlock for a dining philosophers architecture [Luckham 1996]. Rapide allows for the specification of an architecture to be done based on its interfaces, leaving the actual replacement of those by various components with their specific behavior for a later phase. Based on that, one can envision using various pre-existing components on any existing architecture, as long as they conform to the specified interface. Since Rapide is biased towards event-based systems, composing parts via data connections follows naturally, whereas it does not provide for easy means of modelling control connections. It also provides no support for specifying certain system characteristics required for the work being proposed here, such as preemption and backtracking (to be discussed on part III).

1. The constraint checker is not fully implemented yet [Luckham 1996]. 2. Note that some problems only occur occasionally within a single simulation scenario, because there is non-determinism allowed.

38

2.5.7 SADL The work on SADL by Moriconi, Qian, and Riemenschneider [Moriconi et al. 1995] relies on the assumption that large systems’ architectures are described by a hierarchy of related architectures. Where higher levels represent abstractions of lower ones, which may differ in number and kind of components and connectors. This hierarchy being informally described, thus leading to an error-prone refinement process. Based on these observations, they introduce a methodology for correct stepwise refinement of software architectures, by using instances of architectural refinement patterns that are correctness preserving and compositional. The use of this methodology should ultimately lead to fewer architectural design errors, and to extensive and systematic reuse of design knowledge and proofs. To prove the relative correctness between two architectures, they specify an interpretation mapping between them. An interpretation mapping is an association between formulas of the language of the abstract architecture and formulas of the language of the concrete one. An interpretation mapping is determined using a name and a style mapping. The name mapping simply associates the names of the objects in the abstract architecture with those of the concrete one. Thus it needs to be specified for every given pair of architectures. The style mapping says how the constructs of an abstract-level style can be implemented in terms of the constructs of a concrete-level style. These tend to be complex, but need only be

39

defined and proven once. After that the style mapping can be safely reused whenever necessary. The authors discuss two different forms of composition for architectures, vertical and horizontal composition. Vertical composition is used to chain together a sequence of correct architectures, allowing the conclusion that the most concrete architecture in a hierarchy is correct with respect to the most abstract architecture in the hierarchy. Horizontal composition is used to compose instances of refinement patterns to form one large composite refinement architecture. It is also used to compose existing architectures into larger architectures. They then suggest that if two abstract architectures share only components and lower-level architectures share only images of those components under the interpretation mapping, then they can be correctly composed. Subsequently, they show the example in figure 31, as being an appropriate horizontal composition example. The composite system shown in figure 3 adheres to their composability criterion, but it could have problems, depending on intrinsic characteristics of both subsystems A and B. The problem is that they assume the linking architecture will take care of the integration problems, without considering the potential complexity of the issues involved. A deficiency in their paper is that they listed some architectural styles but never explained what they consider relevant characteristics, nor how the styles 1. Figure 4 in their paper.

40

A

A Subsystem A

B

B

Linking Architecture

A

Subsystem B

B

Composite System Figure 3: Horizontal Composition Example

compare to each other. They actually refrain from considering issues like “can components execute concurrently?”, or “does the system allow for preemption?”, which are clearly very important when dealing with architectural composition. Their work’s main focus is clearly on architecture refinement. Vertical composability follows naturally from there, but not horizontal. In horizontal composition, “linking architecture” was mentioned as a solution, we know this can be very complex, and they never hinted on how to deal with that complexity or the problems that may arise. The work proposed here focuses on horizontal composition, more specifically, on detecting potential problems in possible “linking architecture” solutions. Consequently, it is a great complement to the Moriconi, Qian, and Riemenschneider body of work.

41

They actually do discuss what connects to what, and shared variables, but there is no way of representing concurrency, dynamism, termination, or preemption using SADL [Moriconi and Riemenschneider 1997]. So if there could be any potential problems on these areas, there would be problems on applying even vertical composition.

2.5.8 UniCon UniCon is an ADL whose primary focus is on supporting descriptions of architectures, “localizing and codifying the ways components interact, and distinguishing among various packagings of components that require different forms of interaction” [Shaw et al. 1995]. More specifically, the objectives of UniCon and its tool set include: (a) providing uniform access to a wide range of components and connectors (not restricted to a single style); (b) discriminating among various types of components and connectors, facilitating the checking for proper configurations; (c) supporting the use of analysis tools developed by others, and using different underlying representations; and (d) handling existing components as any other component. In UniCon components are specified by their type, property lists (attribute-value pairs), and interaction points (players) where connectors are to be hooked. Connectors are described by their type, property lists, and interaction points (roles) where they are supposed to interface with components [Zelesnik

42

1996]. System configurations are then defined by associating specific components’ players with specific connectors’ roles. Towards achieving objective (a), several types of pre-defined components and connectors are provided in a miscellaneous collection, from which the architect is to choose the ones considered appropriate for the specific situation. Objective (b) is fulfilled by differentiating among the types of interaction points provided by all types of components (players) and connectors (roles), UniCon allows for the restriction of those combinations (i.e., not all player-role pairs are allowed during system composition) by means of implicit rules. These localized checks is the only means of mismatch detection currently provided by the UniCon tool set, there are no means of specifying global systems’ constraints. Mismatches that occur as side effects to the composition of certain components and connectors are not detected at all (e.g., the presence of potential for deadlock, or the existence of some high resource contention). Objective (c), supporting the use of analysis tools developed by others, and using different underlying representations has already been recognized as extremely important by the software architecture research community, hence the effort on ACME (see section 2.5.1). Note that the same property list approach that UniCon uses has also been adopted by ACME, and by the Architecture Capture Tool (ACT-1) currently under development at USC. Currently, UniCon supports for rate-monotonic analyses by another independent CMU tool, and there is on going work for translating to and from ACME.

43

The way that UniCon handles pre-existing components (objective (d)) is by defining their interfaces according to UniCon terms. This means to say that during composition, the only mismatch checking that happens in this situation is once again on making sure that the specific role-player combination is an allowed one.

2.5.9 Wright Wright supports the specification and analysis of interactions between architectural components. Components and connectors are specified using a CSP based notation. Specifically, connectors are described by a protocol which specifies the behavior of the components which it connects [Allen and Garlan 1994]. They are described by their interface points (roles) which indicate what is expected of the components to participate in the interaction, and how that interaction actually takes place (glue). Components are described by their interface points (ports) and their behavior (computation), which indicates how the ports are associated to each other by the component’s behavior. Once component and connector instances are declared, systems configurations are defined by associating pairs of specific component port to connector role. Some of Wright’s main features are the precise description of architectural structures and their abstract behavior, the ability to define architectural styles, and a set of consistency and completeness checks for architectural descriptions [Allen and Garlan 1996]. Architectural structures are obtained by description of

44

their components, connectors, and their configurations. Their abstract behavior is obtained by evaluating the computation part of components, along with the glue part of connectors. Architectural styles in Wright are described by the components and connectors that can be used in the style, along with a set of constraints specifying how these elements can be composed to build a system in that particular style [Monroe et al. 1997]. Hence, Wright allows for style-specific information checking, but does not provide any support for heterogenous styles and checking for the consequent possible mismatches. Wright provides various consistency and completeness checks [Allen and Garlan 1996]. Some of them are: port-computation consistency (ensuring that component descriptions are consistent); connector deadlock-free; roles deadlockfree; port-role compatibility (flagging invalid combinations); style constraints (making sure all predicates for that style hold); attachment completeness (any port/ role that is unattached must be able to behave as a process that simply halts).

45

46

Part III: Contribution The following sections describe our approach to answering the central dissertation question. We first describe the overall approach to extending the AAA model taken. This is followed by a discussion of the current results to date, which includes descriptions of the various styles to be covered, a discussion on relevant new conceptual features found, and a model of the various styles addressed. We then show some examples of potentially found mismatches, followed by their generalization. So far not all styles have been modeled, neither have all conceptual features they introduce. Consequently we have also included a section that points out some issues that will be relevant when expanding the model to include these other styles and their conceptual features.

47

48

3.0 Approach Description We chose to tackle the central dissertation problem by extending and generalizing the body of work started by Ahmed Abd-Allah [Abd-Allah 1996] (section 2.4). His model can distinguish between systems built using the distributed processes, event-based, layered, main-subroutine, multithreaded, pipe-and-filter, and software bus styles. The work proposed here evolves his original model to provide more complete style (and consequently COTS and GOTS packages) coverage. Each style has a very particular set of characteristics. Hence, by studying various other styles we are determining where Abd-Allah’s set of conceptual features need to be extended, such that the model can be used to distinguish between a larger number of systems1. As a natural consequence of increasing the number of conceptual features, the model can also be used to detect an increased set of potential architectural mismatches during composition. We use the blackboard, closed-loop feedback control, logic programming, real-time, rule-based, and transactional database styles. Our initial approach was to investigate the blackboard style depth-first, by working on its description and modeling it in Z2. The blackboard style suggests

1. The need to have the model reflect new conceptual features may also imply a need to modify some attributes of base elements, as well as add new constraints on them in order to depict new styles. 2. We used a plain text form of Z called ZSL [Jia 1994]. ZSL has the advantage of coming with an automated type checker (ZTC) which was used to verify the syntactic correctness of the model’s specification. For an introduction to ZSL see appendix A.

49

the addition of a new conceptual feature, which forced us to revisit the previously defined styles (see section 5.0). As a result of this modeling activity we were able to determine mismatches that could potentially occur while combining blackboard systems with other blackboard systems, or systems using any of the styles previously described by Abd-Allah. These mismatches included a subset of the ones described by Abd-Allah in table 5 on page 27, as well as some new ones (see section 7.1). We later generalized the newly found ones, and evolved Abd-Allah's table accordingly (see section 8.0). Thus, the hypothesis that the original seven conceptual features would cover the full range of architectural style mismatches appear to be false. We will fully verify this conclusion in our future work. Subsequently we examined each and every one of the styles using a breadth-next approach. The idea was to highlight the characteristics of each style that are the most relevant to composition. To this date we have compiled short descriptions of the various styles we will be addressing (see section 4.3). Some of these descriptions are clearly more mature than others---namely the closed-loop feedback control style needs a lot more work. Based on these descriptions we were able to detect some new very important conceptual features, and clearly identify some of their relevance to detecting potential mismatches, as well as determine some important issues that require further investigation (see section 10.0). In the near future, we intend to use the new set of conceptual features, to try to determine the dimensions relevant to the conceptual features space, thus

50

providing orthogonality of the various concepts involved. As well as clear guidelines on how to evolve the conceptual feature set based on the described space. It is important to note that this description shows the temporal ordering of the work to date, not the actual sequencing of their description in this document. This document has already been formatted to accommodate ease of evolution when continuing this work.

3.1 Extending the AAA Model Before going into the details of our model, we will now revisit a few points made while discussing Abd-Allah’s work (section 2.4 on page 22), that do clarify the exact evolution directions expected from Abd-Allah’s AAA model. These are: • His set of architectural base elements might remain the same, but their characteristics will change to reflect new conceptual features at the model level, in fact they have already changed at this point (section 6.0). • His set of conceptual features will be evolving considerably. These also have already evolved somewhat (section 5.0), and have very clear growth directions to include (section 10.0). • The original set of mismatches detected by his model will not only evolve to reflect the new conceptual features, but already do also include considerations about the encapsulation characteristic (section 8.0).

51

• Additionally some new bridging connectors must be added. At least shared resources do become major issues when composing any system with a realtime one (section 10.0). Based on recent feedback, we have started considering the idea of replacing Z as the underlying formalism of this model by some pre-existing ADL. This would have the added benefit of directly allowing specifications (written on the chosen ADL) to be checked for architectural mismatches, as well as undergo whatever analyses provided by the chosen ADL and its tool set. We have not yet determined whether this will happen or not. Our next step is to create a matrix of ADLs (and Z) versus features they support, to determine the natural candidate. Since it is extremely improbable that there is one single ADL that does provide everything we require, one of the features to be looked at is whether the ADL allows us to add new characteristics or not. Clearly, for the time being, the model is shown in Z.

52

4.0 Styles Descriptions This section includes descriptions of the various styles to be addressed by this work. To this date it contains some comments on the event-based style first described by Abd-Allah (section 4.1), a detailed description of the blackboard style (section 4.2), and a concise description of all others (section 4.3). The latter ones will soon be evolving.

4.1 Revisiting Event-Based As described by Abd-Allah, event-based systems: were static (allowed for no spawns); had data transfers supported by shared variables; involved some triggering capabilities; were single-threaded; were unconstrained with respect to distribution and layering; and had encapsulation. This particular representation worked very well in his case, it clearly differentiated between event-based and distributed processes. Most people tend to think of event-based systems as deviating slightly from Abd-Allah’s characterization. The usual definition differs from the one above in that event-based systems are thought of as being dynamic (allowing for spawning) and multi-threaded. Hence, this is the definition we will be using in the model from now on.

53

4.2 Blackboard The blackboard model has been very well described in the literature [Nii 1986]. Below we can find the information that is relevant for our modeling purpose. In the blackboard model, there is a central data structure which contains representations of the solution space. The domain knowledge is partitioned into independent modules of knowledge that transform information from the solution space, with the goal of reaching a solution to the problem at hand. Which module of knowledge to apply is determined dynamically, one step at a time, resulting in the incremental generation of partial solutions. The choice of a knowledge module is based on the solution state (particularly, the latest additions and modifications to the data structure containing pieces of the solution) and on the existence of knowledge modules capable of improving the current state of the solution. The blackboard model is usually described as consisting of three major components: • The knowledge sources: separate and independent modules of problemspecific knowledge. • The blackboard data structure: the problem solving state data are kept in a global database, the blackboard. This data are shared by all knowledge sources. • Control: knowledge sources respond opportunistically to changes in the blackboard. The actual locus of control is implementation dependent, it

54

can be in the knowledge sources, on the blackboard, in a separate module, or in some combination of the three. Knowledge sources produce changes to the blackboard that lead incrementally to a solution to the problem. No one source of knowledge can solve the problem by itself; the solution to the problem depends on the combined contributions of many specialists. The objective of each knowledge source is to contribute information that will lead to a solution to the problem. Cooperation is achieved by assuming that whatever information is needed is supplied by someone else. The knowledge sources and only the knowledge sources modify the blackboard. All modifications to the solution state are explicit and visible. Communication and interaction among the knowledge sources take place solely through the blackboard. The control unit does not write to the blackboard. Each knowledge source is responsible for knowing the conditions under which it can contribute to a solution. Each knowledge source has preconditions that indicate the condition on the blackboard which must exist before the body of the knowledge source is activated. The purpose of the blackboard is to hold computational and solutionstate data needed by and produced by the knowledge sources. Only the knowledge sources are allowed to make changes to the blackboard. Based on the latest changes to the information on the blackboard, a control module(s) selects and executes the next knowledge source.

55

The solution is built one step at a time. The sequence of knowledge source invocation is dynamic and opportunistic rather than fixed and pre-programmed. The knowledge sources respond opportunistically to changes in the blackboard. The control module(s) monitors the changes on the blackboard and decides what actions to take next. The control unit(s) dynamically chooses (decides) which knowledge source to activate next based on the blackboard contents, the knowledge sources’ preconditions, and some control information (such as the history of changes to the information on the blackboard). A blackboard system always terminates. One of the knowledge sources indicates when the problem-solving process is terminated, either because an acceptable solution has been found or because the system cannot continue further for lack of knowledge or data.

4.3 Characteristics of Other Styles In this section we include short descriptions of the various other styles to be covered by this work. In these, we only try to highlight the characteristics that seem relevant to composition, rather than coming up with a full description of the style. The closed-loop feedback control description needs to be evolved considerably.

4.3.1 Rule-Based This description of the rule-based style is heavily founded in the concepts described in the literature [Hayes-Roth 1985] [Rich and Knight 1991] [Shaw

56

and Garlan 1996], while focusing on the features that seem to be relevant for composition. A rule-based system is typically a single-threaded system, using a repository of shared facts (working memory) as the only means of sharing information among its various rules (i.e., there are no data connectors). Here rules are our control components, and facts our shared data. Rules have explicit preconditions that need to be matched by facts in order to permit their execution. The order in which the rules are introduced in the system determines their execution priorities. System execution follows a matchselect-execute cycle, i.e., first the interpreter determines a match by checking the rules’ preconditions against the current facts in working memory, then among all those that had their preconditions fulfilled the one with the highest priority is selected and executed. The execution of rules changes the problem solving state by changing the facts based on new knowledge. Rule-based systems may use both forward and backward chaining when trying to solve a problem. They allow for no backtracking, and they always terminate independent on whether they successfully solved the problem at hand or not.

4.3.2 Logic Programming This description of the logic programming style is heavily founded in the concepts described in the literature [Genesereth and Ginsberg 1985] [Clocksin

57

and Mellish 1987] [Rich and Knight 1991], while focusing on the features that seem to be relevant for composition. A logic programming system is typically a single-threaded system, it uses shared information on unification values as the only means of sharing information among its various rules (i.e., there are no data connectors). Here rules are our control components. Rules have head terms that need to be unified as a precondition to permit their execution. The order in which the rules are introduced in the system determines their execution priorities. System execution follows a unify-execute cycle, i.e., the interpreter tries to unify the head term of the rule, and then, if any successful unification is found, execute it. While executing, rules may invoke (or call) other rules. If some chosen unification fails when executing the rule, then the system backtracks to try for other options. Systems use backward chaining when solving problems, no forward chaining occurs. Intuition tells us that logic programming systems always terminate, though it may take it a long time to try all possible unifications first and then determine that there was none to satisfy the current goal. We still need to verify whether this is the case or not.

58

4.3.3 Transactional Database-Centric This description of the transactional database-centric style is heavily founded in the concepts described in the literature [Elmasri and Navathe 1989], while focusing on the features that seem to be relevant for composition. Transactional database-centric systems have a central repository (or database), of data that is shared among the various control components of the system. There is a database management system (DBMS), which handles concurrent accesses to data, recovery from error situations, and enforces integrity and security constraints. Thus, the DBMS takes care of maintaining data integrity. DBMSs may support for single or multiple users, and may have different locking data items granularity (field level, record level, disk block, whole file, or whole database). Databases may vary in various aspects: they may be distributed or not; they may be replicated or not; their structural organization may be relational, network, hierarchical, or object-oriented; as well as the semantics of the data they contain can be extremely diverse. Also, different databases may be managed by distinct DBMSs. Databases are persistent, kept on disk, hence data is not lost if, or when, the application terminates. Since exceptions may occur---such as transactions not being completed because of disk or computer failure, or transaction or system error---database-centric systems do support for rollback/recovery, in order to maintain data integrity, by avoiding data inconsistencies.

59

4.3.4 Real-Time This description of the real-time style is heavily founded in the concepts described in the literature [Ripps 1989] [Kurki-Suonio 1993] [Fiddler 1994] [Bihari and Gopinath 1992] [Shaw and Garlan 1996] [Stankovic 1988], while focusing on the features that seem to be relevant for composition. Real-time systems are typically multi-threaded, having threads of tasks. Some of their inputs and events arrive asynchronously, and trigger various levels of response. Very often, as a response to some event, some (or all) of the active tasks must be preempted, so that more urgent tasks can execute. CPU is not the only potential source of contention, shared resources play a very big part as well. There are implicit global data connectors, used for broadcasting relevant events, and thus supporting the preemptive behavior. Response time for certain events and components must be predictable in all cases, whether they are preempted or not. As a consequence we have that tasks have priorities associated to them, and known rates of processing and computation loads. Tasks and resources are scheduled accordingly by the operating system, or some modified version of it.

4.3.5 Closed-Loop Feedback Control This initial description of the closed-loop feedback control style is based in the concepts described in a single literature source [Shaw and Garlan

60

1996]. A more complete set of descriptive background is needed in order to approximate the description level required by this work. Closed-loop feedback control systems have a cycle involving control and/or data connectors, and/or shared data. The execution cycle never terminates1, the system continuously monitors some controlled variables, and proceeds with behavioral adaptations as needed. The controlled variables are explicitly shared data. Closed-loop feedback control systems have a set of control components for processing manipulated variables, and producing effects on controlled variables. They also have a set of control components for measuring adjustments required by controlled variables, this set of control components is also known as the controller.

1. It never terminates under normal conditions. Certainly situations such as an electric circuit burning out, or some power outage will (at least temporarily) stop the execution cycle.

61

5.0 New Conceptual Features As seen in the case of blackboard systems, some styles have the characteristic of their systems invariably terminating. Thus termination is clearly a new conceptual feature to be considered, and is extremely relevant for composition (see section 8.0). By adding a boolean attribute to control components called terminates1, whenever all control components in a system have this attribute’s value being true, we will be saying that the system terminates. Clearly this does not cover cases such as the system running into a deadlock situation, but since this is not the scope of this work, we will assume that this kind of situations will be analyzed by also using certain ADLs and tools such as Rapide [Luckham and Vera 1995]. This is a big assumption, but considering this model’s application2, the assumption is tolerable. Although we already know of many other conceptual features to be soon added (section 10.0), they are not part of the model yet, hence not discussed in this section.

1. As with all other attributes, a control component instantiation may choose to specify its value or not, i.e., it may be shown as true, false, or unspecified. 2. This model should be used for risk analysis while composing systems out of parts, preexisting or not. Pre-existing parts have already been extensively tested and used, and thus should not have such problems. Parts to be developed can have their detailed design run through Rapide or the like.

62

5.1 Styles Choices Now we need to revisit the previously described styles and determine how the new conceptual features apply to them.

5.1.1 Main-Subroutine Systems in the main-subroutine style usually terminate. A probable exception arises when we have some infinite loop in one of the control components, either main or any of the subroutines. Hence, most main-subroutine systems terminate, but the style itself is “unconstrained” with respect to termination.

5.1.2 Pipe-and-Filter An interpretation of the pipe-and-filter style analogous to that of the UNIX pipe-and-filter, yields pipe-and-filter systems that execute until they have consumed and processed all of their inputs, generating the correspondent outputs. However, a pipe-and-filter subsystem responsible for receiving telemetry from a satellite, storing the data for history purposes, testing its contents against allowable limits, and then forwarding it to a Satellite Ground Station (SGS) operator (see figure 41) is intrinsically different. Such a pipe-and-filter system never terminates, because it expects continuous inputs from the satellite. Once again, the discussion above demonstrates that the pipe-and-filter style is “unconstrained” with respect to termination.

1. This figure was part of a previous paper [Gacek 1995].

63

send_to_netw

Satellite

get_from_net send_attitude send_to_netw

Network Control

get_telemetry write_tlm_his

Telemetry History

get_telemetry send_telemet

get_telemetry send_to_satel get_network_

External Network

get_from_net

Telemetry Limits

get_telemetry

Events

send_events

get_operator get_comman

send_network read_comma

send_attitude

get_attitude_

External Tracking System

send_telemet

Encrypter Decrypter

Satellite Attitude & Control

display_io

Command Format

enc_IO

write_comma read_compon

send_attitude

Schedule Component

send_attitude

get_time

Time Router

Display

delete_comm

delete_compo write_compo

send_time

read_schedul get_sat_att_ get_operator

encr_decr_da set_key

Time

send_time

Legend

get_telemetry

Current Commands

get_cmd_stat

send_comma

Socket

read_time

read_payload

display_sche

Simulator

_IO_ get_attitude_

Payload Schedule

get_data_req add_to_histo report_status

send_comma

Figure 4: SGS Reference Architecture

Command History

display_histo data_request

get_comman

Data Routing

operator_dir

copy_to_hist

Circuit

Data Acquisition

Command Schedule

send_comma get_next_com

Task

read_time send_critical

Data Processing

64

5.1.3 Distributed Processes Just like main-subroutine, the distributed processes style is “unconstrained” with respect to termination. It is process dependent.

5.1.4 Event-Based Considering the comments on event-based systems introduced in section 4.1, we also need to revisit its choices on the AAA original seven conceptual features. Hence, now the event-based style is characterized as being: Dynamism: dynamic Supported data transfers: implicit network, shared data variables Triggering capability: yes Concurrency: multi-threaded Distribution: unconstrained Layering: unconstrained Encapsulation: yes We consider UNIX daemons [Stevens 1990] to be an example of eventbased systems, in which case they should always be running on the background, i.e., they never terminate. On the other hand, any windows session is also eventbased, just like any system that has some window interface, and both of these examples always terminate. Hence, the event-based style is “unconstrained” with respect to termination.

65

5.1.5 Blackboard Based on the description from section 4.2, one can derive the conceptual feature choices made by this style. The blackboard style is characterized as being: Dynamism: static Supported data transfers: shared repository Triggering capability: no Concurrency: single-threaded Distribution: unconstrained Layering: unconstrained Encapsulation: no We also mentioned that blackboard systems always terminate, independent on whether the problem was successfully solved or not. Hence, its choice for the termination conceptual feature is “yes”.

5.1.6 Conceptual Features Table Revisited The discussion above on the new conceptual features and the specific choices made by each style can be summarized as in table 4.

66

Styles Pipe & Filter

Main/ Subroutine

Distributed Processes

EventBased

Blackboard

Dynamism

static

static

dynamic

dynamic

static

Supported data transfers

explicit data connectors

shared data variables

explicit data connectors

implicit network, shared data variables

shared repository

Triggering capability

no

N/A

no

yes

no

Concurrency

multithreaded

singlethreaded

multithreaded

multithreaded

singlethreaded

Distribution

unconstrained

single node

multiple nodes

unconstrained

unconstrained

Layering

unconstrained

unconstrained

unconstrained

unconstrained

unconstrained

Encapsulation

no

no

no

yes

no

Termination

unconstrained

unconstrained

unconstrained

unconstrained

yes

Conceptual Features

Table 6: Current Instances in Our Architectural Style Space

67

6.0 Modeling the Styles This section contains all information relevant to the Z model, as well as the model itself. We start here by presenting the changes required by the base elements and AAA’s original model in order to accommodate the new styles and their conceptual features (section 6.1) As seen in section 6.2, we have spent some effort revisiting AbdAllah’s description of the event-based style. What we have done was to have the existence of an event manager propagate into the Z model. This actually allows for the detection of one more potential architecture compositional mismatch. Changes to the model of all other styles covered by Abd-Allah were really minor, and only required in order to reflect the changes to the underlying model described in section 6.1. The updated version of these can be found in appendix C. Finally, we present the Z models of the styles we are addressing. To this date this only includes the blackboard style (section 6.3).

6.1 Updates to the Base Elements In order to be able to model the fact that some systems always terminate, we will be adding a boolean attribute to control components called terminates. In the case of systems that always terminate, such as blackboard systems,

68

we will then have the constraint that they are composed of control components that always terminate.1 % Schema for high-level control component schema ControlComponent name : Name; ports : P Port; % Expected arguments if called or spawned arguments : seq DataType; % Type of returned values when returning from a call or spawn returnvalues : seq DataType; % Local variables locals : P DataComponent; % Local objects (given only by name - unique) localobjects : P Name; % Indicate whether it is an object method or not method : Boolean; % Indicate whether it always terminates or not terminates : Boolean; % Nodes it resides on nodes : P Node; % Resource usage resources : Resources; % Expected platform platform : Platform; end schema

We will be modelling repositories, such as the ones used by blackboards, as a set of data components that can be accessed by a set of control components and/or objects. In order to do so, we have created an equivalence definition called Repository, whose descriptions is as above, added the possibility for systems to contain any number of repositories (by changing the System schema), and altered the specifications of the previously defined styles in order to reflect the fact that they do not contain any repository in their systems (see also appendix C).

1. For a deeper discussion on this termination characteristic of systems, refer to section 5.0.

69

% SharedData is a Z abbreviation definition for a data component, and the % control components and/or objects that share it. SharedData == DataComponent +-> (P ControlComponent & P Object) % Repository is a Z abbreviation definition for a set of data components, and % the control components and/or objects that have access to it. Repository == P DataComponent +-> (P ControlComponent & P Object) % Schema for high-level system schema System name : Name; % Initially running control components initialcontrolcomponents : P ControlComponent; % Initially running data connectors initialdataconnectors : P DataConnector; % Global objects globalobjects : P Object; % All system control components, excluding object methods controlcomponents : P ControlComponent; % Allowed system classes classes : P Class; % All system shared data shareddata : SharedData; % All system repository repositories : P Repository; % All system data connectors dataconnectors : P DataConnector; % All system blocking control connectors calls : P Call; % All system non-blocking control connectors spawns : P Spawn; % System recognized messages (events) recognizedmessages : P DataComponent; % All system triggers triggers : P Trigger; % Layers with respect to calls (top, bottom) call_layers : Layers; % Layers with respect to spawns (top, bottom) spawn_layers : Layers; % Layers with respect to dataconnectors (top, bottom) dataconnector_layers : Layers; % The global attributes of the data connectors in the system dataconnectorattributes : DataConnector; % The global attributes of the control connectors in the system controlconnectorattributes : ControlConnector; % Available nodes nodes : P Node; % Resource usage resources : Resources; % Expected platform platform : Platform;

70

where % There is at least one initially running control component or global object % in the system # initialcontrolcomponents + # globalobjects >= 1; % All initially running control components belong to % declared set of control components initialcontrolcomponents subseteq controlcomponents; % All global/local objects belong to a system class forall o : Object | o in r_getallobjects(globalobjects) or o in r_getallobjects({o : Object | exists c : controlcomponents; n : Name | n in c.localobjects @ n = o.name}) @ o.class in classes; % All initially running dataconnectors belong to declared set of % dataconnectors initialdataconnectors subseteq dataconnectors; % All components connected by calls, spawns, and/or dataconnectors are % members of the system control components or of methods of global/ % local objects {c : ControlComponent | (exists call : calls @ c = call.c1 or c = call.c2) or (exists spawn : spawns @ c = spawn.c1 or c = spawn.c2) or (exists dc : dataconnectors @ c = dc.c1 or c = dc.c2)} subseteq controlcomponents setunion r_getallmethods(globalobjects) setunion r_getallmethods(r_getallobjects({o : Object | exists c : controlcomponents; n : Name | n in c.localobjects @ n = o.name})); % All objects connected by dataconnectors are global or local objects {o : Object | (exists dc : dataconnectors | dc.cc_or_obj = otype @ o = dc.o1 or o = dc.o2)} subseteq r_getallobjects(globalobjects) setunion r_getallobjects({o : Object | exists c : controlcomponents; n : Name | n in c.localobjects @ n = o.name}); % Dataconnector ports are subset of controlcomponent, method, and % (global/local) object ports {s : Port | (exists dc : dataconnectors @ s = dc.p1 or s = dc.p2)} subseteq {s : Port | (exists c : controlcomponents @ s in c.ports) or (exists c : ControlComponent | c in controlcomponents setunion r_getallmethods(globalobjects) setunion r_getallmethods(r_getallobjects({o : Object | exists c : controlcomponents; n : Name | n in c.localobjects @ n = o.name})) @ s in c.ports) or (exists o : Object | o in r_getallobjects(globalobjects) or o in r_getallobjects({o : Object | exists c : controlcomponents; n : Name | n in c.localobjects @ n = o.name}) @ s in o.ports)}; % Components sharing data are found in controlcomponents/methods and

71

% objects sharing data are found in global or local objects. forall cset : P ControlComponent; oset : P Object | (exists d : DataComponent @ (d, (cset, oset)) in shareddata) @ cset subseteq controlcomponents setunion r_getallmethods(globalobjects) setunion r_getallmethods(r_getallobjects({o : Object | exists c : controlcomponents; n : Name | n in c.localobjects @ n = o.name})) and oset subseteq r_getallobjects(globalobjects) setunion r_getallobjects({o : Object | exists c : controlcomponents; n : Name | n in c.localobjects @ n = o.name}); % All components accessing any of the repositories are found in % controlcomponents/methods, all objects accessing any of the % repositories are found in global or local objects forall cset : P ControlComponent; oset : P Object; rep : repositories | (exists dset : P DataComponent @ (dset, (cset, oset)) in rep) @ cset subseteq controlcomponents setunion r_getallmethods(globalobjects) setunion r_getallmethods(r_getallobjects({o : Object | exists c : controlcomponents; n : Name | n in c.localobjects @ n = o.name})) and oset subseteq r_getallobjects(globalobjects) setunion r_getallobjects({o : Object | exists c : controlcomponents; n : Name | n in c.localobjects @ n = o.name}); % All layers drawn from the controlcomponents & methods % Layering constraints ignore objects forall layer : Layer | layer in call_layers or layer in spawn_layers or layer in dataconnector_layers @ first layer setunion second layer subseteq controlcomponents setunion r_getallmethods(globalobjects) setunion r_getallmethods(r_getallobjects({o : Object | exists c : controlcomponents; n : Name | n in c.localobjects @ n = o.name})); % Calls constrained to between layers or not constrained at all forall call : ControlConnector | call in calls @ ((exists layer : Layer | layer in call_layers @ (call.c1 in first layer and call.c2 in second layer) or (call.c2 in first layer and call.c1 in second layer)) or (forall layer : Layer | layer in call_layers @ {call.c1, call.c2} setint second layer = {})); % Spawns constrained to between layers or not constrained at all forall spawn : ControlConnector | spawn in spawns @ ((exists layer : Layer | layer in spawn_layers @ (spawn.c1 in first layer and spawn.c2 in second layer) or (spawn.c2 in first layer and spawn.c1 in second layer)) or (forall layer : Layer | layer in spawn_layers @ {spawn.c1, spawn.c2} setint second layer = {})); % Dataconnectors constrained to between layers or not constrained at all

72

forall d : DataConnector | d in dataconnectors @ ((exists layer : Layer | layer in dataconnector_layers @ (d.c1 in first layer and d.c2 in second layer) or (d.c2 in first layer and d.c1 in second layer)) or (forall layer : Layer | layer in dataconnector_layers @ {d.c1, d.c2} setint second layer = {})); forall c : ControlComponent; threads : P Thread | % Every control component and every method is either initial, [trigger] % called, or [trigger] spawned c in controlcomponents setunion r_getallmethods(globalobjects) setunion r_getallmethods(r_getallobjects({o : Object | exists c : controlcomponents; n : Name | n in c.localobjects @ n = o.name})) and threads = {thread : Thread | (exists topcc : ControlComponent @ (topcc in initialcontrolcomponents or (exists t : triggers @ topcc in t.outspawns or topcc in t.outcalls) or (exists c1 : ControlComponent; spawn : ControlConnector | spawn in spawns @ spawn.c1 = c1 and spawn.c2 = topcc)) and thread = {x : ControlComponent | exists chain : P ControlConnector | chain subseteq calls @ dconnected (topcc, x) = {a,b : ControlComponent | exists call : ControlConnector | call in chain @ a = call.c1 and b = call.c2}})} @ (exists thread : Thread | thread in threads @ c in thread) and (forall c : ControlConnector | c in calls or c in spawns @ % Method-method calls/spawns allowed only to global objects OR % between local objects in the same controlcomponent OR % between objects in different threads ((c.c1.method = TRUE and c.c2.method = TRUE) => (c.o2 in globalobjects) or (exists cc : ControlComponent | cc in controlcomponents setunion r_getallmethods(globalobjects) setunion r_getallmethods(r_getallobjects({o : Object | exists c : controlcomponents; n : Name | n in c.localobjects @ n = o.name})) @ {c.o1.name, c.o2.name} subseteq cc.localobjects) or (exists cc1, cc2 : controlcomponents; t1, t2 : threads | cc1 /= cc2 and t1 /= t2 and cc1 in t1 and cc2 in t2 @ c.o1.name in cc1.localobjects and c.o2.name in cc2.localobjects)) and % Nonmethod-method calls/spawns allowed only to global objects % or from a controlcomponent to a local object ((c.c1.method = FALSE and c.c2.method = TRUE) => (c.o2 in globalobjects) or (c.o2.name in c.c1.localobjects)));

73

(forall t : Trigger | t in triggers and t.subtype = ctype @ % Trigger controlcomponent part of the system t.controlcomponent in controlcomponents setunion r_getallmethods(globalobjects) setunion r_getallmethods(r_getallobjects({o : Object | exists c : controlcomponents; n : Name | n in c.localobjects @ n = o.name})) and % Trigger outcalls part of the system t.outcalls subseteq controlcomponents and % Trigger outcalls part of the system t.outspawns subseteq controlcomponents and % Incoming message is a recognized message t.inmessage in recognizedmessages and % Outgoing messages are recognized messages t.outmessageset subseteq recognizedmessages and % Outcalls constrained to between layers or not constrained at all (forall c2 : ControlComponent | c2 in t.outcalls @ ((exists layer : Layer | layer in call_layers @ (t.controlcomponent in first layer and c2 in second layer) or (c2 in first layer and t.controlcomponent in second layer)) or (forall layer : Layer | layer in call_layers @ {t.controlcomponent, c2} setint second layer = {}))) and % Outspawns constrained to between layers or not constrained at all (forall c2 : ControlComponent | c2 in t.outspawns @ ((exists layer : Layer | layer in spawn_layers @ (t.controlcomponent in first layer and c2 in second layer) or (c2 in first layer and t.controlcomponent in second layer)) or (forall layer : Layer | layer in spawn_layers @ {t.controlcomponent, c2} setint second layer = {})))); (forall t : Trigger | t in triggers and t.subtype = otype @ % Trigger object part of the system t.object in r_getallobjects(globalobjects) setunion r_getallobjects({o : Object | exists c : controlcomponents; n : Name | n in c.localobjects @ n = o.name}) and % Trigger outcalls part of the system t.outcalls subseteq controlcomponents and % Trigger outcalls part of the system t.outspawns subseteq controlcomponents and % Incoming message is a recognized message t.inmessage in recognizedmessages and % Outgoing messages are recognized messages t.outmessageset subseteq recognizedmessages); % Available nodes form a superset of the connector nodes {n : Node | (exists c : ControlComponent | c in controlcomponents setunion r_getallmethods(globalobjects) setunion r_getallmethods(r_getallobjects({o : Object | exists c : controlcomponents; n : Name |

74

n in c.localobjects @ n = o.name})) @ n in c.nodes) or (exists call : ControlConnector | call in calls @ n in call.nodes) or (exists spawn : ControlConnector | spawn in spawns @ n in spawn.nodes) or (exists dc : DataConnector | dc in dataconnectors @ n in dc.nodes)} subseteq nodes; end schema

6.2 Revisiting the Event-Based Style Our version of the Event-Based style differs from that of Abd-Allah's in that: • Even though he mentioned the existence of the event manager, it did not get propagated from the textual description into the Z specification of the style. It remained implicit in his model. • We included the event manager on the Z model as being a single control component per event-based system. • We have also changed the model in order to reflect that this style is now considered multi-threaded and dynamic. • Procedure calls are now not only between procedures, but they may also involve the event manager as the caller (never the callee). • Control connectors are now not only calls, but also spawns. • In his specification, events were received directly by the system's objects, and only them. We limited the reception of events to the event manager, based upon which the manager would then issue the appropriate procedure calls/spawns.

75

Hence the new version of the Z specification for the Event-Based style is found below. % Event-Based (implicit invocation) Style global EB_Event : P DataComponent; EB_DataStructure : P DataComponent; EB_Procedure : P ControlComponent; EB_ProcedureCall : P ControlConnector; EB_ProcedureSpawn : P ControlConnector; EB_Object : P Object; EB_EventManager: P ControlComponent; EB_Trigger : P Trigger; EB_System : P System; axiom forall p : EB_Procedure @ p.locals subseteq EB_DataStructure and p.ports = {}; forall pc : EB_ProcedureCall @ % Call connects two procedures, or the event manager and a % procedure, but no procedure can call the event manager {pc.c1, pc.c2} subseteq (EB_Procedure setunion EB_EventManager) and pc.c2 notin EB_EventManager and % Procedure calls cannot be queued pc.queuesize = 0 and % The calling procedure blocks until the called procedure returns pc.blocking = TRUE; forall ps : EB_ProcedureSpawn @ % Spawn connects two procedures, or the event manager and a % procedure, but no procedure can spawn the event manager {ps.c1, ps.c2} subseteq (EB_Procedure setunion EB_EventManager) and ps.c2 notin EB_EventManager and % Procedure spawns cannot be queued ps.queuesize = 0 and % The spawning procedure does not block until the called procedure % returns ps.blocking = FALSE; forall o : EB_Object @ o.data subseteq EB_DataStructure and o.methods subseteq EB_Procedure; forall em : EB_EventManager @ em.locals subseteq EB_DataStructure; forall t : EB_Trigger @ t.subtype = ctype and % Limit reception of events to the event manager t.controlcomponent in EB_EventManager and

76

t.inmessage in EB_Event and % Allow for calls and spawns to be triggered t.outcalls subseteq EB_Procedure and t.outspawns subseteq EB_Procedure; forall s : EB_System @ s.controlcomponents subseteq (EB_Procedure setunion EB_EventManager) and s.globalobjects subseteq EB_Object and % There is exactly one event manager # {em: EB_EventManager | em in s.controlcomponents} = 1 and s.calls subseteq EB_ProcedureCall and s.spawns subseteq EB_ProcedureSpawn and s.recognizedmessages subseteq EB_Event and s.triggers subseteq EB_Trigger and s.dataconnectors = {} and s.spawn_layers = {} and s.dataconnector_layers = {} and s.shareddata = {} and s.repositories = {} and s.triggers /= {}; end axiom

As a result of those changes, we are able to detect one more architectural mismatch, namely that if we have more than one event manager, both assume that they have complete control on execution sequencing. Thus we also changed the group operation as to disallow the existence of more than one event manager in the resulting system. This enables the AAA tool to detect six rather than five of the nine architectural mismatches in the Aesop case study [Garlan et al. 1995] [AbdAllah 1996].

6.3 Blackboard Style This section contains a few considerations relevant to the model details. They are shown here with the intention of facilitating the understanding of the Z model itself.

77

The blackboard data is shared among the knowledge sources by means of the equivalence class Repository, it is not passed around. Thus there is no need for ports and/or data connectors. Also, only the control unit can activate a knowledge source, so there must be no control connectors between any pair of knowledge sources. The fact that the control unit dynamically selects and activates the knowledge source to execute next based on the blackboard contents, the knowledge sources' preconditions, and some control information means that there are no explicit triggers. As we modeled them (and as Nii described), blackboard systems are single-threaded, hence there is no need for special integrity-handling procedures. Since the repository is kept in main memory, in case of failure, all blackboard data is lost and the system must start again from the beginning. As described by Nii, the actual locus of control can be in the knowledge sources, on the blackboard, in a separate module, or in some combination of the three. We chose to model control as a single separate module, a control component. The choice of the instantiations of the base elements within our representation of the blackboard style are: • Components: Knowledge sources; blackboard data; control unit •data: blackboard data (BB_Blackboard_Data) •control: knowledge sources (BB_Ksource); control unit (BB_CtrlUnit)

78

• Objects: none • Connectors: control unit to/from knowledge sources; (blackboard data and knowledge sources communicate via the Repository equivalence) •data: none •control: control unit to/from knowledge sources (BB_Activation) • Ports: none • Triggers: none The constraints on the specific instantiations of the base elements and their occurrences on the blackboard style are listed below: • All blackboard data is part of the BB_DataStructure, as well as all of the knowledge sources and the control unit local variables. • Knowledge sources and the control unit have no ports or local objects. • All control connectors (BB_Activation) in the system connect knowledge sources and the control unit. • There is only one repository per system, the blackboard. • There is exactly one control unit per system. • There is at least one knowledge source in each system. • All of the system’s control components are either BB_Ksource or BB_CtrlUnit. • There is no control component in the system that is both a knowledge source and a control unit. • All of the system’s calls are BB_Activation.

79

• All knowledge sources in the system have control connectors connecting them to the control unit. • All knowledge sources in the system have access to the blackboard data by means of the repository. • All BB_Blackboard_Data is available to knowledge sources and the control unit via the repository. • A blackboard system always terminates, hence all of its control components must terminate. • There is no shared data other than that available via the repository. • There are no ports, objects, data connectors, or triggers. • The system is a directed graph on a star configuration (dstar), where the center is the control unit, all other nodes are knowledge sources, and the edges are system calls, BB_Activation to be more specific. % Blackboard Style global BB_DataStructure : P DataComponent; BB_Blackboard_Data : P DataComponent; BB_Ksource : P ControlComponent; BB_CtrlUnit : P ControlComponent; BB_Activation : P ControlConnector; BB_System : P System; axiom forall bdata : BB_Blackboard_Data @ bdata in BB_DataStructure; forall ksource : BB_Ksource @ ksource.ports = {} and ksource.locals subseteq BB_DataStructure and ksource.localobjects = {}; forall cunit : BB_CtrlUnit @ cunit.ports = {} and cunit.locals subseteq BB_DataStructure and cunit.localobjects = {};

80

forall a : BB_Activation @ % Activations are made from the control unit to the various knowledge % sources only. a.c1 in BB_CtrlUnit and a.c2 in BB_Ksource and % Activation calls cannot be queued a.queuesize = 0 and % The calling component, the control unit, blocks until the called % knowledge source returns a.blocking = TRUE; forall s : BB_System @ % There is exactly one blackboard repository # s.repositories = 1 and % There is exactly one control unit # {cunit : BB_CtrlUnit | cunit in s.controlcomponents} = 1 and % There is at least one knowledge source # {ksource : BB_Ksource | ksource in s.controlcomponents} >= 1 and % All knowledge sources have activation calls connecting to them (forall ksource : BB_Ksource | ksource in s.controlcomponents @ (exists a : BB_Activation @ a.c2 = ksource)) and s.globalobjects = {} and s.classes = {} and % All calls that happen within the system are activation calls s.calls subseteq BB_Activation and s.spawns = {} and s.dataconnectors = {} and s.dataconnector_layers = {} and s.spawn_layers = {} and s.shareddata = {} and s.triggers = {} and % A blackboard system always terminates, hence all of its control % components must terminate. (forall cc : ControlComponent | cc in s.controlcomponents @ cc.terminates = TRUE) and % There is only 1 initial control component, the control unit. # s.initialcontrolcomponents = 1 and (exists cunit : BB_CtrlUnit; ksource : P BB_Ksource @ s.initialcontrolcomponents = {cunit} and % All control components are either knowledge sources or the % control unit. {cunit} setunion ksource = s.controlcomponents and cunit notin ksource and % Nobody can call (activation call) the control unit not (exists call : s.calls @ call.c2 = cunit) and % The system is a directed graph on a star configuration (dstar), % where the center is the control unit, and the edges are system % calls (activation calls to be more specific). dstar(cunit, ksource) = {c1, c2 : s.controlcomponents | exists call : s.calls @ call.c1 = c1 and call.c2 = c2}) and

81

% All blackboard systems have a single thread # (getmaxthreads(s)) = 1 and % All blackboard data is visible to the control unit via the repository, all % control components that can see that data belong to the system % (i.e., they are either any of its knowledge sources or its control unit), % and no object can see the data. (forall r : s.repositories @ (forall bbdata : P DataComponent | bbdata subseteq BB_Blackboard_Data @ (exists cset : P ControlComponent; oset : P Object @ (bbdata, (cset, oset)) in r and BB_CtrlUnit subseteq cset and cset subseteq s.controlcomponents and oset = {}))); end axiom

82

7.0 Examples of Potentially Found Mismatches Here we describe some examples of mismatches that could be potentially found while composing with systems in the styles covered by this work. To this date we have only included information on composition with blackboard systems (section 7.1). This has been done in a very detailed manner. In the subsequent styles to be discussed, we will only include mismatches that were not previously described.

7.1 Composition With Blackboard Systems To get a good feeling on how Abd-Allah’s original mismatches applied to our work, and to be able to properly extend them, we did consider all mismatches potentially found while composing a blackboard system with other blackboard system, as well as with systems in any of the original AAA styles.

7.1.1 Combining Two Blackboard Subsystems • The existence of more than one control unit causes problems on deciding which knowledge source to activate next. Both control units assume they have absolute control. • By having a data connector as the bridge between the 2 subsystems we can potentially run into the situation where data is sent from a knowledge source of one subsystem to a knowledge source of the other subsystem, which is not currently active, and may never become so. This may potentially create a dead-

83

lock situation, or the loss of data. (Data connectors may be buffered or not, also they may be blocking or not (reliable sends)) • Subsystems may assume different underlying platforms. • Two knowledge source (each from one of the subsystems) handling the same piece of blackboard data. Both assumed that their control unit knew about all that wanted that data (both assume single-thread), leading to potential synchronization problems. (Abd-Allah’s mismatch number 1) • If one of the subsystems calls the other and they have a blocking data connector between them simultaneously, creates the possibility of deadlock. (AbdAllah’s mismatch number 3) • Either one of the subsystems could be layered based on calls. Depending on how a call is made from one of the subsystems to the other, we could be violating some layering constraint. (Abd-Allah’s mismatch number 4) • Both subsystems originally forbade spawns, hence if we have a spawn as a bridging connector there is potential for problems. (Abd-Allah’s mismatch number 6) • Both subsystems originally forbade data connectors, hence if we have a data connector as a bridging connector there is potential for problems. (Abd-Allah’s mismatch numbers 10) • Both subsystems originally forbade data connectors, hence if we have some triggered mechanism as a bridging connector there is potential for problems. (Abd-Allah’s mismatch numbers 12)

84

• Both subsystems are not concurrent, hence if we have a spawn as a bridging connector there is potential for problems. (Abd-Allah’s mismatch number 13) • If both subsystems reside in the same node, we may run into resources overuse. (Abd-Allah’s mismatch number 16)

7.1.2 Combining a Blackboard and a Distributed Processes Subsystems • If a knowledge source calls a process p1, p1 may then spawn p2, p1 terminates and returns, while p2 is still executing. I.e., the blackboard subsystem assumes single-thread when in reality there may be multiple ones. • By having a data connector as the bridge between the 2 subsystems we can potentially run into the situation where data is sent from a process to a knowledge source that is not currently active, and may never become so. This may potentially create a deadlock situation, or the loss of data. (Data connectors may be buffered or not, also they may be blocking or not (reliable sends)) • If bridging connector is a call from the blackboard to the distributed processes subsystem, then if the distributed processes don’t terminate and return control to the blackboard subsystem, the blackboard subsystem is in a deadlock situation. • Subsystems may assume different underlying platforms. • Knowledge sources assume that the control unit takes care of synchronization problems, but the control unit knows nothing about the processes from the distributed processes subsystem. (Abd-Allah’s mismatch number 1)

85

• Two threads (one from the blackboard and the other one of the processes from the distributed processes subsystem) have data connectors to 2 different control components in a third thread (it is impossible for the third thread to execute in the two components simultaneously). (Abd-Allah’s mismatch number 2) • If one of the subsystems calls the other and they have a blocking data connector between them simultaneously, creates the possibility of deadlock. (AbdAllah’s mismatch number 3) • Either one of the subsystems could be layered based on calls, and the distributed processes one could also be layered with basis on spawns and/or data connectors. Thus, depending on how a the bridge between the two is made, we could be violating some layering constraint. (Abd-Allah’s mismatch number 4) • The blackboard subsystem forbids spawns, hence if we have a spawn as a bridging connector from the distributed processes subsystem into the blackboard subsystem there is potential for problems. (Abd-Allah’s mismatch number 6) • The blackboard subsystem forbids spawns, hence if we have a triggered spawn as a bridging connector from the distributed processes subsystem into the blackboard subsystem there is potential for problems. (Abd-Allah’s mismatch number 8) • Both subsystems originally forbade triggering, hence if we have any triggering mechanism as a bridging connector there is potential for problems. (AbdAllah’s mismatch number 9)

86

• The blackboard subsystem forbids data connectors, hence if we have a data connector as a bridging connector from the distributed processes subsystem into the blackboard subsystem there is potential for problems. (Abd-Allah’s mismatch number 10) • The blackboard subsystem is not concurrent, hence if we have a spawn as a bridging connector from the distributed processes subsystem into the blackboard one, there is potential for problems. (Abd-Allah’s mismatch number 13) • The blackboard subsystem is not concurrent, hence if we have a triggered spawn as a bridging connector from the distributed processes subsystem into the blackboard subsystem there is potential for problems. (Abd-Allah’s mismatch number 14) • If both subsystems reside in the same node, we may run into resources overuse. (Abd-Allah’s mismatch number 16)

7.1.3 Combining a Blackboard and an Event-Based Subsystems • By having a data connector as the bridge between the 2 subsystems we can potentially run into the situation where data is sent from a knowledge source to a procedure that is not currently active (and may never become so), and viceversa. This may potentially create a deadlock situation, or the loss of data. (Data connectors may be buffered or not, also they may be blocking or not (reliable sends))

87

• If bridging connector is a call from the blackboard to the event-based subsystem, then if the event-based doesn’t terminate and return control to the blackboard subsystem, the blackboard subsystem is in a deadlock situation. • Subsystems may assume different underlying platforms. • A knowledge source from the blackboard subsystem and a procedure from the event-based subsystem handling either the same piece of blackboard data, or the same piece of shared data from the event-based subsystem. Both assumed that they had sole access to that data, leading to potential synchronization problems. One assumed that the control unit took care of this issue, and the other assumed that the event manager did. (Abd-Allah’s mismatch number 1) • If one of the subsystems calls the other and they have a blocking data connector between them simultaneously, creates the possibility of deadlock. (AbdAllah’s mismatch number 3) • Either one of the subsystems could be layered based on calls. Depending on how a call is made from one of the subsystems to the other, we could be violating some layering constraint. (Abd-Allah’s mismatch number 4) • Both subsystems originally forbade spawns, hence if we have a spawn as a bridging connector there is potential for problems. (Abd-Allah’s mismatch number 6) • It may be the case where a new trigger message is used to tell the event manager to activate some part of the blackboard subsystem. If this new trigger

88

message is not part of the previously defined set of recognized ones, we have a problem. (Abd-Allah’s mismatch number 7) • Both subsystems forbid spawns, hence if we have a triggered spawn as a bridging connector there is potential for problems. (Abd-Allah’s mismatch number 8) • The blackboard subsystem originally forbade triggering, hence if we have any triggering mechanism as a bridging connector to the blackboard subsystem there is potential for problems. (Abd-Allah’s mismatch number 9) • The blackboard subsystem originally forbade data connectors, hence if we have a data connector as a bridging connector there is potential for problems. (Abd-Allah’s mismatch numbers 10) • Both subsystems originally forbade data connectors, hence if we have some triggered mechanism as a bridging connector there is potential for problems. (Abd-Allah’s mismatch numbers 12) • Both subsystems are not concurrent, hence if we have a spawn as a bridging connector there is potential for problems. (Abd-Allah’s mismatch number 13) • Both subsystems are not concurrent, hence if we have a triggered spawn as a bridging connector there is potential for problems. (Abd-Allah’s mismatch number 14) • If both subsystems reside in the same node, we may run into resources overuse. (Abd-Allah’s mismatch number 16)

89

7.1.4 Combining a Blackboard and a Main-Subroutine Subsystems • By having a data connector as the bridge between the 2 subsystems we can potentially run into the situation where data is sent from a knowledge source to a subroutine that is not currently active (and may never become so), and viceversa. This may potentially create a deadlock situation, or the loss of data. (Data connectors may be buffered or not, also they may be blocking or not (reliable sends)) • If bridging connector is a call from the blackboard to the main-subroutine subsystem, then if the main-subroutine doesn’t terminate (say it contains an infinite loop) and return control to the blackboard subsystem, the blackboard subsystem is in a deadlock situation. • Subsystems may assume different underlying platforms. • A knowledge source from the blackboard subsystem and a procedure from the main-subroutine subsystem handling either the same piece of blackboard data, or the same piece of shared data from the main-subroutine subsystem. Both assume that they have sole access to that data, leading to potential synchronization problems.(Abd-Allah’s mismatch number 1) • If one of the subsystems calls the other and they have a blocking data connector between them simultaneously, creates the possibility of deadlock. (AbdAllah’s mismatch number 3)

90

• Either one of the subsystems could be layered based on calls. Depending on how a call is made from one of the subsystems to the other, we could be violating some layering constraint. (Abd-Allah’s mismatch number 4) • Both subsystems originally forbade spawns, hence if we have a spawn as a bridging connector there is potential for problems. (Abd-Allah’s mismatch number 6) • Both subsystems originally forbade data connectors, hence if we have a data connector as a bridging connector there is potential for problems. (Abd-Allah’s mismatch numbers 10) • Both subsystems originally forbade data connectors, hence if we have some triggered mechanism as a bridging connector there is potential for problems. (Abd-Allah’s mismatch numbers 12) • Both subsystems are not concurrent, hence if we have a spawn as a bridging connector there is potential for problems. (Abd-Allah’s mismatch number 13) • The main-subroutine subsystem is non-distributed, hence if we have a bridging connector between more than one node there is potential for problems. (AbdAllah’s mismatch number 15) • If both subsystems reside in the same node, we may run into resources overuse. (Abd-Allah’s mismatch number 16)

91

7.1.5 Combining a Blackboard and a Pipe-and-Filter Subsystems • If bridging connector is a call from the pipe-and-filter into the blackboard subsystem, then the called blackboard will assume single-thread, but other pipeand-filter components will still be executing. • By having a data connector as the bridge between the 2 subsystems we can potentially run into the situation where data is sent from a filter to a knowledge source of the blackboard subsystem, which is not currently active, and may never become so. This may potentially create a deadlock situation, or the loss of data. (Data connectors may be buffered or not, also they may be blocking or not (reliable sends)) • Subsystems may assume different underlying platforms. • Knowledge sources assume that the control unit takes care of synchronization problems, but the control unit knows nothing about the filters from the pipeand-filter subsystem. (Abd-Allah’s mismatch number 1) • Two threads (one from the blackboard and the other one of the filters from the pipe-and-filter subsystem) have data connectors to 2 different control components in a third thread (it is impossible for the third thread to execute in the two components simultaneously). (Abd-Allah’s mismatch number 2) • If one of the subsystems calls the other and they have a blocking data connector between them simultaneously, creates the possibility of deadlock. (AbdAllah’s mismatch number 3)

92

• Either one of the subsystems could be layered, the blackboard based on calls and the pipe-and-filter with basis on data connectors. Thus, depending on how a the bridge between the two is made, we could be violating some layering constraint. (Abd-Allah’s mismatch number 4) • Both subsystems originally forbade spawns, hence if we have a spawn as a bridging connector there is potential for problems. (Abd-Allah’s mismatch number 6) • Both subsystems forbid spawns, hence if we have a triggered spawn as a bridging connector there is potential for problems. (Abd-Allah’s mismatch number 8) • The blackboard subsystem originally forbade triggering, hence if we have any triggering mechanism as a bridging connector to the blackboard subsystem there is potential for problems. (Abd-Allah’s mismatch number 9) • The blackboard subsystem originally forbade data connectors, hence if we have a data connector as a bridging connector there is potential for problems. (Abd-Allah’s mismatch numbers 10) • The pipe-and-filter subsystem does not allow for shared data because of synchronization issues. If we now allow filters to access blackboard data, we may run into problems. (Abd-Allah’s mismatch number 11) • The blackboard subsystem is not concurrent, hence if we have a spawn as a bridging connector from the pipe-and-filter subsystem into the blackboard one, there is potential for problems. (Abd-Allah’s mismatch number 13)

93

• The blackboard subsystem is not concurrent, hence if we have a triggered spawn as a bridging connector from the pipe-and-filter subsystem into the blackboard subsystem there is potential for problems. (Abd-Allah’s mismatch number 14) • If both subsystems reside in the same node, we may run into resources overuse. (Abd-Allah’s mismatch number 16)

94

8.0 Newly Found Mismatches Based on the potential mismatches analysis done above, we present here a generalization of the newly found mismatches (section 8.1), followed by some style specific ones (section 8.2). In section 9.0, we show how the newly found mismatches fit into the table relating conceptual features, bridging connectors, and potential architectural mismatches, originally introduced by Abd-Allah (table 5).

8.1 Generic These mismatches were derived from looking at the blackboard style, and considerations on encapsulation. They were not present in Abd-Allah’s work. •

Mismatch Number 17: Data connectors connecting control components that are not always active may lead into deadlock or loss of data. This is a consequence of data connectors being buffered or not, and

blocking or not. In case we have a blocking data connector, the receiving control component may be inactive when data is sent through the data connector, and it may never become active (again), thus creating a deadlock on the sending control component.

95

If we have a non-blocking and non-buffered data connector, it may be the case where the receiving control component becomes active after the data was sent and lost. The only cases where there is no potential for problems are: • if both control components are running concurrently, independent on the data connector characteristics; • the data connector is non-blocking and buffered, and the receiving control component runs after the sending control component, the data will be buffered and available when the receiving control component becomes active. •

Mismatch Number 18: Erroneous assumption of single-thread. Erroneous assumption of single-thread may create problems not only

on accessing any shared data, but also on shared resources. Abd-Allah had already flagged this as a potential problem for sharing data in his mismatch number 1. Here we are also making explicit the fact that any other shared resource could now lead into contention problems. This situation can potentially happen if: • A control component c1 in a single-threaded subsystem calls a control component c2 in a multi-threaded dynamic subsystem. The problem may arise by c2 spawning c3, terminating and returning control to c1, whose subsystem assumes it is running alone.

96

• There is a spawn from a multi-threaded subsystem to a single-threaded one, the callee assumes it is running alone.



Mismatch Number 19: (Triggered) Call to a non-terminating control component. Whenever there is a call (not a spawn) from one control component to

another, if the callee does not terminate (e.g., a closed-loop feedback control system), the caller is in a deadlock situation. •

Mismatch Number 20: Erroneous assumption of same underlying platform. This situation can potentially occur when we wish to have various sub-

systems, or parts of them, residing in the same machine. It can be the case where these parts assume a different underlying platform---we cannot have the same machine satisfy both platform requirements. •

Mismatch Number 21: (Triggered) Call to a private method. Objects have public and private methods. Private methods are hidden

from the outside world, hence are only visible from within that object. •

Mismatch Number 22: (Triggered) Spawn to a private method. Objects have public and private methods. Private methods are hidden

from the outside world, hence are only visible from within that object.

97



Mismatch Number 23: Sharing private data. Objects have public and private data. Private data are hidden from the

outside world, hence are only visible from within that object.

8.2 Style Specific These mismatches are style specific, and were derived from revisiting the event-based style, and looking at the blackboard style. They were not present in Abd-Allah's work. • Event-Based Specific Mismatch There is more than one event manager. In event-based systems, the event manager is responsible for selecting the control components for execution, based on the events received. When composing with other event-based systems, the existence of more than one event manager causes problems on deciding which control component to activate next. Both event managers assume that they have complete control on execution sequencing. • Blackboard Specific Mismatch There exists more than one control unit. In blackboard systems, the control unit is responsible for maintaining the blackboard data integrity. While composing with other blackboard systems, the existence of more than one control unit causes problems on deciding which knowledge source to activate next. Both control units assume they have absolute control.

98

9.0 Revisiting the Mismatches Table Based on the newly established conceptual features (section 5.0) and mismatches described above, we can update the mismatches table accordingly (see table 7). The style specific mismatches described in section 8.2 are not represented

call spawn

6

data connector

17

10, 17

17

18

15

4

21

13

15

4

22

2,3, 17

15, 17

4, 17

17

1

15

shared data

11

triggered call

12

5,7,9

18

15

4

21

12

5,7,9

14

15

4

22

12

5,7,9

15

4

20

20

20

20

triggered spawn

8

triggered data transfer shared machine

20

16, 20

Termination

Encapsulation

Layering

Distribution

Concurrency

Bridging Connectors

Triggered

Dynamism

Conceptual Features

Data Transfers

here.

19

17

23

20

19

20

Table 7: Current Mismatches Note that the first 16 mismatches are the ones described by Abd-Allah, and the others are being introduced by this work. 1. Two concurrent threads share data, with potential synchronization problems. 2. Two threads have data connectors to 2 different control components in a third thread (it is impossible for the third thread to execute in the two components simultaneously - see figure 2 on page 27). 99

3. Two control components in the same thread share a blocking data connector, creating a possibility of deadlock. 4. A layering constraint is violated. 5. Different sets of recognized messages are used by two subsystems that permit triggers. 6. A spawn is made into a subsystem which originally forbade them. 7. An unrecognized trigger message is used. 8. A triggered spawn is made into a subsystem which originally forbade spawns. 9. A trigger refers to a subsystem which originally forbade triggering. 10. A data connector is made into a subsystem which originally forbade them. 11. A shared data relationship refers to a subsystem which originally forbade them. 12. A trigger refers to a subsystem which forbids explicit or implicit data connectors, hence the trigger may never occur. 13. A spawn is made into a subsystem which is not concurrent. 14. A triggered spawn is made into a subsystem which is not concurrent. 15. A remote connector is extended into or out of a non-distributed subsystem (i.e. a subsystem originally confined to a single node). 16. A node resource is overused (this is actually checked by summing across the subsystems’ usage of that particular resource). 17. Data connectors connecting control components that are not always active may lead into deadlock or loss of data. 18. Erroneous assumption of single-thread.

100

19. (Triggered) Call to a non-terminating control component. 20. Erroneous assumption of same underlying platform. 21. (Triggered) Call to a private method. 22. (Triggered) Spawn to a private method. 23. Sharing private data.

101

10.0 Observations on the Additional Styles By analyzing the descriptions of the additional styles yet to be covered by the model---namely rule-based, logic programming, transactional database-centric, real-time, and closed-loop feedback control (see section 4.3 on page 56)--some issues relevant to composition are immediately detected, clearly defining how this work is to evolve. Here we emphasize some of them. Real-time systems allow for preemption. When composing with nonpreemptive systems will cause problems, because the other systems’ components may continue to execute after the occurrence of an interrupt somehow related to their processing. When composing with other preemptive systems may cause problems, since events may be handled differently by the 2 subsystems (one might have a more urgent situation than the other). This clearly suggests that preemption will be another conceptual feature to be accounted for. Real-time systems require that the response time for certain events be predictable in all cases. Composition with non-real-time systems may case problems: •non-real-time systems weren’t built to survive extremely abnormal situations •non-real-time systems have no rates of processing and computation loads explicitly associated with their components •real-time systems sharing any kind of resource with any other system may lead to contention, and change some predicted response time.

102

Composition of real-time systems with other real-time systems brings up issues on how to combine their predicted response times. All of the response time issues clearly indicate that the need for predictable response times or not will be another relevant conceptual feature, just as the sharing of resources other than node (the only one addressed by Abd-Allah) is an extremely relevant bridging connector. Composition of systems which have component priorities (either implicit or explicit) may lead into problems. How do we know how components’ priorities compare across systems? This applies to the real-time, rule-based, and logic programming styles, since all of them have some form of component priorities. Once again, whether components have priorities or not is a relevant conceptual feature. Composition between a system that allows for backtracking and one that doesn’t may clearly cause problems. We may have used part of the other system (which changed the overall state) and then have to backtrack. There is no way of undoing what the other system did. This applies to the logic programming style, it is the only one to show this characteristic. Backtracking characteristics are other conceptual feature relevant for this work. Systems from styles with their roots in artificial intelligence use forward and/or backward chaining approaches to problem solving---rule-based and blackboard systems use both forward and backward chaining, whereas logic pro-

103

gramming uses only backward chaining. Further study is needed in order to determine how this characteristic impacts composition. Other differences between rule-based, blackboard, and logic programming systems are that logic programming has backtracking; and rule-based and blackboard systems have explicit preconditions to run rules, whereas logic programming uses unification of head terms for that purpose. How these differences affect composition is yet to be determined. Rule-based, blackboard, logic programming, and main-subroutine systems are examples of systems that are not reentrant. This means that at most one process can execute a specific piece of code at any given time. During composition, this could cause problems such as trying to start some non-reentrant component that is already executing. This indicates that whether a system is reentrant or not should also be considered a conceptual feature. The subject of composition of various heterogeneous databases has been widely discussed in the literature on federated database systems [Heimbigner and McLeod 1985], and some solutions to certain issues have already been proposed [Hammer and McLeod 1993]. This work will not try to replicate their results, rather try to focus on the detection of potential mismatches found when composing transactional database-centric systems with other system(s). Some compositional problems found when dealing with database-centric systems occur because of characteristics of the underlying DBMS(s), and/or the database itself. Here are some of them:

104

•Problems may arise on handling concurrent accesses to some piece of data. There must be careful communication between the DBMS of the data to be shared across systems, and the parts of the previously independent system. Whether that DBMS support single or multiple users, will have a different effect on the composition. •Meticulous attention should be given to the problem of handling error recovery. We could have the situation where while performing some transaction one system performs a successful transaction in a database pertaining to another system, and then fails. Clearly everything resulting from that transaction should be rolled-back, the problem arises on handling the roll-back of the completely successful transaction on the autonomous database. •It may not be clear how to maintain security and/or integrity constraints across systems. •Approaches to handling semantic heterogeneity may be needed [Hammer and McLeod 1993]. Further study is needed in order to determine if and how the items below can potentially impact composition with database centric systems: •differing data items granularity •databases being distributed or not •databases being replicated or not •differing structural organizations

105

106

Part IV: Conclusion The following sections conclude this document by summarizing the key contributions to be made by this work, and by introducing future directions to be taken for this dissertation, and afterwards.

107

108

11.0 Summary of Key Contributions Below is a list of some foreseen key contributions of this work. They are yet to be fully realized, but are the current goal. • Determining a strong set of conceptual features required for effectively describing and comparing architectural styles, as well as systems. • Model of architectural styles, extending the AAA model for a more complete style coverage. • Model of systems composition based on the styles’ models mentioned above. • Conceptual feature space description, providing a consolidated and more formal foundation for the model, as well as guidelines on how to evolve it. • Application of the models to a realistic problem. • CASE tool based on the above mentioned models, to be used for analyzing various systems compositions for architectural mismatches.

109

12.0 Future Directions This section describes the series of short term next steps that we will be taking in our current work, as well as suggests some directions to be pursued in the long term.

12.1 Short Term These steps are the ones to be part of this dissertation, not including future directions after its completion. • Build matrix of ADLs (and Z) versus features they support, determining the formalism to be used for our model. • If some formalism other than Z is chosen, redo the current model using the new formalism. • Complete the styles descriptions, specially the closed-loop feedback control. During this activity concentrate on determining new conceptual features that rea relevant to composition. • Model all styles, concentrating on the new conceptual feature set. • Look for relations among the various conceptual features, trying to extract the dimensions required for a conceptual feature space. • Look for relations (such as subset or special case of) among styles, e.g. closedloop and real-time; the various AI-based styles; database and blackboard. • Analyze for potential mismatches still not detected by the current model.

110

• Update the grouping operation to reflect the new features and mismatches discussed. • Work on a new version of the AAA tool, which reflects the complete new AAA model. This version is to be written in Java. • Use AAA on a real-life example containing styles or at least conceptual features newly added to the model.

12.2 Long Term These are some of the possible continuations to the body of work proposed here. • Provide for import/export from the AAA tool notation to ACME. • Study the existent ADLs, how well they support the various dimensions of the conceptual feature space, and how they could be extended for better coverage. • Add full support for behavioral characteristics. This would allow for the detection of mismatches such as generating a deadlock due to the way subsystems were composed (if no ACME interchange mechanism is present). • Reflect additional architectural views such as cost, performance, and reliability. • Propose solutions to the identified mismatches. • Create a catalog of various COTS and GOTS tools for the AAA tool to incorporate.

111

• Investigate quality related architectural attributes, and how they impact systems composition.

112

Part V: Bibliography and Appendices The bibliography used for this work is given, as well as appendices describing the formal notation used earlier and the complete AAA Z model generated by Abd-Allah [Abd-Allah 1996], and some minor changes to it. There is also an appendix covering the various acronyms used throughout this work.

113

114

13.0 Bibliography [Abd-Allah 1996] A. Abd-Allah, Composing Heterogeneous Software Architectures, Doctoral Dissertation, Center for Software Engineering, University of Southern California, August 1996 (http://sunset.usc.edu/TechRpts/dissertation.html). [Allen and Garlan 1994] R. Allen and D. Garlan, “Formalizing Architectural Connection,” in Proceedings of the 16th International Conference on Software Engineering, IEEE Computer Society Press, Sorrento, Italy, May 1994, pp. 71-80. [Allan and Garlan 1996] R. Allen and D. Garlan, The Wright Architectural Specification Language, 24 September 1996 (http://www.cs.cmu.edu/afs/cs/project/able/ ftp/wright-tr.ps). [Bihari and Gopinath 1992] T. E. Bihari and P. Gopinath, “Object-Oriented RealTime Systems: Concepts and Examples,” Computer, December 1992, pp. 25-32. [Boehm and Scherlis 1992] B. W. Boehm and W. L. Scherlis, “Megaprogramming,” Proceedings of the DARPA Software Technology Conference, April 1992 (available via USC Center for Software Engineering, Los Angeles, CA, 900890781). [Clocksin and Mellish 1987] W. F. Clocksin and C. S. Mellish, Programming in Prolog, third edition, Springer-Verlag, 1987. [Elmasri and Navathe 1989] R. Elmasri and S. B. Navathe, Fundamentals of Database Systems, Benjamin/Cunnings Publishing, 1989. [Fiddler 1994] J. Fiddler, “Hard Real-Time vs. Soft Real-Time,” UNIX Review, April 1994, pp. 47. [Gacek 1995] C. Gacek, “Exploiting Domain Architectures in Software Reuse,” in Proceedings of the ACM-SIGSOFT Symposium on Software Reusability (SSR’95), ACM Press, Seattle, Wa., 28-30 April 1995, pp. 229-232. [Gacek et al. 1995] C. Gacek, A. Abd-Allah, B. Clark, and B. Boehm, “On the Definition of Software Architecture,” in Proceedings of the First International Workshop on Architectures for Software Systems - In Cooperation with the 17th International Conference on Software Engineering, D. Garlan (ed.), Seattle, Wa., 24-25 April 1995, pp. 85-95.

115

[Garlan 1995] D. Garlan, An Introduction to the Aesop System, Carnegie Mellon University, 11 July 1995 (http://www.cs.cmu.edu/afs/cs/project/able/www/aesop/ html/aesop-overview.ps). [Garlan et al. 1995a] D. Garlan, R. Allen, and J. Ockerbloom, “Architectural Mismatch or Why it’s hard to build systems out of existing parts,” IEEE Software, November 1995, pp. 17-26. [Garlan et al. 1995b] D. Garlan, R. Monroe, and D. Wile, ACME: An Architectural Interchange Language, Technical Report CMU-CS-95-219, Carnegie Mellon University, November 1995. [Garlan et al. 1997] D. Garlan, R. Monroe, and D. Wile, ACME: An Architecture Description Interchange Language, white paper, Carnegie Mellon University, 14 January 1997 (http://www.cs.cmu.edu/afs/cs/project/able/ftp/acme-esec97.ps). [Genesereth and Ginsberg 1985] M. Genesereth and M. Ginsberg, “Logic Programming,” Communications of the ACM, vol. 28, no. 9, September 1985, pp. 933-941. [Hammer and McLeod 1993] J. Hammer and D. McLeod, “An Approach to Resolving Semantic Heterogeneity in a Federation of Autonomous, Heterogeneous Database Systems,” International Journal of Intelligent & Cooperative Information Systems, M. Papazoglou and T. Sellis (ed.), World Scientific, vol. 2, no. 1, 1993, pp. 51-83. [Kazman et al. 1997] R. Kazman, P. Clements, G. Abowd, and L. Bass, “Classifying Architectural Elements as a Foundation for Mechanism Matching,” to appear in Proceedings of COMPSAC 1997, Washington, DC, August 1997. [Kurki-Suonio 1993] R. Kurki-Suonio, “Stepwise Design of Real-Time Systems,” IEEE Transactions on Software Engineering, vol. 19, no. 1, January 1993, pp. 5669. [Jia 1994] X. Jia, “ZTC: A Type Checker for Z User’s Guide”, Department of Computer Science, DePaul University, 1994. [Hayes-Roth 1985] F. Hayes-Roth, “Rule-Based Systems,” Communications of the ACM, vol. 28, no. 9, September 1985, pp. 921-932. [Heimbigner and McLeod 1985] D. Heimbigner and D. McLeod, “A Federated Architecture for Information Management,” ACM Transactions on Office Information Systems, vol. 3, no. 3, July 1985, pp. 253-278.

116

[Luckham 1996] D. Luckham, “Rapide: A Language and Toolset for Simulation of Distributed Systems by Partial Orderings of Events,” DIMACS Partial Order Methods Workshop IV, Princeton University, July 1996 (http://anna.stanford.edu/ rapide/whats-new.html). [Luckham and Vera 1995] D. Luckham and J. Vera, “An Event-Based Architecture Definition Language,” IEEE Transactions on Software Engineering, vol. 21, no. 9, September 1995, pp. 717-734. [Magee and Kramer 1996] J. Magee and J. Kramer, “Dynamic Structure in Software Architectures,” in Proceeding of the ACM SIGSOFT’96: Fourth Symposium on the Foundations of Software Engineering (FSE4), San Francisco, CA, October 1996, pp. 24-32. [McIlroy 1969] M. D. McIlroy, “Mass Produced Software Components,” Software Engineering, NATO Science Committee, January 1969, pp. 138-155. [Medvidovic 1997] N. Medvidovic, A Classification and Comparison Framework for Software Architecture Description Languages, Technical Report UCI-ICS-9702, Department of Information and Computer Science, University of California, Irvine, CA, 92697-3425, February 1997. [Medvidovic et al. 1996] N. Medvidovic, R. N. Taylor, and E. J. Whitehead, Jr., “Formal Modeling of Software Architectures at Multiple Levels of Abstraction,” in Proceeding of the California Software Symposium 1996, Los Angeles, CA, April 1996, pp. 28-40. [MetaH 1996] ___, MetaH Language and Tools, 31 December 1996 (http:// www.htc.honeywell.com/projects/dssa/dssa_tools/dssa_tools_mh.html). [Monroe and Garlan 1996] R. Monroe and D. Garlan, “Style-Based Reuse for Software Architectures,” in Proceedings of the Fourth International Conference on Software Reuse, Orlando, Fl., 23-26 April 1996. [Monroe et al. 1997] R. T. Monroe, A. Kompanek, R. Melton, and D. Garlan, “Architectural Styles, Design Patterns, and Objects,” IEEE Software, January 1997, pp. 43-52. [Moriconi and Riemenschneider 1997] M. Moriconi R. A. Riemenschneider, Introduction to SADL 1.0---A Language for Specifying Software Architecture Hierarchies, Technical Report SRI-CSL-97-01, Computer Science Laboratory, SRI International, March 1997 (http://www.csl.sri.com/sadl/sadl-intro.ps.gz).

117

[Moriconi et al. 1995] M. Moriconi, X. Qian, and R. A. Riemenschneider, “Correct Architecture Refinement,” IEEE Transactions on Software Engineering, vol. 21, no. 4, April 1995, pp. 356-372. [Nii 1986] H. Nii, “Blackboard Systems - Parts 1 and 2,” AI Magazine, vol. 7, no. 3 (pp. 38-53), and no. 4 (pp. 62-69), 1986. [Perry and Wolf 1992] D. E. Perry and A. L. Wolf, “Foundations for the Study of Software Architecture,” ACM Software Engineering Notes, vol. 17. no. 4, October 1992, pp. 40-52. [Prieto-Diaz and Freeman 1987] R. Prieto-Diaz and P. Freeman, “Classifying Software for Reusability,” IEEE Software, January 1987, pp. 6-16. [Pyle et al. 1993] I. Pyle, P. Hruschka, M. Lissandre and K. Jackson, Real-Time Systems---Investigating Industrial Practice, John Wiley & Sons Ltd., England, 1993. [Radice and Phillips 1988] R. A. Radice and R. W. Phillips, Software Engineering--An Industrial Approach, vol. 1, Prentice Hall, 1988. [Rapide 1996] ___, Guide to the Rapide 1.0 Language Reference Manuals, Stanford University, 5 December 1996 (http://anna.stanford.edu/rapide/lrms/overview.ps). [Rich and Knight 1991] E. Rich and K. Knight, Artificial Intelligence, second edition, McGraw-Hill, 1991. [Ripps 1989] D. L. Ripps, An Implementation Guide to Real-Time Programming, Yourdon Press, 1989. [Shaw and Clements 1997] M. Shaw and P. Clements, “A Field Guide to Boxology: Preliminary Classification of Architectural Styles for Software Systems,” to appear in Proceedings of COMPSAC 1997, Washington, DC, August 1997 (http:// www.cs.cmu.edu/afs/cs.cmu.edu/project/vit/www/paper_abstracts/Boxology.html) [Shaw and Garlan 1996] M. Shaw and D. Garlan, Software Architectures---Perspectives on an Emerging Discipline, Prentice Hall, 1996. [Shaw et al. 1995] M. Shaw, R. DeLine, D. V. Klein, T. L. Ross, D. M. Young, and G. Zelesnik, “Abstractions for Software Architecture and Tools to Support Them,” IEEE Transactions on Software Engineering, vol. 21. no. 4, April 1995, pp. 314335.

118

[Spivey 1992] J. Spivey, The Z Notation, Prentice Hall, 1992. [Stankovic 1988] J. Stankovic, “Misconceptions About Real-Time Computing---A Serious Problem for Next-Generation Systems,” Computer, October 1988, pp. 1019. [Stevens 1990] W. R. Stevens, UNIX Network Programming, Prentice Hall, 1990. [Tracz 1994] W. Tracz, “Domain-Specific Software Architecture Frequently Asked Questions,” ACM Software Engineering Notes, vol. 9. no. 2, April 1994, pp. 52-56. [Vestal 1997] S. Vestal, MetaH Programmer’s Manual, Version 1.14, Technical Report Honeywell Technology Center, 7 March 1997. [Zelesnik 1996] G. Zelesnik, The UniCon Language Reference Manual, Carnegie Mellon University, 13 May 1996 (http://www.cs.cmu.edu/~UniCon/referencemanual/Reference_Manual_1.html).

119

120

14.0 Appendices

Appendix A: Introduction to the ZSL Notation This is a very brief introduction to Z and ZSL. Z is a formal notation for specifying software systems, based on first order logic and set theory. It uses certain graphical constructs as part of the notation. For this reason, ZSL was invented: it is a purely textual form of Z. ZSL does not add anything to Z beyond an ASCII interface.

Given Sets Sometimes it is not necessary to give a detailed specification of items that we are trying to model. In that case, the items can be captured by given sets. [Name, BasicUnit, Book, Human]

Z comes with some built-in given sets, namely the integers, natural numbers, and whole numbers. [Z, N, N1] % integers, natural numbers, whole numbers respectively

To represent set membership: 3 in N -3 notin N1

121

Types We can use given sets in declarations of variables to act as the type of the variable. Types can also be drawn from other Z constructs (e.g. schemas). nameofsystem : Name population : N

Building Sets We sometimes want to build sets out of other types. names : P Name % a set of names nameandages : P (Name cross Z) % a set of binary tuples - name with integers nameandages2 : Name Z % the same as the previous: it is a relation humantoage : Name --> Z % a relation which is also a function

Predicates (Constraints) First order predicates are supported in Z. forall n : N1 | n in setofbignumbers @ n > 1000 % some set of big numbers all have numbers greater than 1000 exists min : N1 | min in setofbignumbers @ forall n : setofbignumbers @ min 100 population < 6000000000 end axiom

The list of axioms is an implicit conjunction.

Schemas The basic unit for capturing state in Z is the schema. Schemas have two parts: a signature which captures attributes, and a property which captures constraints about the attributes in the signature. schema Car type : CarType passengers : P Name wheels : N1 where # passengers < 6 % the cardinality of the set passengers is less than 6 wheels 1 and dom edges = nodes and ran edges = nodes and (forall a, b : nodes @ uconnected (a,b) = edges))

125

% all nodes are connected to each other or (#nodes = 0 or #nodes = 1)) % trivial case: a graph of zero or one node end generic generic [X] cdgraph : (X & P X) (X X) % true iff a directed graph is connected with respect to a given `root’ node (where the graph is represented as a set of nodes and a set of edges) where forall root : X; nodes : P X; edges : X X | root in nodes @ cdgraph (root, nodes) = edges ((#nodes > 1 and dom edges = nodes and ran edges = nodes and (forall a : nodes @ dconnected (root, a) = edges)) % all nodes are connected to the root or (#nodes = 0 or #nodes = 1)) % trivial case: a graph of zero or one node end generic generic [X] utree : P X (X X) % true iff an undirected graph is a tree (where the graph is represented as a set of nodes and a set of edges) where forall nodes : P X; edges : X X @ utree nodes = edges ((#nodes > 1 and dom edges = nodes and ran edges = nodes and #edges = #nodes - 1 and (forall a, b : nodes @ uconnected (a,b) = edges)) % the number of edges is one less than the number of nodes, and all nodes are connected to each other or (#nodes = 0 or #nodes = 1)) % trivial case: a tree of zero or one node end generic generic [X] dtree : (X & P X) (X X) % true iff a directed graph is a tree with respect to a given `root’ node (where the graph is represented as a set of nodes and a set of edges) where forall root : X; nodes : P X; edges : X X | root in nodes @ dtree (root, nodes) = edges ((#nodes > 1 and dom edges = nodes and ran edges = nodes and #edges = #nodes - 1 and (forall a : nodes @ dconnected (root, a) = edges)) % the number of edges is one less than the number of nodes, and all

126

nodes are connected to the root or (#nodes = 0 or #nodes = 1)) % trivial case: a tree of zero or one node end generic generic [X] ustar : P X (X X) % true iff an undirected graph is a star where forall nodes : P X; edges : X X @ ustar nodes = edges ((utree nodes = edges) and (exists center : X @ #nodes > 1 => (forall a,b : X | (a,b) in edges @ a = center or b = center))) % the graph is a tree, and one node is found in all the edges end generic generic [X] dstar : (X & P X) (X X) % true iff a directed graph is a star where forall center : X; nodes : P X; edges : X X | center in nodes @ dstar (center, nodes) = edges ((dtree (center, nodes) = edges) and #nodes > 1 => (forall a,b : X | (a,b) in edges @ a = center)) % the graph is a tree, and one node is found in all the edges (the root) end generic generic [X] uring : P X (X X) % true iff an undirected graph is a ring where forall nodes : P X; edges : X X @ uring nodes = edges ((#nodes > 2 and dom edges = nodes and ran edges = nodes and #edges = #nodes and (forall a : nodes @ #{x, y : X | (x,y) in edges and (x=a or y=a)} = 2)) % the number of edges is equal to the number of nodes, and each node is found in 2 edges or (#nodes = 0 or #nodes = 1 or #nodes = 2)) % trivial case: a ring of zero, one, or two nodes end generic generic [X] ufullyconnectedgraph : P X (X X) % true iff an undirected graph is fully connected

127

where forall nodes : P X; edges : X X @ ufullyconnectedgraph nodes = edges ((#nodes > 1 and dom edges = nodes and ran edges = nodes and #edges = (#nodes * (#nodes - 1)) div 2 and (forall a,b : nodes @ (a,b) in edges or (b,a) in edges)) % the number of edges is equal to the number of nodes multiplied by the same minus one, all divided by two, and an edge exists between all pairs of nodes or (#nodes = 0 or #nodes = 1)) % trivial case: a fully connected graph of zero or one node end generic [CpuType, DistributedCommunicationMechanismType, OperatingSystemType, GraphicalUserInterfaceType, ImplementationLanguageType] % sets of platform options global sparc, i80x86, m680x0, powerpc : CpuType; rpc, messages, sharedmemory : DistributedCommunicationMechanismType; sunos, solaris, aix, windows3, windows95, dos, os2, system7, vms : OperatingSystemType; xwindowsgui, windows3gui, windows95gui, system7gui, os2gui : GraphicalUserInterfaceType; c, cplusplus, ada, pascal, prolog, lisp, fortran, cobol, smalltalk, basic : ImplementationLanguageType; end global % partial listing of the possible platform options [VendorType, VersionType] schema PlatformOption [X] type : X; vendor : VendorType; version : VersionType; end schema

% schema for platform options schema Platform cpumodel : PlatformOption[CpuModelType]; discommmech : PlatformOption[DistributedCommunicationMechanismType]; language : PlatformOption[ImplementationLanguageType]; os : PlatformOption[OperatingSystemType]; gui : PlatformOption[GraphicalUserInterfaceType]; end schema %% inrel PlatformCompatible

128

global _ PlatformCompatible _ : Platform Platform; % determine if two platforms are compatible with each other axiom forall p1, p2 : Platform @ p1 PlatformCompatible p2 p1.cpumodel = p2.cpumodel and p1.discommmech = p2.discommmech and p1.language = p2.language and p1.os = p2.os and p1.gui = p2.gui; end axiom schema Node platform : Platform; end schema Percent == {n : N | n addResources inputset = NoResources) and (inputset = {r1} => addResources inputset = r1) and (({r1, r2} subseteq inputset and r3 notin inputset) => addResources(inputset) = addResources((inputset \ {r1, r2}) setunion {r3}) and r3.sloc = r1.sloc + r2.sloc and r3.datasize = r1.datasize + r2.datasize and r3.codesize = r1.codesize + r2.codesize and r3.cpuload = r1.cpuload + r2.cpuload and r3.mainmemory = r1.mainmemory + r2.mainmemory and r3.networkbandwidth = r1.networkbandwidth + r2.networkbandwidth); forall r_actual, r_limits : Resources @ r_actual ResourceCompatible r_limits r_actual.sloc c2 in o2.methods; % if either component is a method, it belongs to the respective object ((p1.iotype = io_in and p2.iotype = io_out) or (p1.iotype = io_in and p2.iotype = io_inout) or

133

(p1.iotype = io_inout and p2.iotype = io_inout) or (p2.iotype = io_in and p1.iotype = io_out) or (p2.iotype = io_in and p1.iotype = io_inout)); % allowable port combinations: in - out, inout - inout, in - inout {n : Node | n in c1.nodes or n in c2.nodes or n in o1.nodes or n in o2.nodes} subseteq nodes; % the connector nodes form a superset of the component/object nodes end schema

% schema for high-level control connector schema ControlConnector name : Name; c1, c2 : ControlComponent; % connected control components o1, o2 : Object; % connected objects (if the control components are methods) arguments : seq DataType; % arguments passed in during a call or spawn (if any) returnvalues : seq DataType; % values when returning from a call or spawn (if any) rate : N1; % maximum transfer rate queuesize : N; % queuesize - 0 if connector does not queue requests blocking : Boolean; % true if the transfer blocks waiting for a response reliable : Boolean; % true if each transfer is reliably sent nodes : P Node; % nodes it resides on resources : Resources; % resource usage platform : Platform; % expected platform where {n : Node | n in c1.nodes or n in c2.nodes} subseteq nodes; % the connector nodes form a superset of the component nodes c1.method = TRUE c1 in o1.methods and c2.method = TRUE c2 in o2.methods; % if either component is a method, it belongs to the respective object arguments = c2.arguments; returnvalues = c2.returnvalues; end schema Call == {c : ControlConnector | c.blocking = TRUE} Spawn == {c : ControlConnector | c.blocking = FALSE} axiom forall c : Spawn @ c.c1.method = FALSE and c.c2.method = FALSE; % impose artificial constraint: no spawns to/from object methods

134

end axiom

% schema for high-level trigger schema Trigger name : Name; subtype : COsubtype; % indicate if an object or a control component is being connected controlcomponent : ControlComponent; % the control component which receives the data message object : Object; % the object which receives the data message inmessage : DataComponent; % the input message inports : P Port; % the input port which the message come in over outports : P Port; % the output ports for any outgoing messages outmessageset : P DataComponent; % the set of triggered outgoing messages outcalls : P ControlComponent; % the set of triggered calls outspawns : P ControlComponent; % the set of triggered spawns where forall s : Port | s in inports @ s.iotype = io_in or s.iotype = io_inout; % in ports accept input forall s : Port | s in outports @ s.iotype = io_out or s.iotype = io_inout; % out ports allow output subtype = ctype => inports setunion outports subseteq controlcomponent.ports and controlcomponent.method = FALSE; % if the trigger is for a control component, the ports are indeed found in the specified control component, and it is not a method subtype = otype => inports setunion outports subseteq object.ports and outcalls subseteq object.methods and outspawns = {}; % if the trigger is for an object, the ports are indeed found in the specified object. Calls are to object methods, and no spawns are allowed of object methods (artificial constraint). end schema Layer == P ControlComponent & P ControlComponent % Layer is a Z abbreviation definition for two sets of control components (top half and bottom half of layer) Layers == P ControlComponent P ControlComponent % An abbreviation definition for a set of layers

135

Thread == P ControlComponent % A thread is a set of control components that are presumably connected by calls (not spawns). “Thread” should only be used in the proper context otherwise use “P ControlComponent”.

% schema for high-level system schema System name : Name; initialcontrolcomponents : P ControlComponent; % initially running control components initialdataconnectors : P DataConnector; % initially running data connectors globalobjects : P Object; % global objects controlcomponents : P ControlComponent; % all system control components, excluding object methods classes : P Class; % allowed system classes shareddata : DataComponent +-> (P ControlComponent & P Object); % all system shared data dataconnectors : P DataConnector; % all system data connectors calls : P Call; % all system blocking control connectors spawns : P Spawn; % all system non-blocking control connectors recognizedmessages : P DataComponent; % system recognized messages (events) triggers : P Trigger; % all system triggers call_layers : Layers; % layers with respect to calls (top, bottom) spawn_layers : Layers; % layers with respect to spawns (top, bottom) dataconnector_layers : Layers; % layers with respect to dataconnectors (top, bottom) dataconnectorattributes : DataConnector; % the global attributes of the data connectors in the system controlconnectorattributes : ControlConnector; % the global attributes of the control connectors in the system nodes : P Node; % available nodes resources : Resources; % resource usage platform : Platform; % expected platform where # initialcontrolcomponents + # globalobjects >= 1; % there is at least one initially running control component or global object in the system initialcontrolcomponents subseteq controlcomponents;

136

% all initially running control components belong to declared set of control components forall o : Object | o in r_getallobjects(globalobjects) or o in r_getallobjects({o : Object | exists c : controlcomponents;n : Name | n in c.localobjects @ n = o.name}) @ o.class in classes; % all global/local objects belong to a system class initialdataconnectors subseteq dataconnectors; % all initially running dataconnectors belong to declared set of dataconnectors {c : ControlComponent | (exists call : calls @ c = call.c1 or c = call.c2) or (exists spawn : spawns @ c = spawn.c1 or c = spawn.c2) or (exists dc : dataconnectors @ c = dc.c1 or c = dc.c2)} subseteq controlcomponents setunion r_getallmethods(globalobjects) setunion r_getallmethods(r_getallobjects({o : Object | exists c : controlcomponents; n : Name | n in c.localobjects @ n = o.name})); % all components connected by calls, spawns, and/or dataconnectors are members of the system control components or of methods of global/ local objects {o : Object | (exists dc : dataconnectors | dc.cc_or_obj = otype @ o = dc.o1 or o = dc.o2)} subseteq r_getallobjects(globalobjects) setunion r_getallobjects({o : Object | exists c : controlcomponents; n : Name | n in c.localobjects @ n = o.name}); % all objects connected by dataconnectors are global or local objects {s : Port | (exists dc : dataconnectors @ s = dc.p1 or s = dc.p2)} subseteq {s : Port | (exists c : controlcomponents @ s in c.ports) or (exists c : ControlComponent | c in controlcomponents setunion r_getallmethods(globalobjects) setunion r_getallmethods(r_getallobjects({o : Object | exists c : controlcomponents; n : Name | n in c.localobjects @ n = o.name})) @ s in c.ports) or (exists o : Object | o in r_getallobjects(globalobjects) or o in r_getallobjects({o : Object | exists c : controlcomponents; n : Name | n in c.localobjects @ n = o.name}) @ s in o.ports)}; % dataconnector ports are subset of controlcomponent, method, and (global/local) object ports forall cset : P ControlComponent; oset : P Object | (exists d : DataComponent @ (d, (cset, oset)) in shareddata) @ cset subseteq controlcomponents setunion r_getallmethods(globalobjects) setunion r_getallmethods(r_getallobjects({o : Object | exists c : controlcomponents; n : Name | n in c.localobjects @ n = o.name})) and oset subseteq r_getallobjects(globalobjects) setunion

137

r_getallobjects({o : Object | exists c : controlcomponents; n : Name | n in c.localobjects @ n = o.name}); % components sharing data are found in controlcomponents/methods and objects sharing data are found in global or local objects % layering constraints currently ignore objects forall layer : Layer | layer in call_layers or layer in spawn_layers or layer in dataconnector_layers @ first layer setunion second layer subseteq controlcomponents setunion r_getallmethods(globalobjects) setunion r_getallmethods(r_getallobjects({o : Object | exists c : controlcomponents; n : Name | n in c.localobjects @ n = o.name})); % all layers drawn from the controlcomponents & methods forall call : ControlConnector | call in calls @ ((exists layer : Layer | layer in call_layers @ (call.c1 in first layer and call.c2 in second layer) or (call.c2 in first layer and call.c1 in second layer)) or (forall layer : Layer | layer in call_layers @ {call.c1, call.c2} setint second layer = {})); % calls constrained to between layers or not constrained at all forall spawn : ControlConnector | spawn in spawns @ ((exists layer : Layer | layer in spawn_layers @ (spawn.c1 in first layer and spawn.c2 in second layer) or (spawn.c2 in first layer and spawn.c1 in second layer)) or (forall layer : Layer | layer in spawn_layers @ {spawn.c1, spawn.c2} setint second layer = {})); % spawns constrained to between layers or not constrained at all forall d : DataConnector | d in dataconnectors @ ((exists layer : Layer | layer in dataconnector_layers @ (d.c1 in first layer and d.c2 in second layer) or (d.c2 in first layer and d.c1 in second layer)) or (forall layer : Layer | layer in dataconnector_layers @ {d.c1, d.c2} setint second layer = {})); % dataconnectors constrained to between layers or not constrained at all forall c : ControlComponent; threads : P Thread | c in controlcomponents setunion r_getallmethods(globalobjects) setunion r_getallmethods(r_getallobjects({o : Object | exists c : controlcomponents; n : Name | n in c.localobjects @ n = o.name})) and threads = {thread : Thread | (exists topcc : ControlComponent @ (topcc in initialcontrolcomponents or (exists t : triggers @ topcc in t.outspawns or topcc in t.outcalls) or (exists c1 : ControlComponent; spawn : ControlConnector | spawn in spawns @ spawn.c1 = c1

138

and spawn.c2 = topcc)) and thread = {x : ControlComponent | exists chain : P ControlConnector | chain subseteq calls @ dconnected (topcc, x) = {a,b : ControlComponent | exists call : ControlConnector | call in chain @ a = call.c1 and b = call.c2}})} @ (exists thread : Thread | thread in threads @ c in thread) and % every control component and every method is either initial, [trigger] called, or [trigger] spawned (forall c : ControlConnector | c in calls or c in spawns @ ((c.c1.method = TRUE and c.c2.method = TRUE) => (c.o2 in globalobjects) or (exists cc : ControlComponent | cc in controlcomponents setunion r_getallmethods(globalobjects) setunion r_getallmethods(r_getallobjects({o : Object | exists c : controlcomponents; n : Name | n in c.localobjects @ n = o.name})) @ {c.o1.name, c.o2.name} subseteq cc.localobjects) or (exists cc1, cc2 : controlcomponents; t1, t2 : threads | cc1 /= cc2 and t1 /= t2 and cc1 in t1 and cc2 in t2 @ c.o1.name in cc1.localobjects and c.o2.name in cc2.localobjects)) and % method-method calls/spawns allowed only to global objects OR between local objects in the same controlcomponent OR between objects in different threads ((c.c1.method = FALSE and c.c2.method = TRUE) => (c.o2 in globalobjects) or (c.o2.name in c.c1.localobjects))); % nonmethod-method calls/spawns allowed only to global objects or from a controlcomponent to a local object (forall t : Trigger | t in triggers and t.subtype = ctype @ t.controlcomponent in controlcomponents setunion r_getallmethods(globalobjects) setunion r_getallmethods(r_getallobjects({o : Object | exists c : controlcomponents; n : Name | n in c.localobjects @ n = o.name})) and % trigger controlcomponent part of the system t.outcalls subseteq controlcomponents and % trigger outcalls part of the system t.outspawns subseteq controlcomponents and % trigger outcalls part of the system t.inmessage in recognizedmessages and % incoming message is a recognized message t.outmessageset subseteq recognizedmessages and % outgoing messages are recognized messages (forall c2 : ControlComponent | c2 in t.outcalls @ ((exists layer : Layer | layer in call_layers @ (t.controlcomponent in first layer and c2 in second layer) or (c2 in first layer and t.controlcomponent in second layer)) or

139

(forall layer : Layer | layer in call_layers @ {t.controlcomponent, c2} setint second layer = {}))) and % outcalls constrained to between layers or not constrained at all (forall c2 : ControlComponent | c2 in t.outspawns @ ((exists layer : Layer | layer in spawn_layers @ (t.controlcomponent in first layer and c2 in second layer) or (c2 in first layer and t.controlcomponent in second layer)) or (forall layer : Layer | layer in spawn_layers @ {t.controlcomponent, c2} setint second layer = {})))); % outspawns constrained to between layers or not constrained at all (forall t : Trigger | t in triggers and t.subtype = otype @ t.object in r_getallobjects(globalobjects) setunion r_getallobjects({o : Object | exists c : controlcomponents; n : Name | n in c.localobjects @ n = o.name}) and % trigger object part of the system t.outcalls subseteq controlcomponents and % trigger outcalls part of the system t.outspawns subseteq controlcomponents and % trigger outcalls part of the system t.inmessage in recognizedmessages and % incoming message is a recognized message t.outmessageset subseteq recognizedmessages); % outgoing messages are recognized messages {n : Node | (exists c : ControlComponent | c in controlcomponents setunion r_getallmethods(globalobjects) setunion r_getallmethods(r_getallobjects({o : Object | exists c : controlcomponents; n : Name | n in c.localobjects @ n = o.name})) @ n in c.nodes) or (exists call : ControlConnector | call in calls @ n in call.nodes) or (exists spawn : ControlConnector | spawn in spawns @ n in spawn.nodes) or (exists dc : DataConnector | dc in dataconnectors @ n in dc.nodes)} subseteq nodes; % available nodes form a superset of the connector nodes end schema

% unique name constraints axiom forall p1, p2 : Port @ p1.name = p2.name => p1 = p2; forall d1, d2 : DataComponent @ d1.name = d2.name => d1 = d2; forall c1, c2 : ControlComponent @ c1.name = c2.name => c1 = c2; forall d1, d2 : DataConnector @ d1.name = d2.name => d1 = d2; forall c1, c2 : ControlConnector @ c1.name = c2.name => c1 = c2; forall o1, o2 : Object @ o1.name = o2.name => o1 = o2; forall t1, t2 : Trigger @ t1.name = t2.name => t1 = t2; forall s1, s2 : System @ s1.name = s2.name => s1 = s2; end axiom global

140

getmaxthreads : System +-> P Thread; % retrieve maximum number of different threads in a system % Assumes that objects do not start out executing any method concurrently axiom forall system : System; threads : P Thread @ getmaxthreads(system) = threads (forall thread : Thread | thread in threads @ (exists topcc : ControlComponent @ (topcc in system.initialcontrolcomponents or (exists t : system.triggers @ topcc in t.outspawns or topcc in t.outcalls) or (exists c1 : ControlComponent; spawn : ControlConnector | spawn in system.spawns @ spawn.c1 = c1 and spawn.c2 = topcc)) and thread = {x : ControlComponent | exists chain : P ControlConnector | chain subseteq system.calls @ dconnected (topcc, x) = {a,b : ControlComponent | exists call : ControlConnector | call in chain @ a = call.c1 and b = call.c2}})); end axiom

% three weakly constrained styles global SoftwareBusSystems : P System; DistributedSystems : P System; MultithreadedSystems : P System; axiom forall s : System | s in SoftwareBusSystems @ (ustar s.controlcomponents = {x, y : ControlComponent | exists d : DataConnector @ d in s.dataconnectors and d.c1 = x and d.c2 = y}) and (# s.dataconnectors = # s.controlcomponents - 1); % dataconnectors form a star (center/bus distributes messages) forall s : System | s in DistributedSystems @ # {n : Node | (exists c : ControlComponent | c in s.controlcomponents @ n in c.nodes) or (exists call : ControlConnector | call in s.calls @ n in call.nodes) or (exists spawn : ControlConnector | spawn in s.spawns @ n in spawn.nodes) or (exists dc : DataConnector | dc in s.dataconnectors @ n in dc.nodes)} > 1; % the system rests on more than one node forall s : System | s in MultithreadedSystems @ # (getmaxthreads(s)) > 1; % the maximum number of possible threads is greater than one end axiom % Pipe & Filter Style

141

global PF_Socket : P Port; PF_Pipe : P DataConnector; PF_Filter : P ControlComponent; PF_System : P System; axiom forall s : PF_Socket @ s.iotype /= io_inout and % no socket is used for both input and output s.streaming = TRUE; % all data transfers are streamed forall p : PF_Pipe @ p.cc_or_obj = ctype and % pipes always connect filters and not objects p.directionality = forward and % unidirectional {p.c1, p.c2} subseteq PF_Filter and % pipe connects two filters {p.p1, p.p2} subseteq PF_Socket and % ports belong to the P/F style p.p1.iotype = io_out and p.p2.iotype = io_in and % p1 acts as sender, p2 acts as receiver p.p1 /= p.p2; % the sender socket is different than the receiver forall f : PF_Filter @ f.ports subseteq PF_Socket and % ports belong to the P/F style f.localobjects = {}; forall s : PF_System @ s.controlcomponents subseteq PF_Filter and s.dataconnectors subseteq PF_Pipe and s.globalobjects = {} and s.classes = {} and s.calls = {} and s.spawns = {} and s.shareddata = {} and s.call_layers = {} and s.spawn_layers = {} and s.triggers = {} and s.initialcontrolcomponents = s.controlcomponents and s.initialdataconnectors = s.dataconnectors and (forall p : s.dataconnectors @ exists f1, f2 : s.controlcomponents @ p.p1 in f1.ports and p.p2 in f2.ports) and % all pipe sockets connect filter sockets (forall p1, p2 : s.dataconnectors @ ((p1.p1 = p2.p1 and p1.p2 = p2.p2) => p1 = p2)); % no two pipes connect the same sender and receiver end axiom

% Main/Subroutine Style

142

global MS_DataStructure : P DataComponent; MS_Procedure : P ControlComponent; MS_ProcedureCall : P ControlConnector; MS_System : P System; axiom forall p : MS_Procedure @ p.ports = {} and p.locals subseteq MS_DataStructure and p.localobjects = {}; forall pc : MS_ProcedureCall @ {pc.c1, pc.c2} subseteq MS_Procedure and % call connects two procedures pc.queuesize = 0 and % procedure calls cannot be queued pc.blocking = TRUE; % the calling procedure blocks until the called procedure returns forall s : MS_System @ s.controlcomponents subseteq MS_Procedure and dom s.shareddata subseteq MS_DataStructure and s.calls subseteq MS_ProcedureCall and s.globalobjects = {} and s.classes = {} and s.spawns = {} and s.dataconnectors = {} and s.spawn_layers = {} and s.dataconnector_layers = {} and s.triggers = {} and # s.initialcontrolcomponents = 1 and # (getmaxthreads(s)) = 1 and % all M/S systems have a single thread (exists main : MS_Procedure; subroutines : P MS_Procedure @ s.initialcontrolcomponents = {main} and {main} setunion subroutines = s.controlcomponents and main notin subroutines and (forall call : s.calls @ call.c2 /= main) and cdgraph (main, subroutines) = {c1, c2 : MS_Procedure | exists call : s.calls @ call.c1 = c2 and call.c2 = c2}) and % system forms a connected, directed graph of calls starting from main # {n : Node | (exists c : ControlComponent | c in s.controlcomponents @ n in c.nodes) or (exists call : ControlConnector | call in s.calls @ n in call.nodes)} = 1; % the system rests on one node end axiom

% Distributed Processes Style global DP_DataStructure : P DataComponent; DP_Socket : P Port;

143

DP_Process : P ControlComponent; DP_Circuit : P DataConnector; DP_ProcessCall : P ControlConnector; DP_ProcessSpawn : P ControlConnector; DP_System : P System; axiom forall s : DP_Socket @ s.iotype = io_inout; forall p : DP_Process @ p.ports subseteq DP_Socket and p.locals subseteq DP_DataStructure and p.localobjects = {}; forall c : DP_Circuit @ {c.p1, c.p2} subseteq DP_Socket and {c.c1, c.c2} subseteq DP_Process and c.cc_or_obj = ctype and % circuits always connect processes and not objects c.directionality = twoway; % bidirectional forall pc : DP_ProcessCall @ {pc.c1, pc.c2} subseteq DP_Process and % call connects two processes pc.queuesize = 0 and % process calls cannot be queued pc.blocking = TRUE; % the calling process blocks until the called process returns forall ps : DP_ProcessSpawn @ {ps.c1, ps.c2} subseteq DP_Process and % spawn connects two processes ps.queuesize = 0 and % process spawn cannot be queued ps.blocking = FALSE; % the spawning process does not block forall s : DP_System @ s in DistributedSystems and s.controlcomponents subseteq DP_Process and s.dataconnectors subseteq DP_Circuit and s.calls subseteq DP_ProcessCall and s.spawns subseteq DP_ProcessSpawn and s.globalobjects = {} and s.classes = {} and s.shareddata = {} and s.triggers = {} and (forall c : s.dataconnectors @ exists p1, p2 : s.controlcomponents @ c.p1 in p1.ports and c.p2 in p2.ports) and % all circuit sockets connect process sockets (forall c1, c2 : s.dataconnectors @ c1 /= c2 => (not (c1.p1 = c2.p1 and c1.p2 = c2.p2)) and (not (c1.p1 = c2.p2 and c1.p2 = c2.p1)));

144

% no two circuits connect the same pair of sockets end axiom % Event-Based (implicit invocation) Style global EB_Event : P DataComponent; EB_DataStructure : P DataComponent; EB_Procedure : P ControlComponent; EB_ProcedureCall : P ControlConnector; EB_Object : P Object; EB_Trigger : P Trigger; EB_System : P System; axiom forall p : EB_Procedure @ p.locals subseteq EB_DataStructure and p.ports = {}; forall pc : EB_ProcedureCall @ {pc.c1, pc.c2} subseteq EB_Procedure and % call connects two procedures pc.queuesize = 0 and % procedure calls cannot be queued pc.blocking = TRUE; % the calling procedure blocks until the called procedure returns forall o : EB_Object @ o.data subseteq EB_DataStructure and o.methods subseteq EB_Procedure; forall t : EB_Trigger @ t.object in EB_Object and t.inmessage in EB_Event and t.outmessageset subseteq EB_Event and t.outcalls subseteq EB_Procedure and t.subtype = otype and % limit reception of events to objects t.outspawns = {}; % no spawns allowed to be triggered forall s : EB_System @ s.controlcomponents subseteq EB_Procedure and s.globalobjects subseteq EB_Object and s.calls subseteq EB_ProcedureCall and s.recognizedmessages subseteq EB_Event and s.triggers subseteq EB_Trigger and s.spawns = {} and s.shareddata = {} and s.triggers /= {}; end axiom % Helper function for recursively retrieving all the control components associated with a set of control components and objects. Retrieves methods of all local objects found. global getallcontrolcomponents :

145

(P ControlComponent & P Object) +-> P ControlComponent; axiom forall inputccs, outputccs : P ControlComponent; inputobs : P Object @ getallcontrolcomponents(inputccs, inputobs) = outputccs outputccs = inputccs setunion r_getallmethods(inputobs) setunion r_getallmethods(r_getallobjects({o : Object | exists c : inputccs; n : Name | n in c.localobjects @ n = o.name})); end axiom

% Helper function for recursively retrieving all the objects associated with a set of control components and objects. Retrieves all local objects found. global getallobjects : (P ControlComponent & P Object) +-> P Object; axiom forall inputobs, outputobs : P Object; inputccs : P ControlComponent @ getallobjects(inputccs, inputobs) = outputobs outputobs = inputobs setunion r_getallobjects({o : Object | exists c : inputccs; n : Name | n in c.localobjects @ n = o.name}); end axiom % group operation for composition global group : (P System & Name & P ControlConnector & P ControlConnector & (DataComponent +-> (P ControlComponent & P Object)) & P DataConnector & Layers & Layers & Layers) +-> System; % inputs include a set of (sub)systems and new bridging connectors. output is the resulting system. axiom forall subsystems : P System; newname : Name; newcalls, newspawns : P ControlConnector; extendedshareddata : DataComponent +-> (P ControlComponent & P Object); newdataconnectors : P DataConnector; newcall_layers, newspawn_layers, newdataconnector_layers : Layers; newsystem : System @ group(subsystems, newname, newcalls, newspawns, extendedshareddata, newdataconnectors, newcall_layers, newspawn_layers, newdataconnector_layers) = newsystem newsystem.name = newname and newsystem.initialcontrolcomponents = {x : ControlComponent | exists s : System | s in subsystems @ x in s.initialcontrolcomponents} and newsystem.controlcomponents = {x : ControlComponent | exists s : System | s in subsystems @ x in s.controlcomponents} and

146

newsystem.globalobjects = {x : Object | exists s : System | s in subsystems @ x in s.globalobjects} and (forall c : ControlConnector | c in newcalls or c in newspawns @ (exists s1, s2 : subsystems @ c.c1 in getallcontrolcomponents(s1.controlcomponents, s1.globalobjects) and c.c2 in getallcontrolcomponents(s2.controlcomponents, s2.globalobjects) and s1 /= s2)) and (forall d : DataConnector | d in newdataconnectors @ (exists s1, s2 : subsystems @ d.c1 in getallcontrolcomponents(s1.controlcomponents, s1.globalobjects) and d.c2 in getallcontrolcomponents(s2.controlcomponents, s2.globalobjects) and s1 /= s2)) and % all new connectors span the subsystems {c : ControlComponent | (exists call : ControlConnector | call in newcalls @ c = call.c1 or c = call.c2) or (exists spawn : ControlConnector | spawn in newspawns @ c = spawn.c1 or c = spawn.c2) or (exists dc : DataConnector | dc in newdataconnectors @ c = dc.c1 or c = dc.c2)} subseteq newsystem.controlcomponents and % all components addressed in the new calls, spawns, and dataconnectors are members of the new system control components (this constraint is redundant) (forall d : DataComponent; cset : P ControlComponent; oset : P Object | (d, (cset, oset)) in extendedshareddata @ (exists oldcset : P ControlComponent; oldoset : P Object; s : System @ s in subsystems and (d, (oldcset, oldoset)) in s.shareddata and oldcset subseteq cset and cset subseteq getallcontrolcomponents(newsystem.controlcomponents, newsystem.globalobjects) and oldoset subseteq oset and oset subseteq getallobjects(newsystem.controlcomponents, newsystem.globalobjects))) and % extended shareddata uses existing data but with larger sets of sharing components/objects {x : ControlConnector | exists s : System | s in subsystems @ x in s.calls} setint newcalls = {} and newsystem.calls = {x : ControlConnector | exists s : System | s in subsystems @ x in s.calls} setunion newcalls and {x : ControlConnector | exists s : System |

147

s in subsystems @ x in s.spawns} setint newspawns = {} and newsystem.spawns = {x : ControlConnector | exists s : System | s in subsystems @ x in s.spawns} setunion newspawns and {x : DataConnector | exists s : System | s in subsystems @ x in s.dataconnectors} setint newdataconnectors = {} and newsystem.dataconnectors = {x : DataConnector | exists s : System | s in subsystems @ x in s.dataconnectors} setunion newdataconnectors and newsystem.shareddata = {x : DataComponent & (P ControlComponent & P Object) | exists s : System | s in subsystems @ x in s.shareddata} += extendedshareddata and % extended shared data overrides subsystem’s shared data (forall layer : Layer | layer in newcall_layers or layer in newspawn_layers or layer in newdataconnector_layers @ first layer setunion second layer subseteq getallcontrolcomponents(newsystem.controlcomponents, newsystem.globalobjects)) and % all layers drawn from the control components newsystem.call_layers = {x : Layer | exists s : System | s in subsystems @ x in s.call_layers} setunion newcall_layers and newsystem.spawn_layers = {x : Layer | exists s : System | s in subsystems @ x in s.spawn_layers} setunion newspawn_layers and newsystem.dataconnector_layers = {x : Layer | exists s : System | s in subsystems @ x in s.dataconnector_layers} setunion newdataconnector_layers and (forall call : ControlConnector | call in newcalls @ ((exists layer : Layer | layer in newsystem.call_layers @ (call.c1 in first layer and call.c2 in second layer) or (call.c2 in first layer and call.c1 in second layer)) or (forall layer : Layer | layer in newsystem.call_layers @ {call.c1, call.c2} setint second layer = {}))) and % calls constrained to between layers or not constrained at all (forall spawn : ControlConnector | spawn in newspawns @ ((exists layer : Layer | layer in newsystem.spawn_layers @ (spawn.c1 in first layer and spawn.c2 in second layer) or (spawn.c2 in first layer and spawn.c1 in second layer)) or (forall layer : Layer | layer in newsystem.spawn_layers @

148

{spawn.c1, spawn.c2} setint second layer = {}))) and % spawns constrained to between layers or not constrained at all (forall d : DataConnector | d in newdataconnectors @ ((exists layer : Layer | layer in newsystem.dataconnector_layers @ (d.c1 in first layer and d.c2 in second layer) or (d.c2 in first layer and d.c1 in second layer)) or (forall layer : Layer | layer in newsystem.dataconnector_layers @ {d.c1, d.c2} setint second layer = {}))) and % dataconnectors constrained to between layers or not constrained at all (forall s1, s2 : System | s1 in subsystems and s2 in subsystems @ s1.recognizedmessages = s2.recognizedmessages) and % all subsystems have identical sets of recognized messages newsystem.recognizedmessages = {x : DataComponent | exists s : System | s in subsystems @ x in s.recognizedmessages} and newsystem.triggers = {x : Trigger | exists s : System | s in subsystems @ x in s.triggers} and newsystem.nodes = {x : Node | exists s : System | s in subsystems @ x in s.nodes} and not (exists threads : P Thread; l1, l2, l3 : Thread; c1, c2a, c2b, c3 : ControlComponent; d1, d2 : DataConnector | threads = {thread : Thread | thread in getmaxthreads(newsystem)} and l1 in threads and l2 in threads and l3 in threads and l1 /= l2 and l2 /= l3 and l3 /= l1 and c2a /= c2b and c1 in l1 and c2a in l2 and c2b in l2 and c3 in l3 and ((d1.c1 = c1 and d1.c2 = c2a) or (d1.c1 = c2a and d1.c2 = c1)) and ((d2.c1 = c3 and d2.c2 = c2b) or (d2.c1 = c2b and d2.c2 = c3)) @ d1 in newsystem.dataconnectors and d2 in newsystem.dataconnectors) and % 2 threads may not have dataconnectors going to 2 different components in a thread not (exists threads : P Thread; l1, l2 : Thread; c1, c2 : ControlComponent; s1 : DataComponent & (P ControlComponent & P Object) | c1 in (first (second s1)) and c2 in (first (second s1)) and threads = {thread : Thread | thread in getmaxthreads(newsystem)} and l1 in threads and l2 in threads and c1 /= c2 and l1 /= l2 and c1 in l1 and c2 in l2 @ s1 in newsystem.shareddata) and

149

% 2 threads may not share a piece of data end axiom

150

Appendix C: Minor Changes to Abd-Allah’s Model of Styles This section contains only the model of styles discussed by AbdAllah’s work, that required some minor changes to accommodate changes made to the underlying model as to include the new conceptual features. % Pipe & Filter Style global PF_Socket : P Port; PF_Pipe : P DataConnector; PF_Filter : P ControlComponent; PF_System : P System; axiom forall s : PF_Socket @ % No socket is used for both input and output s.iotype /= io_inout and % All data transfers are streamed s.streaming = TRUE; forall p : PF_Pipe @ % Pipes always connect filters and not objects p.cc_or_obj = ctype and % Unidirectional p.directionality = forward and % Pipe connects two filters {p.c1, p.c2} subseteq PF_Filter and % Ports belong to the P/F style {p.p1, p.p2} subseteq PF_Socket and % p1 acts as sender, p2 acts as receiver p.p1.iotype = io_out and p.p2.iotype = io_in and % The sender socket is different than the receiver p.p1 /= p.p2; forall f : PF_Filter @ % Ports belong to the P/F style f.ports subseteq PF_Socket and f.localobjects = {}; forall s : PF_System @ s.controlcomponents subseteq PF_Filter and s.dataconnectors subseteq PF_Pipe and s.globalobjects = {} and s.classes = {} and s.calls = {} and s.spawns = {} and s.shareddata = {} and

151

s.repositories = {} and s.call_layers = {} and s.spawn_layers = {} and s.triggers = {} and % A pipe-and-filter system always terminates, hence all of its filters % (control components) must terminate. (forall cc : ControlComponent | cc in s.controlcomponents @ cc.terminates = TRUE) and s.initialcontrolcomponents = s.controlcomponents and s.initialdataconnectors = s.dataconnectors and % All pipe sockets connect filter sockets (forall p : s.dataconnectors @ exists f1, f2 : s.controlcomponents @ p.p1 in f1.ports and p.p2 in f2.ports) and % No two pipes connect the same sender and receiver (forall p1, p2 : s.dataconnectors @ ((p1.p1 = p2.p1 and p1.p2 = p2.p2) => p1 = p2)); end axiom

% Main/Subroutine Style global MS_DataStructure : P DataComponent; MS_Procedure : P ControlComponent; MS_ProcedureCall : P ControlConnector; MS_System : P System; axiom forall p : MS_Procedure @ p.ports = {} and p.locals subseteq MS_DataStructure and p.localobjects = {}; forall pc : MS_ProcedureCall @ % Call connects two procedures {pc.c1, pc.c2} subseteq MS_Procedure and % Procedure calls cannot be queued pc.queuesize = 0 and % The calling procedure blocks until the called procedure returns pc.blocking = TRUE; forall s : MS_System @ s.controlcomponents subseteq MS_Procedure and dom s.shareddata subseteq MS_DataStructure and s.repositories = {} and s.calls subseteq MS_ProcedureCall and s.globalobjects = {} and s.classes = {} and s.spawns = {} and s.dataconnectors = {} and s.spawn_layers = {} and s.dataconnector_layers = {} and s.triggers = {} and # s.initialcontrolcomponents = 1 and

152

% All M/S systems have a single thread # (getmaxthreads(s)) = 1 and % System forms a connected, directed graph of calls starting from % main (exists main : MS_Procedure; subroutines : P MS_Procedure @ s.initialcontrolcomponents = {main} and {main} setunion subroutines = s.controlcomponents and main notin subroutines and (forall call : s.calls @ call.c2 /= main) and cdgraph (main, subroutines) = {c1, c2 : MS_Procedure | exists call : s.calls @ call.c1 = c2 and call.c2 = c2}) and % The system rests on one node # {n : Node | (exists c : ControlComponent | c in s.controlcomponents @ n in c.nodes) or (exists call : ControlConnector | call in s.calls @ n in call.nodes)} = 1; end axiom % Distributed Processes Style global DP_DataStructure : P DataComponent; DP_Socket : P Port; DP_Process : P ControlComponent; DP_Circuit : P DataConnector; DP_ProcessCall : P ControlConnector; DP_ProcessSpawn : P ControlConnector; DP_System : P System; axiom forall s : DP_Socket @ s.iotype = io_inout; forall p : DP_Process @ p.ports subseteq DP_Socket and p.locals subseteq DP_DataStructure and p.localobjects = {}; forall c : DP_Circuit @ {c.p1, c.p2} subseteq DP_Socket and {c.c1, c.c2} subseteq DP_Process and % Circuits always connect processes and not objects c.cc_or_obj = ctype and % Bidirectional c.directionality = twoway; forall pc : DP_ProcessCall @ % Call connects two processes {pc.c1, pc.c2} subseteq DP_Process and % Process calls cannot be queued pc.queuesize = 0 and % The calling process blocks until the called process returns pc.blocking = TRUE; forall ps : DP_ProcessSpawn @ % Spawn connects two processes

153

{ps.c1, ps.c2} subseteq DP_Process and % Process spawn cannot be queued ps.queuesize = 0 and % The spawning process does not block ps.blocking = FALSE; forall s : DP_System @ s in DistributedSystems and s.controlcomponents subseteq DP_Process and s.dataconnectors subseteq DP_Circuit and s.calls subseteq DP_ProcessCall and s.spawns subseteq DP_ProcessSpawn and s.globalobjects = {} and s.classes = {} and s.shareddata = {} and s.repositories = {} and s.triggers = {} and % All circuit sockets connect process sockets (forall c : s.dataconnectors @ exists p1, p2 : s.controlcomponents @ c.p1 in p1.ports and c.p2 in p2.ports) and % No two circuits connect the same pair of sockets (forall c1, c2 : s.dataconnectors @ c1 /= c2 => (not (c1.p1 = c2.p1 and c1.p2 = c2.p2)) and (not (c1.p1 = c2.p2 and c1.p2 = c2.p1))); end axiom

154

Appendix D: Acronyms • AAA - Architect’s Automated Assistant • ADL - Architecture Description Language • AI - Artificial Intelligence • API - Application Program Interface • CASE - Computer Aided Software Engineering • COTS - Commercial Off The Shelf • CPU - Central Processing Unit • CSE - Center for Software Engineering • DBMS - Database Management System • DSSA - Domain Specific Software Architecture • GOTS - Government Off The Shelf • GUI - Graphical User Interface • OTS - Off The Shelf • SGS - Satellite Ground Station • USC - University of Southern California

155