Chapter 4. The Architectural Perspective

FAQ 4.01 What is the purpose of this chapter?

image

To discuss the relationship between software architecture and OO design and OO programming.

It is critical to plan for change in the software system as well as in the people who will be used to construct and maintain the software. Good architecture is the key to planning for and responding to change.

Many of the design and programming principles advocated in this book are rooted in software architecture. For example, an important architectural principle is to reduce unnecessary coupling, and this book discusses how C++ can be used to decrease coupling. Thus it is important to understand the architect's perspective and to know how to translate architectural principles into C++ constructs.

In this book, the term software architecture is used rather broadly to describe several activities that occur early in the development cycle, including domain analysis and defining the logical (rather than physical) organization of the system.

FAQ 4.02 Why is software architecture important?

image

Because it is vital to producing good software.

Good software is correct, usable, maintainable, testable, flexible, documented, solves a meaningful problem, performs well, and has an acceptable cost of ownership. In other words, it gets the job done. It is the job of the system architect(s) to understand and balance a wide range of competing forces (business forces, management forces, and technical forces) and lay the groundwork for the rest of the team to produce good software. If the architecture is inadequate or inappropriate, everyone ends up paying a penalty.

First, every system has an architecture. Either it is explicitly defined, documented, and serves as a solid basis for ongoing system development, or it evolves haphazardly as a by-product of hundreds of ill-considered and inconsistent decisions.

Second, don't believe anyone who says that a system doesn't need an architecture or that time and money can be saved by skipping the definition of the system's architecture. Building a system without an architecture is like building an office building without blueprints—sure, the thing might get finished, but it probably won't fulfill its goals, it will probably cost more than it should, and there is a greater risk that it will collapse.

Third, software architecture techniques, OO methods, design patterns, tools, and programming languages are mature enough that there is no reason for any system to be developed without an adequate architecture.

Fourth, good software does not have to be OO software (gasp!) and does not have to be reusable (gasp again!). Too many projects have suffered from excessive worrying about reuse and not enough worrying about usability. And sometimes the concerns about what someone might want the software to possibly do someday leads to complexity that precludes it ever meeting its immediate requirements.

From an architectural perspective, the moral is to favor conservatism and to realize that common sense should prevail. This profession is tough enough; don't try to accomplish any more than is necessary and don't push the technological envelope without good reason. It is better to err on the conservative side and build a practical system. At least that way you get a chance to live and fight another day. This chapter discusses some of the important issues in making software usable, extensible, and reusable through the use of OO techniques.

FAQ 4.03 What should the architecture be based on, the problem being solved or the problem domain?

image

The problem domain.

One of the primary goals of the software architect is to build a system that will survive changes in requirements and that can be adapted to new and related problems. To achieve this goal the system architecture must have a stable base.

The specification of a single problem that is to be solved is unstable, since it depends on the whims of the customer and therefore is unsuitable as the basis for the system architecture. The problem domain is much more stable, because it is an artifact of the world in which the customer lives.

For example, every order entry system must deal with orders, customers, prices, quantities, payments, addresses, sales reports, and so on. These entities represent the problem domain and are stable across all order entry systems.

However, each particular order entry system has different parameters that reflect the customer's current requirements based on the current business situation, including different placement of fields on the screen, different colors for different fields, different currencies for multinational applications, and so on. Furthermore, some order entry systems are implemented as PC applications, others are implemented as Web-based applications, while others are implemented as Interactive Voice Response systems.

The moral for the software architect is that the system architecture should be based on the problem domain because the needs of customers change more rapidly than their world does.

FAQ 4.04 Should the software architecture be based on the policy of the problem?

No—that would be totally insane.

The policy of any single problem is unstable. Software systems based on the least stable element (the problem) are inflexible, cannot respond to changing requirements, and are doomed to become brittle.

Software should be written so that changing the requirements doesn't break the architecture. Basing the architecture on the most stable element, the problem domain, accomplishes this objective.

Note that software can survive problem changes only within the confines of the problem domain. It's unreasonable to expect a system that was originally designed for the problem domain of compilers to work for cellular telephones, since this would be changing the problem domain rather than just the problem.

From an architectural standpoint, the message is to usually emphasize the problem domain rather than technical infrastructure. However, there are occasional counter examples, and this is why intimate knowledge of both technology and the problem domain is so important.

FAQ 4.05 Do customers ever change their requirements?

Ha, ha, ha! The only customers who don't change their requirements are dead customers. In all of recorded history, no customer has ever changed his/her mind less than twice (and the poor customer who only made two sets of changes was hit by a meteorite on the way to sending in the third set of changes). While it is true that some requirement changes can be avoided with foresight, it is also true that most requirement changes occur for perfectly valid reasons. Between the beginning of a project and the first release, requirements change due to changing market conditions, changing business objectives, competitive pressure, and changing technology. In the longer term (after the first release), requirements change for all the same reasons.

