Chapter 4

Towards a Design Handbook for Integrating Software Components

Chapter 2 argued for separating the core functional pieces of a software application from their interconnection relationships. Last chapter introduced an architectural language that enables this separation by providing separate abstractions for activities and dependencies. This chapter goes one step further: It observes that, when taken out of context, many interconnection problems in software applications are related to a relatively narrow set of concepts, such as resource flows, resource sharing, and timing dependencies. These concepts are orthogonal to the problem domain of most applications, and can therefore be captured in an application-independent vocabulary of dependency types. Likewise, the design of associated coordination processes involves a relatively narrow set of coordination concepts, such as shared events, invocation mechanisms, and communication protocols. Therefore, it can also be captured in a design space that assists designers in designing a coordination process that manages a given dependency type, simply by selecting the value of a relatively small number of design dimensions. The proposed vocabulary of dependencies and design space of coordination processes, taken together, can form the basis for a design handbook for integrating software components. The development of such a handbook aims to reduce the specification and implementation of software component interdependencies to a routine design problem, capable of being assisted, or even automated, by computer tools.

4.1 Motivation

The purpose of this chapter is to give an answer to the following two questions:

Why do software components interconnect with one another?

How do software components interconnect with one another?

We would like to organize the answers to the first question in a vocabulary of dependency types, and the answers to the second question in a design space of coordination processes. Finally, we would like to connect each of the whys, with a set of hows, that is, associate each dependency type with a set of coordination processes for managing it.

A vocabulary of interdependency patterns would greatly aid designers in constructing application architectural diagrams. Instead of always inventing a new dependency to express a given component relationship, designers would often simply choose one from the dependency vocabulary.

Furthermore, the existence of a coordination process design space would reduce the step of managing dependencies with coordination processes to a routine, or even automatic, selection of an element from a coordination process repository.

Finally, a vocabulary of dependency types and coordination processes would contribute to an increased understanding of the problems of software interconnection. Over time, researchers have developed a vast arsenal of algorithms and techniques for process synchronization, communication, and resource allocation. What has been missing so far is a unified framework for relating those algorithms to the problems they are attempting to solve. Such a framework should encompass (and relate to one another) synchronization, communication, and resource allocation considerations. It should relate techniques and algorithms that are currently being studied by a number of different research areas (programming languages, operating systems, concurrent and distributed systems). Therefore, it could form the basis for developing a design handbook of software component interconnection. Such a handbook could help reduce the integration of existing software components into new applications to a routine design problem.

The approach taken in this chapter is based on coordination theory [Malone94], an emerging research area that focuses on the interdisciplinary study of coordination. Coordination theory defines coordination as the process of managing dependencies among activities. One of its objectives is to characterize different kinds of dependencies and identify the coordination processes that can be used to manage them. This work extends the frameworks presented in [Malone94], and is the first detailed application of the theory to the understanding of software component relationships. Coordination theory is discussed in more detail in Section 7.2.

It is important to emphasize that the results described in this chapter do not claim rigorous generality and completeness. Our goal was to develop a dependency vocabulary and coordination process design space that covers a useful subset of the component relationships and constraints encountered in practice. The SYNOPSIS machinery enables designers to incrementally enrich this vocabulary with new abstractions and processes. It is our hope that this work will provide a useful starting point that will lead in interesting extensions by future research.

4.2 Overview of the Dependencies Space

The vocabulary of dependencies presented in this chapter is based on the simple assumption that component interdependencies are explicitly or implicitly related to patterns of resource production and usage. In other words, activities need to interact with other activities, either because they use resources produced by other activities, or because they share resources with other activities.

The definition of resources can be made broad enough to make this assumption cover most (if not all) cases of component interaction encountered in software systems. Our current definition of resources encompasses:

processor time (control)

data of various types

operating system resources (memory pools, pipes, sockets, etc.)

hardware resources (printers, disks, multimedia adapters, etc.)

In every resource relationship, participating activities can be distinguished into two roles:

Resource producers

Resource consumers

The existence of two different roles in resource relationships, implies the existence of three different classes of dependencies:

Dependencies between producers and consumers

Dependencies among consumers who use the same resources

Dependencies among producers who produce for the same consumers

Dependencies between producers and consumers are modeled using a family of dependencies called flow dependencies. Malone and Crowston [Malone94] have observed that, in general, whenever flows occur, one or more other sub-dependencies are present. In particular, flow dependencies can be decomposed to the following set of lower-level dependencies:

Sections 4.5 and 4.6 are devoted to a detailed discussion of flow dependencies.

