Guideline: Structuring Components |
This guideline explains how to structure your component model so that you can make changes to individual components without impacting the rest of the system.
Relationships
Related Elements | Detail Component Model
Main Description
This guideline explains how to structure your component model to ensure that the components are: · Highly cohesive · Loosely coupled · Well isolated · Of the right granularity · Layered according to their generality Your selection of an architectural pattern to follow has a strong influence on how you structure your component model. While this guideline covers how to structure components using the layering technique, layering is only one of many possible architectural patterns upon which to base your structuring activities. By following this guideline, you define a number of well structured, logical components and their responsibilities. The concept of assigning responsibilities to components was made popular through the CRC (Classes-Responsibilities-Collaborations) technique [WIRFS-BROCK90]. Responsibilities are defined as: · The knowledge a component maintains · The actions a component performs You may define the components using a modeling tool, or drawings in a word processing document. Figure 1 depicts an example of a UML Component Relationship Diagram created using this technique. Figure 1. Component Relationship Diagram To structure your component model, assess the components according to a number of attributes. These attributes help you asses the overall quality of a component. ### Cohesion Cohesion is a measure of how well a component's responsibilities are related to each other. High cohesion (components with closely related responsibilities) is good, while low cohesion is bad. An example of a highly cohesive component might be a 'Dictionary' component that has the responsibilities of checking spelling and performing a thesaurus function to find alternatives for words. If the 'Dictionary' component also has the responsibility for performing numeric arithmetic, then it exhibits low cohesion. It would be better for that responsibility to be dealt with by a different component. The following are seven degrees of cohesion, listed from highest to lowest: Functional: Operations all contribute to the execution of one and only one problem related task. Sequential: Operations are involved in activities such that output data from one activity serves as input data to the next. Communicational: Operations contribute to activities that use the same input, or output data. Procedural: Operations are involved in different, and possibly unrelated activities, which flows from one activity to the next. Temporal: Operations are involved in activities that are related in time. Logical: Operations contribute to activities of the same general category; the activities to be executed are selected externally. Coincidental: Operations have no meaningful relationship to each other. ### Coupling Coupling is an indication of the strength of the associations between components. Strongly coupled components have tightly bound associations, and the components are highly dependent on each other. Weakly coupled components have very loose (or even non-existent) associations with each other. Weakly coupled components are better than tightly coupled ones, because it is easier to switch one component for another, or update a component without affecting others. There are six degrees of coupling, listed following from best to worst: Data coupling: Communication is via parameters, where each parameter is an elementary piece of data. Stamp coupling: Communication is via composite data, or data with meaningful internal structure. Control coupling: Data passed is intended to control the internal logic of the component. Common coupling: Components both refer to the same global data area. Content coupling: One component refers to the inside of another in some way; one component changes the data inside another. Hybrid coupling: Different meanings are assigned to different parts of a range of data. For example, a flag is both a data flag and a control flag simultaneously. ### Isolation Isolation is a measure of the degree to which product or technology dependencies are isolated from each other. There are two extremes of isolation: Bad isolation: Every component has a dependency on the product or technology of other components. There is little to no use of patterns that encourage isolation techniques. Good isolation: Product and technology dependencies are fully decoupled. There is good use of patterns that encourage isolation techniques. Examples of such patterns include the Gang of Four "Proxy", "Bridge", and "Mediator" patterns and the GRASP "Indirection" pattern. Isolation and coupling are closely related. Isolation of products and technologies ensures loose coupling. Layering is another approach to ensuring good isolation. ### Granularity Granularity is a measure of the size, or amount of functionality, assigned to a component. There are five levels of granularity: Very fine grained: For example, an object-oriented language class useful for assembling distributed components, but not considered a component in its own right. Fine grained: A software element that can be called at runtime, with a clear interface and a separation between interface and implementation. Also known as a distributed component. Medium grained: An autonomous business concept, or business process. Also known as a business component. Coarse grained: A set of cooperating business components assembled to deliver a solution to a business problem. Also known as a system-level component. Very course grained: For example, a federation of system-level components working together to provide some business value. It helps heterogeneous information systems interoperate. You can think of a system-level component as the same as an application. However, one major difference is that a component-based system is made up of components visible at runtime. The implementation of a component can be changed without having to change the rest of the system. Making such changes is more difficult with large, monolithic applications. Different component-based systems (applications) can be assembled without necessarily having to redesign at the detail level, break code apart, recompile, or re-link the system. ### Layering Layering involves: Identifying suitable architectural layers within which components can be placed. Placing components (and subsystems) into these layers according to their generality and functionality. Defining rules for how the layers can interact with each other. Bachmann et al [BACHMANN00] offer the following definition of layering. "Layering, like all architectural structures, reflects a division of the software into units. In this case, the units are layers; each layer represents a virtual machine. A virtual machine is a collection of software that together provides a cohesive set of services that other software can utilize without knowing how those services are implemented. ...The goal of layering is to define virtual machines that are small enough to be well understood, but comprehensive enough so that likely changes will affect only a single layer". Layering is a mechanism for grouping a set of components according to their generality. For example, a system might have the following layers: All components that provide application-independent business function. Application-independent business functions are things like customer management and product management, which apply to many applications. All components that provide service functions, such as error handling and audit. These components are both business- and application-independent. Middleware components, such as message queuing and relational DBMS software. Layering offers the following benefits [BACHMANN00]: Layers help to bring quality attributes of modifiability and portability to a system. A change to a lower layer that does not affect its interface will not require a change to a higher layer. For example, any J2EE compliant application server that conforms to the J2EE standard may be freely substituted without change to application-level software. A change to a higher layer that does not affect what it requires from lower layers will not affect a lower layer. In general, changes to a layered software system that do not affect an interface are confined to a single layer. Thus, layers define units of reuse and portability. Layers are part of the blueprint role that architecture plays for constructing the system. By knowing which layers contains their software, developers know what services they can rely on in the coding environment. Layers may define work assignments for development teams. Layers are part of the communication role played by architecture. In a large system, the number of dependencies among modules expands rapidly. Organizing the software into layers with interfaces is an important tool to help you manage complexity and communicate the structure to developers. Layers help with the analysis role played by architecture. They can be used for analyzing the impact of changes to the design. Layering can be strict or non-strict. A strict layering scheme means that components can only use components in the same layer, or layers, immediately below them. A non-strict layering scheme means components can use components in the same, or any lower layer. As a general rule, components should not use components in upper layers. If components have dependencies on components in higher layers, then it is difficult to replace the upper layer components without changing the lower layer components. There are many ways of layering software; Figure 2 shows one possible set of layers. You may need fewer or more layers, depending on the size and complexity of your system. However, avoid schemes with ten or more layers, as they may be overly complex. Figure 2. Software layers When defining layers, describe the responsibilities of each layer. For example, in Figure 2: The DialogueControl layer handles user-system interactions and logic. The BusinessProcessing layer contains application-specific services that handle functional requirements logic and choreography. The BusinessServices layer contains more general business components that may be used in several applications. The Middleware layer contains components such as interfaces to databases and platform-independent operating system services. The SystemSoftware layer contains components such as operating systems and databases. Layers are not the same as tiers. Tier pictures express allocation to machines in a distributed environment, data flow among elements, and the presence and utilization of communication channels. These diagrams are similar to layer diagrams, but tier diagrams tend to show two-way arrows indicating bi-directional communication. Bi-directional communication is discouraged in a layer diagram. Furthermore, assignment of a component to a tier is defined by the required service level characteristics of the system. The main difference between layer diagrams and tier diagrams is that the former has no notion of placement, while the latter does. Figure 3 illustrates the differences between layers and tiers. Figure 3. Layers and tiers
More Information
Concepts | Architectural Pattern Component Layering Logical and Physical Components
Guidelines | Layering
© Copyright IBM Corp. 1987, 2009. All Rights Reserved.