11.3 Steps to Establish an Architecture Baseline
A good architecture should be established as early as possible. Even in theory, it is very difficult to change a poor architecture into a good one with incremental techniques such as refactoring. In practice, it is extremely difficult. This is not to say that refactoring is not useful, but it is much better to begin with an initial structure that is relatively good. Otherwise, the cost of refactoring is too high for any business-oriented manager to accept, and he or she will typically opt for quick fixes instead. So, a good architecture needs to be created when the cost of creating it is small or even non-existent. Prioritization of architectural work has a good return on investment. It reduces the need for redesign and minimizes throwaway work during the remainder of the project. Having achieved a good initial structure, you can continually evaluate the architecture and make the necessary refinements and refactorings.
The architecture is manifested as an early version of the final system known as an architecture baseline. The architecture baseline is a subset of the entire system, so we call it the skinny system. This skinny system has versions of all the models that the full-fledged system has at the end of the project. It includes the same skeleton of subsystems, components, and nodes, but not all the musculature is in place. However, they do have behavior, and they are executable code. The skinny system evolves to become the full-fledged system, perhaps with some minor changes to the structure and behavior. The changes are minor because, at the end of the elaboration or architectural iterations, we have by definition a stable architecture; otherwise, the elaboration phase must continue until we know that this goal has been achieved. There is a systematic way to do this.
Even though the skinny system (the architecture baseline) usually only includes 5 to 15 percent of the final code, it is enough to validate the key decisions you have made. More importantly, you need to be assured that the skinny system can grow to become the complete system. The skinny system is accompanied by a paper product called the architecture description. But now, this paper product is verified and validated through the architecture baseline.
Use Cases Drive the Architecture Baseline
The establishment of the architecture baseline is driven by a critical subset of use cases. We call this subset the architecturally significant use cases. Before you can identify the architecturally significant use cases, you must first identify all the use cases for the system—at least to the best of your knowledge with the available information. Please note that identifying use cases is not the same as specifying use cases. Identifying is about scoping and exploring and finding what the system needs to do. Specifying use cases is about detailing the flows and the steps in the use case. Specifying use cases is allocated across the project lifecycle. However, identifying the use cases can and must be done early.
From these identified use cases, you determine which among them are important—important in the sense that together they cover all the key decisions you need to make:
- They exercise key functionalities and characteristics of the system.
- They have a large coverage in terms of the various risks that you face concerning functionality, infrastructure, platform specifics, and so on.
- They stress some delicate or risky parts of the system.
- They are the basis for the rest of the system to be developed.
Architecturally significant use cases involve use cases of different kinds. After all, each use case captures a different set of stakeholder concerns and requires different decisions to be made. Your list of architecturally significant use cases will therefore involve a combination of both application and infrastructure use cases. You might find this in your system use cases that are technically similar and have similar interaction patterns. In that circumstance, you need to choose just one use case as a representative, since the moment you can solve one of them, you can solve the others. For example, the Check In Customer and Check Out Customer use cases are similar, so you choose just one of them to serve as an architecturally significant use case.
Once you have identified the architecturally significant use cases, you can explore the critical scenarios within them. As you analyze the use case scenarios, you get a better understanding of what the system needs to do and how the elements in the system should interact with each other. Through that understanding, you define and evaluate the architecture. This proceeds iteratively until you achieve a stable architecture. By stable, we mean that key risks in the system have been resolved, and the decisions made are a sufficient basis for you to develop the rest of the system.
The architecture is influenced not only by the architecturally significant use cases, but also by the platform, legacy systems that the system needs to be integrated to, standards and policies, distribution needs, middleware and frameworks used, and so on. Even then, use cases are still useful for evaluating the architecture. You analyze each use case in the context of the chosen platform, the chosen middleware, the chosen distribution structure, and so on. In this way, you can evaluate whether the choices you have made are sufficient and discover where improvements need to be made.
Establish the Architecture Baseline Iteratively
For a complex system, it takes several iterations before you finally establish a stable architecture. Since these iterations focus on developing the architecture, they are also called the architectural iterations. In Unified Process terminology, these iterations are known as elaboration iterations.
You must address all architectural concerns in each architectural iteration. You may not be successful at resolving all of them in each architectural iteration, but you need to consider all of them. Each architectural iteration produces an increment that resolves some of these architectural concerns.
The iterations proceed until all architectural concerns have indeed been resolved. At the end of these architectural iterations, you have an early version of the system (a skinny system) that is executable. It is supported by test and execution results, so it is verified and validated.
The version of the system at this point is the architecture baseline. Thus, the architecture is an early version of the system that demonstrates how architectural concerns are resolved. Since the system comprises a set of models, the architecture baseline is also represented by a version of these models. The architecture baseline is accompanied by an architecture description, which is an extract of the models.
The architecture description serves as a guide for the whole development team through the lifetime of the system. The architecture description is the reference to be followed by the developers in subsequent iterations of the project.
The architecture description is also reviewed by stakeholders to determine if the architecture is indeed feasible. Attached to the architecture description (and basically to every artifact) is a history sheet that explains the system's evolution. It may also explain important decisions.
You normally find the architecture description developed concurrently, often ahead of the activities that result in the versions of the models that are parts of the architecture baseline. It is to be updated in iterations following the architecture baseline.
During architectural iterations, progress is relatively slow because you need time to make decisions. Once you have gone past the architectural iterations, productivity will shoot up significantly, so the time devoted to iterations is well spent.
Before we discuss architecture description, we need to present the concepts that will help you understand it. Since the architecture description is such an important artifact, we devote an entire chapter to it (see Chapter 18, "Describing the Architecture").