Sharing dependencies contained inside flows assume that multiple users of a resource are independent, and therefore competing with one another for resource access. In many applications however, users (or producers) of a resource are cooperating in application-specific ways. In those cases, designers must explicitly specify additional dependencies that describe the patterns of cooperation among users (or producers). Imagine, for example, a database resource which is generated by some activity and subsequently used by three other activities. In one particular application, one of the users of the database is using it to write values that will be read by the other users. This application-specific pattern of cooperation among users of the database requires the specification of an additional prerequisite relationship between the writer and the reader activities (Figure 4_1).

Application-specific patterns of cooperation among activities that share resources are expressed using additional flows and another family of dependencies called timing dependencies. Timing dependencies express constraints on the relative flow of control among a set of activities. The most widely used are prerequisite dependencies (A must complete before control flows into B) and mutual exclusion dependencies (A and B cannot execute at the same time).




Figure 4-1: An example of cooperative resource use.

In addition to specifying application-specific cooperation patterns, timing dependencies are often used to specify implicit resource relationships. For example, mutual exclusion dependencies are often used to specify implicit resource sharing relationships, in which support for resource accesses is embedded inside the code of each activity. Also, prerequisite dependencies often specify implicit flow relationships in which resource production and consumption are embedded inside the code. Section 4.7 describes a family of timing dependencies. For each dependency, its relationship with a resource dependency is illustrated.

Throughout the chapter, it becomes apparent that, apart from classifying and enumerating elementary dependency types, it is also useful to begin to collect and classify sets of frequently occurring composite dependency patterns. In many cases, designers have developed specialized, more efficient joint coordination processes for such patterns. Section 4.8 will present a few useful composite patterns of flows and joint coordination processes for managing them.

4.3 The Concept of a Design Space

As with any complex taxonomy, it is useful to classify both dependencies and coordination processes using multi-dimensional design spaces [Bell72, Lane90]. Each dimension of the design space describes variation in some design choice. Values along a dimension are called design alternatives. They correspond to alternative requirements or implementation choices. For example, when selecting a data transportation mechanism, the number of data readers could be one design dimension; the location of readers relative to the writer could be another. Figure 4-2 illustrates a tiny design space for selecting a data transportation mechanism.

Figure 4-2: A simple design space for selecting a data transportation mechanism.

Specific designs are described by points in the design space, identified by the dimensional values that correspond to their design choices.

Successful design spaces reduce the problem of design to that of answering a simple set of questions. They also organize related design alternatives "close" to each other and expose correlations between various aspects of design. Finally, they can be easily translated into computerized knowledge bases that can help semi-automate the design task.

Our problem requires the construction of two, related, design spaces:

In addition, each point in the dependency design space (dependency type) must be associated to a coordination design space for managing it.

Our objective in the following sections is to define related dependency and coordination design spaces for each family of dependencies.

The success of a design-space description of design alternatives clearly lies in the choice of dimensions and specific dimensional values (design alternatives). There is no obvious rigorous way of defending a particular set of choices. Neither Bell and Newell [Bell72], nor Lane [Lane90] have offered any justification for their dimensions and alternatives, except for their own intuition and the usefulness of the resulting description. I will follow the same path, simply proposing a set of dimensions and trying to show empirically that they form a useful description of design alternatives.

4.4 A Taxonomy of Resources

Before we begin the description of resource flow dependencies, we present a taxonomy of resources occurring in software systems. This taxonomy will be useful both for distinguishing between different special cases of flow relationships, and for determining the range of alternative ways of managing them.

The taxonomy is summarized in Figure 4-3 The following is a discussion of its principal dimensions.


Figure 4-3: A taxonomy of resources.

4.4.1 Resource Kind

Control. The resource usually referred to in Computer Science as control, is more accurately described as a thread of processor attention. In order for any software activity to begin execution, it needs to receive control from somewhere, that is, it needs to receive the attention of some processor. Control flow dependencies thus describe the flow of processor attention from one activity to another.

4.4.2 Resource Access

Resource access determines how producers and users access their corresponding resources.

The use of identifiers is extremely widespread in software systems. Identifiers provide mappings that allow a wide variety of resources (system, hardware, complex data structures) to be accessed by software components that can only interface with their environment through relatively simple data resource ports.

System and hardware resources are always accessed indirectly. Complex data resources, such as files and databases, are also typically accessed using identifiers.

4.4.3 Resource Transportability

Transportability determines whether resources can be moved around in the system.