The message here is that changing requirements are a fact of life and the wise team plans for them rather than complaining about them.

FAQ 4.06 Are stable requirements desirable?

No—the only software that doesn't have to be changed is software no one uses.

If the job is done right the first time, people will use the software again. And since everything else in life seems to change rapidly, it is certain that the software will need to be updated, expanded, changed, or revised. The only way to have stable requirements is for the product to be so bad that no one wants to use it. Stable requirements reflect a dead product. Stable requirements are an enemy, not a friend.

The wise architect knows that change is inevitable and has the judgment needed to balance the short-term and long-term requirements in a way that the developers can implement. On the other hand, the developer needs to understand that adding nonrequested flexibility “just in case someone needs it” is not a responsible action.

FAQ 4.07 What is the key to planning for change?

image

Understanding the problem domain.

Almost every OO analysis and design method promotes understanding the problem domain through some form of domain analysis. This is the process of becoming familiar with the problem domain by (among other things) interviewing domain experts, analyzing existing business processes, working with customers, and validating and refining these findings. This process produces a model of the problem domain including domain objects, services provided by these objects, and the interaction patterns of these objects.

The domain model is the extensible, flexible, reusable basis on which the software architecture should be based. The beauty of OO technology and C++ is that public inheritance (see FAQ 2.24, 7.01) can be used to reflect the fundamental, immutable properties of the problem domain and the domain model. In this way, the public inheritance relationships model the problem domain rather than depending on the fickle requirements of the even more fickle customer. Thus the architecture can and should be made to reflect the problem domain rather than the particular problem at hand.

These issues will be discussed at great length later in the book.

The key is to recognize that OO technology provides flexibility when the domain analysis is solid and the software faithfully reflects the domain analysis. Under these circumstances, changing the details of the problem creates incidental disturbances rather than fundamental disruptions.

FAQ 4.08 What is a framework?

image

A framework is a thematic collection of software that is used to build applications.

A framework is a set of class hierarchies plus models of interaction and cooperation between the various objects of the various hierarchies. The framework defines a generic program structure that is suitable for building a group of related applications or systems. Usually the framework provides default behavior for common situations while allowing the default behavior to be easily overridden with application-specific behavior when necessary. That is, the framework is designed to be customized for solving a specific problem or building a specific business application.

In C++, the most important artifacts in the generic program structure are usually abstract base classes (ABCs) (see FAQs 2.24, 17.03). The framework also prescribes the valid interactions among the objects. In C++, the default behavior and the ability to customize the framework is usually accomplished using inheritance and dynamic binding.

FAQ 4.09 What is the “inversion of control” exhibited by frameworks?

image

The Hollywood model: Don't call us, we'll call you.

In traditional applications, the application programmer writes the main event loop and this “main program” reaches out and calls reusable library routines as needed. This is “piecewise reuse”: the idea is to reuse little pieces of software but leave it up to the application programmer to write the main program. In this approach, the called chunks of software are the reusable assets and the main program is the “glue code” that is application specific.

Frameworks are just the opposite: the framework—not the application code—controls the flow of execution, and the framework reaches out and calls the application-specific code written by the application developer as needed. This is made possible because the framework is specially designed to call virtual functions to perform operations that are expected to be application specific. Thus, the application programmer specializes the framework by overriding these virtual functions as necessary (see FAQ 2.24).

This inversion of control is a powerful and useful concept, but it is initially quite uncomfortable for developers and their managers. For some reason, everyone emotionally equates the word “reuse” with calling little chunks of reusable code; they have a hard time seeing that frameworks (where reuse involves a big chunk of reusable code calling small chunks of application-specific code) provide higher degrees of reuse.

FAQ 4.10 What is an extensible, domain-specific framework?

A competitive advantage.

An extensible, domain-specific framework models the key abstractions of the problem domain. Domain-specific frameworks, along with the classes from general-purpose class libraries (see FAQ 28.01), are the building blocks for constructing applications/systems for that problem domain.

An extensible, domain-specific framework should have as much domain-specific knowledge as possible while remaining as independent as possible from any single problem being solved. If there is not enough domain-specific knowledge, future developers must largely rediscover the problem domain. If it has too much problem-specific knowledge, future developers will always be fighting the problem-specific assumptions.

FAQ 4.11 What characteristics make a framework extensible yet domain-specific?

image

Mechanism rich, policy free.

In this context, mechanism refers to anything (information, data, procedures, processes) that is intrinsic to the problem domain; policy refers to anything that is likely to change or to be application specific. Examples of mechanism in order processing systems might include payment methods such as purchase orders, cash, cash on delivery, and credit cards, whereas the interest rate for late payment might be an example of policy.

