So far, we have considered architecture in general and looked at how software architecture is both similar to and different from architecture in other domains. We now turn our attention to the “how” of software architecture. Where should the architect focus her attention when she is creating the architecture for a software system?
That’s right—the first concern of a software architect is not the functionality of the system.
For example, if we offer to hire you to develop the architecture for a “web-based application,” would you start by asking us about page layouts and navigation trees, or would you ask us questions such as:
Who will host it? Are there technology restrictions in the hosting environment?
Do you want to run on a Windows Server or on a LAMP stack?
How many simultaneous users do you want to support?
How secure does the application need to be? Is there data that we need to protect? Will the application be used on the public Internet or a private intranet?
Can you prioritize these answers for me? For example, is number of users more important than response time?
Depending on our answers to these and a few other questions, you can begin sketching out an architecture for the system. And we still haven’t talked about the functionality of the application.
Now, admittedly, we cheated a bit here because we asked for a “web-based application,” which is a well-understood domain, so you already knew what decisions would have the most influence on your architecture. Similarly, if we had asked for a telecommunications system or an avionics system, an architect experienced in one of those domains would have some notion of required functionality in mind. But still, you were able to begin creating the architecture without worrying too much about the functionality. You did this by focusing on quality concerns that needed to be satisfied.
Quality concerns specify the way in which the functionality must be delivered in order to be acceptable to the system’s stakeholders, the people with a vested interest in the outcome of the system. Stakeholders have certain concerns that the architect must address. Later, we will discuss concerns that are typically raised when trying to assure that the system has the required qualities. As we said earlier, one role of the architect is to ensure that the design of the system will meet the needs of the client, and we use quality concerns to help us understand those needs.
This example highlights two key practices of successful architects: stakeholder involvement and a focus on both quality concerns and functionality. As the architect, you began by asking us what we wanted from the system, and in what priority. In a real project, you would have sought out other stakeholders. Typical stakeholders and their concerns include:
Funders, who want to know if the project can be completed within resource and schedule constraints
Architects, developers, and testers, who are first concerned with initial construction and later with maintenance and evolution
Project managers, who need to organize teams and plan iterations
Marketers, who may want to use quality concerns to differentiate the system from competitors
Users, including end users, system administrators, and the people who do installation, deployment, provisioning, and configuration
Technical support staff, who are concerned with the number and complexity of Help Desk calls
Every system has its own set of quality concerns. Some, such as performance, security, and scalability, may be well-specified, but other, often equally important concerns, such as changeability, maintainability, and usability, may not be defined with enough detail to be useful. Odd, isn’t it, that stakeholders want to put functions in software and not hardware so that they can be easily and quickly modified, and then often give short shrift to changeability when stating their quality concerns? Architecture decisions will have an impact on what kinds of changes can be done easily and quickly and what changes will take time and be hard to do. So shouldn’t an architect understand his stakeholders’ expectations for qualities such as “changeability” as well as he understands the functional requirements?
Once the architect understands the stakeholders’ quality concerns, what does she do next? Consider the trade-offs. For example, encrypting messages improves security but hurts performance. Using configuration files may increase changeability but could decrease usability unless we can verify that the configuration is valid. Should we use a standard representation for these files, such as XML, or invent our own? Creating the architecture for a system involves making many such difficult trade-offs.
The first task of the architect, then, is to work with stakeholders to understand and prioritize quality concerns and constraints. Why not start with functional requirements? Because there are usually many possible system decompositions. For example, starting with a data model would lead to one architecture, whereas starting with a business process model might lead to a different architecture. In the extreme case, there is no decomposition, and the system is developed as a monolithic block of software. This might satisfy all functional requirements, but it probably will not satisfy quality concerns such as changeability, maintainability, or scalability. Architects often must do architecture-level refactoring of a system, for example to move from simplex to distributed deployment, or from single-threaded to multithreaded in order to meet scalability or performance requirements, or hardcoded parameters to external configuration files because parameters that were never going to change now need to be modified.
Although there are many architectures that can meet functional requirements, only a subset of these will also satisfy quality requirements. Let’s go back to the web application example. Think of the many ways to serve up web pages—Apache with static pages, CGI, servlets, JSP, JSF, PHP, Ruby on Rails, or ASP.NET, to name just a few. Choosing one of these technologies is an architecture decision that will have significant impact on your ability to meet certain quality requirements. For example, an approach such as Ruby on Rails might provide the fast time-to-market benefit, but could be harder to maintain as both the Ruby language and the Rails framework continue to evolve rapidly. Or perhaps our application is a web-based telephone and we need to make the phone “ring.” If you need to send true asynchronous events from the server to the web page to satisfy performance requirements, an architecture based on servlets might be more testable and modifiable.
In real-world projects, satisfying stakeholder concerns requires many more decisions than simply selecting a web framework. Do you really need an “architecture,” and do you need an “architect” to make the decisions? Who should make them? Is it the coder, who may make many of them unintentionally and implicitly, or is it the architect, who makes them explicitly with a view in mind of the entire system, its stakeholders, and its evolution? Either way, you will have an architecture. Should it be explicitly developed and documented, or should it be implicit and require reading of the code to discover?
Often, of course, the choice is not so stark. As the size of the system, its complexity, and the number of people who work on it increase, however, those early decisions and the way that they are documented will have greater and greater impact.
We hope you understand by now that architecture decisions are important if your system is going to meet its quality requirements, and that you want to pay attention to the architecture and make these decisions intentionally rather than just “letting the architecture emerge.”
What happens when the system is very large? One of the reasons that we apply architecture principles such as “divide and conquer” is to reduce complexity and enable work to proceed in parallel. This allows us to create larger and larger systems. Can the architecture itself be decomposed into parts, and those parts worked on by different people in parallel? In considering computer architecture, Gerrit Blaauw and Fred Brooks asserted:
...if, after all techniques to make the task manageable by a single mind have been applied, the architectural task is still so large and complex that it cannot be done in that way, the product conceived is too complex to be usable and should not be built. In other words, the mind of a single user must comprehend a computer architecture. If a planned architecture cannot be designed by a single mind, it cannot be comprehended by one. (1997)
Do you need to understand all aspects of an architecture in order to use it? An architecture separates concerns so, for the most part, the developer or tester using the architecture to build or maintain a system does not need to deal with the entire architecture at once, but can interact with only the necessary parts to perform a given function. This allows us to create systems larger than a single mind can comprehend. But, before we completely ignore the advice of the people who built the IBM System/360, one of the longest-lived computer architectures, let’s look at what prompted them to make this statement.
Fred Brooks said that conceptual integrity is the most important attribute of an architecture: “It is better to have a system...reflect one set of design ideas, than to have one that contains many good but independent and uncoordinated ideas” (1995). It is this conceptual integrity that allows a developer who already knows about one part of a system to quickly understand another part. Conceptual integrity comes from consistency in things such as decomposition criteria, application of design patterns, and data formats. This allows a developer to apply experience gained working in one part of the system to developing and maintaining other parts of the system. The same rules apply throughout the system. As we move from system to “system-of-systems,” the conceptual integrity must also be maintained in the architecture that integrates the systems, for example by selecting an architecture style such as publish/subscribe message bus and then applying this style uniformly to all system integrations in the system-of-systems.
The challenge for an architecture team is to maintain a single-mindedness and a single philosophy as they go about creating the architecture. Keep the team as small as possible, work in a highly collaborative environment with frequent communication, and have one or two “chiefs” act as benevolent dictators with the final say on all decisions. This organizational pattern is commonly seen in successful systems, whether corporate or open source, and results in the conceptual integrity that is one of the attributes of a beautiful architecture.
Good architects are often formed by having better architects mentor them (Waldo 2006). One reason may be that there are certain concerns that are common to nearly all projects. We have already alluded to some of them, but here is a more complete list, with each concern phrased as a question that the architect may need to consider during the course of a project. Of course, individual systems will have additional critical concerns.
What functionality does the product offer to its users?
What changes may be needed in the software in the future, and what changes are unlikely and need not be especially easy to make in the future?
What will the performance of the product be?
How many users will use the system simultaneously? How much data will the system need to store for its users?
What interactions will the system have with other systems in the ecosystem in which it will be deployed?
How is the task of writing the software organized into work assignments (modules), particularly modules that can be developed independently and that suit each other’s needs precisely and easily?
How can the software be built as a set of components that can be independently implemented and verified? What components should be reused from other products and which should be acquired from external suppliers?
If the product will exist in several variations, how can it be developed as a product line, taking advantage of the commonality among the versions, and what are the steps by which the products in the product line can be developed (Weiss and Lai 1999)? What investment should be made in creating a software product line? What is the expected return from creating the options to develop different members of the product line?
In particular, is it possible to develop the smallest minimally useful product first and then develop additional members of the product line by adding (and subtracting) components without having to change the code that was written previously?
If the product requires authorization for its use or must restrict access to data, how can security of data be ensured? How can “denial of service” and other attacks be withstood?
Finally, a good architect realizes that the architecture affects the organization. Conway noted that the structure of a system reflects the structure of the organization that built it (1968). The architect may realize that Conway’s Law can be used in reverse. In other words, a good architecture may influence an organization to change so as to be more efficient in building systems derived from the architecture.