4.4.4 Resource Sharing

This section describes a framework for reasoning about shared resources that was developed by George Wyner and Gilad Zlotkin at the MIT Center for Coordination Science [Wyner95a].

Wyner and Zlotkin proposed a small number of important resource attributes that can help designers classify coordination requirements for shared resource dependencies. They observed that these important attributes are not merely a function of the resource type, but of the intended mode of usage as well. That is, the same resource type, used in different modes (e.g. read versus written), might display different sharing behavior along those attributes. For that reason they refer to them as attributes of resources-in-use. These attributes are:

a. Divisibility

Divisibility specifies whether a resource-in-use can be divided into independent subresources. Some example of divisible and indivisible resources are shown below.
ResourceUsage Description

Divisible
Memory heapRead/Write Heaps can be divided into independent smaller blocks
Network channelConnect Physical network channels can support multiple independent connections

Indivisible
Scalar variableRead/Write Scalar variables can only store one value
pgp Encrypted File DecryptEncrypted files can only be decrypted in their entirety

b. Consumability

Consumability specifies whether a resource-in-use is being destructively consumed. Consumable resources can be used a finite amount of times. Nonconsumable resources can be used an arbitrarily large amount of times. Some example of consumable and nonconsumable resources in use are shown below:
ResourceUsage Description

Consumable
Pipe channelRead Values "disappear" from the channel as they are being read
PROMWrite PROMs (Programmable Read Only Memories) can only be written once

Nonconsumable
FileRead Files can be read an arbitrarily large amount of times
ProcessorStart Task Processors can be used to start an arbitrarily large number of tasks



c. Concurrency

Concurrency specifies whether a resource-in-use can be used by more than one users at the same time. Concurrency can be finite, setting a finite limit on the number of concurrent users, or infinite (arbitrarily large). The following are examples of finitely and infinitely concurrent resources.
ResourceUsage Description

Infinitely Concurrent
FileRead In most systems, multiple users are allowed to read files concurrently
Multitasking Processor Start TaskMultitasking systems appear to execute multiple tasks concurrently

Finitely Concurrent
Ftp ServerConnect Ftp servers often limit the number of concurrent connections for performance reasons
PrinterPrint File Printers cannot interleave the printing of different files

4.5 A Generic Model of Resource Flows

This section presents a generic model for classifying flow dependencies and a generic process for managing them. Section 4.6 describes how this generic model can be specialized to manage different special cases of flow dependencies.

In the most general case, flow dependencies exist between a number of resource producers and a number of consumers (Figure 4-4). Dependencies are connected to activities through resource producer and consumer ports. Producer and consumer ports are abstract ports (see Section 3.3.3). That is, they are composite ports that contain implementation-specific groupings of low-level interface ports that logically participate in the production and consumption of a given resource.

We assume that, by default, a flow dependency between a set of activities implies a stream of resource flows over the lifetime of an application execution. Coordination processes for managing flow dependencies are designed with this assumption in mind. Situations where resources are produced or consumed only once during the lifetime of an application execution are represented by special types of dependencies.





DependencyDescription
UsabilityProduced resources must be in a form usable by each user
Accessibility Produced resources must be made accessible to each user
Prerequisite Resources must be produced before they can be used
Resource sharing Multiple consumers share the same resources
Consumer sharing Multiple producers produce resources for the same consumers


Figure 4-4: A generic model of resource flow dependencies.

Our objectives in this section are the following:

Both design spaces are based on a generic model for decomposing flow dependencies into lower-level dependencies, shown in Figure 4-4. Managing a flow dependency implies managing all lower-level dependencies. This model extends the ideas introduced in [Malone94], and attempts to capture the different considerations that must be addressed whenever resources are exchanged or shared among different activities.

The generic model for managing flow dependencies focuses on the relationships between producers and users of resources. It assumes that different consumers (producers) are independent from one another and compete for access to resources (consumers).

In the following sections, we will first introduce dependency and coordination processes design spaces for each of the lower-lever dependencies. The design space for generalized flow dependencies will then be defined by the product of the component dependencies design spaces.

4.5.1 Usability Dependencies

4.5.1.1 Types of usability dependencies

Usability dependencies state the simple fact that resource users should be able to properly use produced resources. This is a very general requirement that encompasses compatibility issues such as:

The exact meaning and range of usability considerations varies with each kind of resource. Section 4.6, which describes specializations of flow dependencies for a variety of different resources, also discusses in more detail the meaning of usability dependencies for each of them.

4.5.1.2 Managing usability dependencies