So the ideal extensible, domain-specific framework is rich in the mechanism of the problem domain but free from policy within the problem. This makes it a suitable basis for a wide range of applications without forcing every organization to adopt the same policies. If it isn't mechanism rich, future developers won't get as much “oomph” (a technical term) as they might otherwise. If it isn't policy free, future developers will have to work around the obsolete policy.

Deciding what is mechanism and what is policy is an art. Within an extensible framework for order processing systems, is assuming that all transactions can be processed in a single currency an example of mechanism or policy? Clearly, this is situation specific. For some organizations this assumption is perfectly reasonable and it can be built into the mechanism of the framework. For other organizations the currency might change from transaction to transaction, in which case the decision of which currency to use is a policy decision that should not be built into the mechanism of the framework.

FAQ 4.12 What happens if the domain analysis is incorrect?

It costs money.

Once a domain analysis mistake has been discovered, randomly patching the code makes matters worse. Instead of patching code, fix the domain analysis error. Unfortunately, fixing domain analysis errors often breaks existing code.

Even though changing existing code is expensive, it is often far more expensive to continue building the software based on a faulty domain analysis. Domain analysis errors usually make software brittle.

That's why it has been said that domain-analysis errors are ten times more costly to fix than programming errors. If you must make changes, sooner is often much cheaper than later.

FAQ 4.13 How much effort should be expended to support change—that is, how much is extensibility worth?

It depends on the specific situation, but don't focus on supporting change to the point that the project won't finish on time.

An extensible product isn't worth much if it has no users. On the other hand, having lots of users but inflexible software means that enhancing and maintaining the software will be an expensive proposition. In today's rapidly changing business climate it can be deadly to have an inflexible software product. It's a delicate balancing act.

Here is a real-life example that illustrates this issue. Two organizations had similar products. One used OO technology to achieve extensibility (a new release every six months); the other shipped a new release every two years. Not only did the rapid-fire organization create four times as many sales opportunities per customer than its slower counterpart, it also used its enhanced features to become the market leader.

The only software that never changes is software that no one uses. Successful software will need to be changed. The hard decision is the judgment call as to the risk/reward ratio for investing in future extensibility. Once this decision has been made, it is important that the developer not undo the decision by gratuitously enhancing the system without authorization. Too many developers add flexibility to the software just because it can be done, paying no attention to whether it should be done.

FAQ 4.14 How does an architect make the software architecture flexible?

image

Intentionally.

The main message here is that flexibility is not something that comes automatically, even with OO. The other message is that it is not possible to create infinitely flexible software without introducing unmanageable complexity, so the only alternative is to rely on knowledge of the problem domain to make wise choices.

Here's a way to do it.

  1. Write down the specific places where the architects and analysts think the software needs to be flexible. Make sure the list isn't too long.
  2. Throw out everything on the list that a user/customer wouldn't pay real money for. Usually this means discarding all the “technical flexibility spots” such as swapping out class libraries, since customers are usually willing to pay only for things that affect the external behavior, not the internal implementation of external behavior. Again, make sure the list isn't too long.
  3. Do a cost/benefit analysis on each of the remaining line items. Get the customer to add whatever survives this analysis to the “Nonfunctional Requirements Specification” or other appropriate document, just to make sure the customer realizes what's going on.

Don't try to create software that's like a rubber band—flexible in every conceivable direction. Instead, identify a few specific places where the system needs be flexible and do a good job with those places. If you get this point wrong, you'll end up with massive unnecessary complexity and your project will probably fail.

FAQ 4.15 What is the secret to achieving reuse?

image

Building a reuse culture.

Some aspects of reuse are technical (such as carrying out successful domain analysis and building extensible, domain-specific frameworks), but the real problems come from human issues. Developers need to lose the attitude that says, “I want to build my own infrastructure because it's more fun and enhances my career” and “I don't trust or want to understand someone else's work, so I'll do everything from scratch.” If the human issues aren't resolved, the technology questions become immaterial.

Enlightened leadership and an appropriate reward system can sometimes overcome these problems, but sometimes the project team itself can foster the right attitude. In one case the developers decided that working together was important, and they used the word “big” to describe people and actions that contributed to reuse (as in “That is big of you”) and conversely the word “small” to describe people and actions that were petty or self-centered. Thus the words “big” and “small” became an informal mechanism for the team to enforce and reinforce their culture in a reasonably nonthreatening way.

The architectural perspective is to recognize that reuse is much more than a technical question and that there are inherent limits on what is possible. There is no point in investing development effort to achieve reuse if the organizational culture will keep the reuse from actually occurring.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset