Guiding Quality Design Decisions
Recall that one can view an architecture as the result of applying a collection of design decisions. What we present here is a systematic categorization of these decisions so that an architect can focus attention on those design dimensions likely to be most troublesome.
The seven categories of design decisions are
1. Allocation of responsibilities
2. Coordination model
3. Data model
4. Management of resources
5. Mapping among architectural elements
6. Binding time decisions
7. Choice of technology
These categories are not the only way to classify architectural design decisions, but they do provide a rational division of concerns. These categories might overlap, but it’s all right if a particular decision exists in two different categories, because the concern of the architect is to ensure that every important decision is considered. Our categorization of decisions is partially based on our definition of software architecture in that many of our categories relate to the definition of structures and the relations among them.
Allocation of Responsibilities
Decisions involving allocation of responsibilities include the following:
■■ Identifying the important responsibilities, including basic system functions, architectural infrastructure, and satisfaction of quality attributes.
■■ Determining how these responsibilities are allocated to nonruntime and runtime elements (namely, modules, components, and connectors).
Strategies for making these decisions include functional decomposition, modeling realworld objects, grouping based on the major modes of system operation, or grouping based on similar quality requirements: processing frame rate, security level, or expected changes.
In Chapters 5–11, where we apply these design decision categories to a number of important quality attributes, the checklists we provide for the allocation of responsibilities category is derived systematically from understanding the stimuli and responses listed in the general scenario for that QA.
Software works by having elements interact with each other through designed mechanisms. These mechanisms are collectively referred to as a coordination model. Decisions about the coordination model include these:
■■ Identifying the elements of the system that must coordinate, or are prohibited from coordinating.
■■ Determining the properties of the coordination, such as timeliness, currency, completeness, correctness, and consistency.
■■ Choosing the communication mechanisms (between systems, between our system and external entities, between elements of our system) that realize those properties. Important properties of the communication mechanisms include stateful versus stateless, synchronous versus asynchronous, guaranteed versus nonguaranteed delivery, and performancerelated properties such as throughput and latency.
Every system must represent artifacts of systemwide interest—data—in some internal fashion. The collection of those representations and how to interpret them is referred to as the data model. Decisions about the data model include the following:
■■ Choosing the major data abstractions, their operations, and their properties. This includes determining how the data items are created, initialized, accessed, persisted, manipulated, translated, and destroyed.
■■ Compiling metadata needed for consistent interpretation of the data.
■■ Organizing the data. This includes determining whether the data is going to be kept in a relational database, a collection of objects, or both. If both, then the mapping between the two different locations of the data must be determined.
Management of Resources
An architect may need to arbitrate the use of shared resources in the architecture. These include hard resources (e.g., CPU, memory, battery, hardware buffers, system clock, I/O ports) and soft resources (e.g., system locks, software buffers, thread pools, and nonthreadsafe code).
Decisions for management of resources include the following:
■■ Identifying the resources that must be managed and determining the limits for each.
■■ Determining which system element(s) manage each resource.
■■ Determining how resources are shared and the arbitration strategies employed when there is contention.
■■ Determining the impact of saturation on different resources. For example, as a CPU becomes more heavily loaded, performance usually just degrades fairly steadily. On the other hand, when you start to run out of memory, at some point you start paging/swapping intensively and your performance suddenly crashes to a halt.
Mapping among Architectural Elements
An architecture must provide two types of mappings. First, there is mapping between elements in different types of architecture structures—for example, mapping from units of development (modules) to units of execution (threads or processes). Next, there is mapping between software elements and environment elements—for example, mapping from processes to the specific CPUs where these processes will execute.
Useful mappings include these:
■■ The mapping of modules and runtime elements to each other—that is, the runtime elements that are created from each module; the modules that contain the code for each runtime element.
■■ The assignment of runtime elements to processors.
■■ The assignment of items in the data model to data stores.
■■ The mapping of modules and runtime elements to units of delivery.
Binding Time Decisions
Binding time decisions introduce allowable ranges of variation. This variation can be bound at different times in the software life cycle by different entities— from design time by a developer to runtime by an end user. A binding time decision establishes the scope, the point in the life cycle, and the mechanism for achieving the variation.
The decisions in the other six categories have an associated binding time decision. Examples of such binding time decisions include the following:
■■ For allocation of responsibilities, you can have buildtime selection of modules via a parameterized makefile.
■■ For choice of coordination model, you can design runtime negotiation of protocols.
■■ For resource management, you can design a system to accept new peripheral devices plugged in at runtime, after which the system recognizes them and downloads and installs the right drivers automatically.
■■ For choice of technology, you can build an app store for a smartphone that automatically downloads the version of the app appropriate for the phone of the customer buying the app.
When making binding time decisions, you should consider the costs to implement the decision and the costs to make a modification after you have implemented the decision. For example, if you are considering changing platforms at some time after code time, you can insulate yourself from the effects caused by porting your system to another platform at some cost. Making this decision depends on the costs incurred by having to modify an early binding compared to the costs incurred by implementing the mechanisms involved in the late binding.
Choice of Technology
Every architecture decision must eventually be realized using a specific technology. Sometimes the technology selection is made by others, before the intentional architecture design process begins. In this case, the chosen technology becomes a constraint on decisions in each of our seven categories. In other cases, the architect must choose a suitable technology to realize a decision in every one of the categories.
Choice of technology decisions involve the following:
■■ Deciding which technologies are available to realize the decisions made in the other categories.
■■ Determining whether the available tools to support this technology choice (IDEs, simulators, testing tools, etc.) are adequate for development to proceed.
■■ Determining the extent of internal familiarity as well as the degree of external support available for the technology (such as courses, tutorials, examples, and availability of contractors who can provide expertise in a crunch) and deciding whether this is adequate to proceed.
■■ Determining the side effects of choosing a technology, such as a required coordination model or constrained resource management opportunities.
■■ Determining whether a new technology is compatible with the existing technology stack. For example, can the new technology run on top of or alongside the existing technology stack? Can it communicate with the existing technology stack? Can the new technology be monitored and managed?