One interesting observation resulting from this work is that, irrespective of the particular usability issue being managed, coordination alternatives for managing usability dependencies can be classified using the following two design dimensions (Figure 4-5) :
Design Dimension Design Alternatives
Who is responsible for ensuring usability? - Designer (Standardization)

- Producers

- Consumers

- Both producers and consumers

- Third party

When are usability requirements fixed? - At design-time

- At run-time

Figure 4-5: A framework for managing usability dependencies.

Who is responsible for ensuring usability ?

The following alternatives are possible:

Are usability requirements fixed ?

Coordination processes can be further classified depending on whether the producer and consumer formats are fixed and known at design-time, or whether they are negotiated at run-time. In the latter case, the management of usability dependencies might introduce additional flow dependencies to the system, that have to be managed in turn.

4.5.2 Accessibility Dependencies

4.5.2.1 Types of accessibility dependencies

Accessibility dependencies specify that a resource must be accessible to a user before it can be used. Since users are software activities, accessibility specifies more accurately that a resource must be accessible to the process that executes a user activity before it can be used. Important parameters in specifying accessibility dependencies are the number of producers, the number of users, and the resource kind.

4.5.2.2 Managing accessibility dependencies

There are two broad alternatives for making resources accessible to their users (Figure 4_6):

Depending on the type of resource being transferred, either or both alternatives might be needed. Placing producer and user activities "close" to one another generally decreases the cost of transporting the resource. Combinations of placing activities and transporting resources should be considered in situations where the cost of placing the activities is lower than the corresponding gain in the cost of transporting the resource.

The following is a discussion of the two alternatives:

Principal design alternatives First-level of specialization Second-level of specialization

Place producers and consumers "close together"
Place at design-time



Place at run-time

- Package in same sequential module

- Package in same executable

- Assign to same processor

- Assign to nearby processors

- Code is accessible to all processors

- Physical code transportation required


Transport resource

Actual processes depend on resource kind (see Section 4.6)

Figure 4-6: A framework for managing accessibility dependencies.

a. Place producers and users "close together"

This can be done either at design-time, or at run-time.

ul> - Place activities at design-time. The following is a list of ways to manage this step, in decreasing order of efficiency:

- Move activities at run-time. Either producers can be moved close to users or vice-versa. In the simplest case this would imply assigning the producer to the same processor where user activities are also assigned. In more complicated cases, this step might require physically transferring an activity's code to the target machine.

b. Transport resource from producers to users

This step depends on the kind of resource that is flowing. It is discussed in more detail in Section 4.6.

4.5.3 Prerequisite Dependencies

4.5.3.1 Types of prerequisite dependencies

A fundamental requirement in every resource flow is that a resource must be produced before it can be used. This is captured by including a prerequisite dependency in the decomposition of every flow dependency.


Figure 4-7: Prerequisite dependency.

Prerequisites are relationships between two sets of activities (Figure 4-7). In the following discussion we will refer to set A as the precedent set and to set B as the consequent set. As is the case with flow dependencies, prerequisite dependencies in our vocabulary have stream semantics: they assume that precedent and consequent activities might execute multiple times over the lifetime of an application execution. Prerequisite dependencies thus specify constraints on the allowed execution interleavings of precedent and consequent activities.

Prerequisite dependencies occur very frequently in software architectures. They are the most frequently used member of the dependency family we call timing dependencies. Timing dependencies express constraints in the timing of control flow into a set of activities. They are discussed in Section 4.7.

Prerequisite dependencies form a family of related sequencing constraints. The most useful members of the prerequisite family are the following:

The above variations of prerequisite relationships can be organized in a specialization hierarchy, as shown in Figure 4-9. The implication of prerequisite specialization relationships is that coordination processes for managing a prerequisite relationship can also be used to manage any of its parent relationships in the specialization structure. For example, in order to manage a cumulative prerequisite, in addition to using processes specifically designed for this type of prerequisite, designers can also consider using coordination processes for transient or lockstep prerequisites.


Figure 4-9: Specialization relationships among different prerequisite dependency types.

Prerequisite dependencies can be further classified according to:

4.5.3.2 Managing prerequisite dependencies

There are four generic processes for managing prerequisite dependencies (Figure 4-10):

a. Producer Push

This process decomposes into a control flow dependency (Section 4.6.1). The alternatives for managing it are the same as those of managing the corresponding control flow dependency.

Producer push processes manage lockstep prerequisites. Consequents are invoked once each time the precedents complete execution.


Producer Push



As soon as the precedent completes, it invokes the consequent by explicitly passing control to them.

Consumer Pull



Before it begins execution, the consequent synchronously calls the precedent.

Peer Synchronization



Both precedent and consequent are executed by independent threads of control and synchronize themselves using shared events.

Controlled Hierarchy



A third party controls the invocation of both the precedent and the consequent

Figure 4-10: Generic processes for managing prerequisite dependencies.

b. Consumer Pull

This process family decomposes into a synchronous call pattern of control flow dependencies. The alternatives for managing it are the same as those of managing the corresponding pattern of control flows.

Consumer pull processes manage lockstep prerequisites. Precedents are invoked once before each consequent. Consumer pull organizations can also be used to manage persistent and perishable dependencies: Before starting itself, each consequent checks whether the prerequisite condition is valid, and invokes the precedent activities if it is not.

c. Peer Synchronization

Peer synchronization processes can be used to manage all kinds of prerequisites. Figure 4_11 shows their generic form for each kind of one-to-one prerequisite. All processes can be generalized to handle many-to-many prerequisites.



Figure 4-11: Generic processes for managing prerequisite dependencies using peer event synchronization.

Peer Synchronization processes rely on the generation and detection of shared events in the system. Events can be classified as follows (Figure 4-12):


Persistent Memoryless Events
Event typeGenerate DetectReset
SemaphoreSignal Semaphore (V)
Wait on Semaphore (P)
File CreationCreate File Test File Existence Delete File
File ModificationWrite File Compare file modification time with stored modification time Set stored modification time to file modification time
Process CreationCreate Process Test Process Existence Kill Process

Transient Memoryless Events
Event typeGenerate Detect
UNIX Signal mechanism signal system callwait system call
Windows DDE mechanism send DDE transactioninitialize DDE conversation

Cumulative Events
EventReset IncrementDecrement Detect
Counting SemaphoreSet semaphore to zero Signal semaphore
Wait on semaphore
ListClear List Add element to list Remove element from list Check if list is empty

Figure 4-12: A taxonomy and examples of event types.



d. Controlled Hierarchy

There are three variations on this process:

Controlled hierarchy processes can be used to manage lockstep prerequisites. Permanent prerequisites can also be managed by this approach by placing the prerequisite code before any other code in the system (e.g. in an initialization module or at the top of the main program).

Figure 4-13 summarizes the design dimensions of prerequisite dependencies and coordination processes.

Principal Design Dimensions Design Alternatives Other Design Dimensions
Type of prerequisite - Persistent

- Perishable

- Cumulative

- Transient

- Lockstep

Organization of coordination mechanism - Producer Push

- Consumer Pull

- Peer Synchronization

- Controlled Hierarchy

- Synchronous vs. Asynchronous

control flow


- Type of shared event used

- Wait for precedent completion

vs. pre-scheduling

Figure 4-13: A framework for managing prerequisite dependencies.

4.5.4 Sharing Dependencies

4.5.4.1 Types of sharing dependencies

Sharing arises when more than one activity requires access to the same resource. Sharing dependencies can be specialized using the three dimensions of the resource-in-use framework of Section 4.4.4. For each different combination of resource-in-use parameters (e.g. indivisible, consumable, concurrent), a different specialization of sharing dependency can be defined.

Sharing dependencies arise in one-to-many, many-to-one, and many-to-many flow dependencies in two distinct situations:

a. Resource sharing

Resource sharing considerations arise in one-to-many flow dependencies, because more than one activity uses the same resource. Resource users are assumed to be independent. Therefore, the sharing coordination requirements depend solely on the sharing properties of the resource. The different possibilities are:
  • Divisible resources
  • Resources can be divided among the users.
  • Consumable resources
  • The total number of users must be restricted.
  • Nonconcurrent resources
  • The number of concurrent users must be restricted .

    b. Consumer sharing

    Consumer sharing dependencies arise in many-to-one flow dependencies because more than one producers produce for the same consumer activity, viewed as a "resource". Consumer "resources" can be characterized using the resource-in-use framework. The different dimensions are:
    DivisibilityConsumer activities either occur or do not occur. Therefore, they are considered indivisible resources.
    ConsumabilityConsumability of a consumer activity means that it can occur a limited number of times or, equivalently, that it can accept a limited number of produced resources. This implies the need for coordination in order to select which resources will be accepted. Modeling consumer activities as consumable resources enables many-to-one flow dependencies to be used for modeling race conditions.
    ConcurrencyConcurrency determines whether multiple instances of a consumer activity can be active at the same time. Some consumer activities are nonconcurrent (e.g. non-reentrant procedures). In that case, coordination should be installed to restrict simultaneous execution of more than one activity instances.

    Many-to-many flow dependencies contain a combination of both resource and consumer sharing dependencies.

    4.5.4.2 Managing sharing dependencies

    The problem of resource sharing has been studied extensively by researchers in various areas and there exists a huge literature of related algorithms and techniques. Our purpose in this section is to take an architectural look at resource sharing techniques, showing how their interfaces can be abstracted to a small number of generic processes, and how they relate to the other components of a resource flow management process in a small, well-defined number of ways.

    There are three general techniques for coordinating resource sharing requirements (Figure 4-14):

    Resource Type Sharing Coordination Required Specializations
    Divisible Resources Divide Resource- Divide before transportation

    - Divide after transportation

    Indivisible Resources
    Consumable and/or

    Finitely Concurrent

    Restrict access to resource


    Replicate resource

    - Restrict consumer activity execution

    - Restrict resource transportation

    - Restrict resource production

    Nonconsumable and

    Infinitely Concurrent

    No sharing coordination is required

    Figure 4-14: A framework for managing sharing dependencies.

    a. Divide resource

    This technique applies to divisible resources. It can be represented by a process that uses the entire resource and produces a set of new subresources (Figure 4-15). Subresources are considered independent resources and can then flow to each user with no further coordination.


    Figure 4-15: Sharing of divisible resources in a flow dependency.

    There are two different ways a resource divide can be combined with the rest of a flow coordination process:


    b. Restrict access to resource

    This very general technique applies to both consumable and nonconcurrent resources. In both cases the function of the coordination process is to restrict the flow of control into activities accessing the resource (Figure 4-16). More specifically:

    From an architectural perspective, there are three different ways an access restriction process can be integrated with the rest of a flow coordination process:


    Figure 4-16: Sharing by restricting access to resource.

    c. Replicate Resource

    Resource replication is a technique that jointly manages accessibility and resource sharing dependencies. Its more general architectural form is similar to that of a resource division process. However, it applies to indivisible resources.

    Combinations of division and restriction

    The previous techniques can be combined to handle more complex resource sharing requirements. For example, in order to share a resource that is nonconcurrent and finitely divisible among a potentially infinite number of users a combination of division and access restriction can be used: Whenever an access is desired, extraction of a new subresource is first attempted. If that fails, time-sharing is used. This algorithm is used, for example, to manage the sharing of finite capacity buffered input/output channels among a potentially infinite number of user processes.

    4.5.5 Putting it all together: Flow dependencies

    The design dimensions of generalized resource dependencies are the sum of the design dimensions of their component dependencies (Figure 4-17). For each combination of dimension values, a different special case of resource flow can be defined. The following is a discussion of the different dimensions and the alternative flow dependencies they can be used to define.


    Figure 4-17: First two levels of design dimensions for flow dependencies.

    a. Resource kind

    The most important design dimension is the kind of resource. Section 4.6 will describe how resource dependencies are specialized according to this dimension.

    b. Prerequisite relationship

    Another important dimension is the kind of prerequisite requirement. According to this dimension, resource relationships are classified into:

    Managing Prerequisite Coordination Processes

    The coordination process selected to manage a prerequisite dependency at the heart of a resource flow has a profound influence on the overall organization of the interacting activities. Corresponding to the four generic classes of prerequisite coordination processes we have an equivalent taxonomy of flow organizations:

    c. Number of producers and users - Sharing dimensions

    one-to-allEach resource flows to all users
    one-to-one-of-many Each resource flows to one of the users. This can be managed in an application-independent way (e.g. first come-first served), or in an application-specific way. In the latter case, user consumer ports usually provide additional pieces of information, such as user priorities.

    each-to-allEvery resource produced flows to all users
    each-to-oneEvery resource produced flows to one user only
    each-from-one Each user receives one resource only
    all-from-one Only one of the resources produced flows to (all) users

    The design alternatives for managing resource dependencies are the product of the different alternatives for managing each component dependency. In principle, each of the component dependencies can be managed by independent coordination processes. In practice however, there often exist opportunities to increase efficiency by managing patterns of dependencies using joint coordination processes. This gives rise to additional design alternatives that designers should be aware of. We have already encountered the opportunity to use joint coordination processes for managing accessibility and sharing (restrict resource transportation, replicate resource). In the following sections, we will encounter more opportunities for joint dependency management.


    Continue on to remainder of Chapter 4