Chapter 1: Fundamentals of Application Architecture
J.D. Meier, Alex Homer, David Hill, Jason Taylor, Prashant Bansode, Lonnie Wall, Rob Boucher Jr, Akshay Bogawat
- Learn the fundamental concepts of application architecture.
- Understand key application architecture terms and principles.
- Learn about the key forces shaping today’s architectural landscape.
Application architecture is the process of defining a structured solution that meets all of the technical and operational requirements, while optimizing common quality attributes such as performance, security, and manageability. It involves a series of decisions based on a wide range of factors, and each of these decisions can have considerable impact on the quality, performance, maintainability, and overall success of the application. By following the processes described in this guide, and using the information it contains, you will be able to construct architectural solutions that address all of the relevant concerns, can be deployed on your chosen infrastructure, and provide results that meet the original aims and objectives.
This chapter lays a foundation for practical application architecture. It starts by describing architecture and design at a high level and then dives deeper into specific aspects of application architecture and design. The remainder of the guide follows the same approach. Finally, this chapter defines key terms and principles related to application architecture. Understanding these will help you gain the most benefit from this guide and be more successful as an application architect. After you work through his chapter, you will understand the overall techniques and goals of application architecture and design, the major factors you must consider, and the different ways that you can approach application design. This will help you to understand concepts such as architectural and application styles, quality attributes and cross-cutting concerns, and analyzing and representing architecture.
What Is Application Architecture?
Software architecture is often defined as the structure or structures of a system. Several well-known industry experts have expanded that definition with information on the decisions that must be made related to architecture. Here we look at a few somewhat formal definitions of architecture, and then take a more informal view.
Kruchten, Booch, Bittner, and Reitman on Architecture
Philippe Kruchten, Grady Booch, Kurt Bittner, and Rich Reitman derived and refined a definition of architecture based on work by Mary Shaw and David Garlan (Shaw and Garlan 1996). Their definition is:
“Software architecture encompasses the set of significant decisions about the organization of a software system including:
Selection of the structural elements and their interfaces by which the system is composed.
Behavior as specified in collaboration among those elements.
Composition of these structural and behavioral elements into larger subsystems.
Architectural style that guides this organization.
Software architecture also involves functionality, usability, resilience, performance, reuse, comprehensibility, economic and technology constraints, tradeoffs and aesthetic concerns.”
Fowler on Architecture
In Patterns of Enterprise Application Architecture
, Martin Fowler outlines some common recurring themes when explaining architecture:
- The highest-level breakdown of a system into its parts.
- The decisions that are hard to change.
- There are multiple architectures in a system.
- What is architecturally significant can change over a system’s lifetime.
- In the end, architecture boils down to whatever the important stuff is.
Bass, Clements, and Kazman on Architecture
In Software Architecture in Practice (2nd edition)
, Bass, Clements, and Kazman define architecture as follows:
“The software architecture of a program or computing system is the structure or structures of the system, which comprise software elements, the externally visible properties of those elements, and the relationships among them. Architecture is concerned with the public side of interfaces; private details of elements—details having to do solely with internal implementation—are not architectural.”!!! Why Do We Need Architecture?
Like any other complex structure, software must be built on a solid foundation. Failing to consider key scenarios, failing to design for common problems, or failing to appreciate the long-term consequences of key decisions can put your application at risk. Modern tools and platforms help to simplify the tasks of building applications, but they do not replace the requirement to design your application based on your specific scenarios. The risks exposed by poor architecture include software that is unstable, is unable to support business requirements, or could even prevent the application from working when deployed into a production environment.
Consider the following high-level concerns when thinking about software architecture:
- How will the application be deployed into production?
- How will the users be using the application?
- What are the quality attribute requirements, such as security, performance, concurrency, internationalization, and configuration?
- What are the architectural trends that might impact your application now or after it has been deployed?
Architecture vs. Design
According to Martin Fowler in the “Who Needs an Architect?” available at http://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=01231144
“…the expert developers working on that project have a shared understanding of the system design. This shared understanding is called ’architecture.’ This understanding includes how the system is divided into components and how the components interact through interfaces. These components are usually composed of smaller components, but the architecture only includes the components and interfaces that are understood by all the developers.”
Therefore architecture focuses on how components and interfaces are used by or interact with other components. Selecting data structures or algorithms implemented within the components is not an architectural concern. Rather than use hard-and-fast rules to distinguish between architecture and design, it makes sense to combine these two areas. In some cases, decisions are clearly more architectural in nature. In other cases, the decisions are more about design, and how they help you to realize that architecture.
User, Business, and System Goals
Systems should be architected with consideration for the user, the system, and the business goals. For each of these areas, outline key scenarios, important quality attributes (for example, maintainability), key satisfiers, and key dissatisfiers. When possible, develop and consider metrics that measure success in each of these areas.
Figure 1 User, business, and system goals*
Tradeoffs are likely between each area, and a balance point must be found. For example, responsiveness might be a major user goal, but the system administrator is not willing to invest in the hardware required to meet that goal for 100 percent of the time. A balance point might be to meet the goal only 80 percent of the time.
The Goals of Architecture
Application architecture seeks to build a bridge between business requirements and technical requirements by understanding use cases, and then finding ways to implement those use cases in the software. The goal of architecture is to identify the requirements that impact the structure of the application. Good architecture reduces the business risks associated with building a technical solution. A good design is sufficiently flexible to be able to handle the natural drift that will occur over time in hardware and software technology, as well as in user scenarios and requirements. An architect must consider the overall impact of design decisions, the inherent tradeoffs between quality attributes (such as performance and security), and the tradeoffs required to address user, system, and business requirements.
Keep in mind that the architecture should:
- Expose the structure of the system but hide the implementation details.
- Realize all of the use-case scenarios.
- Try to address the concerns of various stakeholders.
- Handle both functional and quality requirements.
Approach to Architecture
There are key decisions that must be addressed with any architecture, regardless of your architectural approach. At a minimum, you must determine the type of application that you are building, the architectural styles that will be used, and how you will handle cross-cutting concerns. Throughout this guide, we use an architectural baseline for framing out the different areas that must be addressed in your architecture. The architectural baseline is shown in the following diagram.inage:ArchMetaFrame.PNG Figure 2 The architecture meta-frame
In addition to the architectural baseline, you can use the following approach to help define your architecture. The first step is to identify the type of application you plan to build. Next, you must understand how the application will be deployed. Once you know what type of application you are building and how it will be deployed, you can start to drill down into the architecture to identify styles and technologies that you will use. Finally, you must consider how quality attributes and cross-cutting concerns will be incorporated into the design of your system.
Choosing the right application type is the key part of the process of designing and architecting an application. Your choice of an appropriate application type is governed by your specific requirements and infrastructure limitations. This guide covers the following application types:
- Mobile applications designed for mobile devices.
- Rich client applications designed to run primarily on a client PC.
- Rich Internet applications designed to be deployed from the Internet, which support rich user interface (UI) and media scenarios.
- Service applications designed to support communication between loosely coupled components.
- Web applications designed to run primarily on the server in fully connected scenarios.
When you design your application architecture, you must take into account corporate policies and procedures, together with the infrastructure on which you plan to deploy your application. Whether or not the target environment is inflexible, your application design must accommodate any restrictions that exist in that environment. Your application design must also take into account quality attributes such as security, performance, and maintainability. Sometimes you must make design tradeoffs due to protocol restrictions and network topologies.
Identify the requirements and constraints that exist between the application architecture and infrastructure architecture early in the design process. This helps you to choose an appropriate deployment topology, and to resolve conflicts between the application and infrastructure architecture early in the process.
An architectural style is a set of principles. Each style defines a set of rules that specify the kinds of components you can use to assemble a system, the kinds of relationships used in their assembly, constraints on the way they are assembled, and assumptions about the meaning of how you put them together. Examples of architectural styles are client/server, component-based, layered architecture, message-bus, Separated Presentation, 3-tier/N-tier, object-oriented, and service-oriented architecture (SOA). Many factors can influence your choice of architectural styles. These include the capacity of your organization for design and implementation, the capabilities and experience of developers, and the infrastructure constraints and deployment scenarios available.
When choosing technologies for your application, the key factors to consider are the type of application you are developing and your preferred options for application deployment topology and architectural styles. Your choice of technologies will also be governed by organization policies, infrastructure limitations, resource skills, and so on. You must compare the capabilities of the technologies you choose against your application requirements, taking into account all of these factors before making decisions
Quality attributes—such as security, performance, and maintainability—can be used to focus your thinking around the critical problems that your design should solve. Depending on your requirements, you might need to consider every quality attribute covered in this guide, or you might only need to consider a subset. For example, every application design must consider security and performance, but not every design needs to consider interoperability or scalability. Understand your requirements and deployment scenarios first so that you know which quality attributes are important for your design. Keep in mind that quality attributes may conflict; for example, security often requires a tradeoff against performance or usability. Analyze and understand the key tradeoffs when designing for security attributes so that side effects do not become obvious later.
When designing to accommodate quality attributes, consider the following guidelines:
- Quality attributes are system properties that are separate from the functionality of the system.
- From a technical perspective, implementing quality attributes can differentiate a good system from a bad one.
- There are two types of quality attributes: those that are measured at run time, and those that can only be estimated through inspection.
- Analyze the tradeoffs between quality attributes.
Questions you should ask when considering quality attributes include:
- What are the key quality attributes required for your application? Identify them as part of the design process.
- What are the key requirements for addressing these attributes? Are they actually quantifiable?
- What are the acceptance criteria that will indicate that you have met the requirements?
Cross-cutting concerns represent key areas of your design that are not related to a specific layer in your application. For example, you might want to cache data in the presentation layer, the business layer, and the data access layer. In such a case you will also need to design an exception-management framework that will work within each layer and across the layers as exceptions are propagated through the system. In addition, you should design logging so that each layer can log to a common store and the results can be correlated, and you should design a communication approach that you can use to communicate between the layers. Because authentication and authorization concerns also exist across multiple layers, you must determine how to pass identities and grant access to resources through the system.
The following list describes the key cross-cutting concerns that you must consider when architecting your applications:
- Authentication. Determine how to authenticate your users and pass authenticated identities across the layers.
- Authorization. Ensure proper authorization with appropriate granularity within each layer, and across trust boundaries.
- Caching. Identify what should be cached, and where to cache, to improve your application’s performance and responsiveness. Ensure that you consider Web farm and application farm issues when designing caching.
- Communication. Choose appropriate protocols, reduce calls across the network, and protect sensitive data passing over the network.
- Exception management. Catch exceptions at the boundaries. Do not reveal sensitive information to end users.
- Instrumentation and logging. Instrument all of the business- and system-critical events, and log sufficient details to recreate events in your system. Do not log sensitive information.
Designing Your Architecture
Modern thinking on architecture assumes that your design will evolve over time and that you cannot know everything you need to know up front in order to fully architect your system. Your design will generally need to evolve during the implementation stages of the application as you learn more, and as you test the design against real-world requirements. Create your architecture with this evolution in mind so that it will be agile in terms of adapting to requirements that are not fully known at the start of the design process.
Consider the following questions as you create an architectural design with agility in mind:
- What are the foundational parts of the architecture that represent the greatest risk if you get them wrong?
- What are the parts of the architecture that are most likely to change, or whose design you can delay until later with little impact?
- What are your key assumptions, and how will you test them?
- What conditions may require you to refactor the design?
Do not attempt to over-engineer the architecture, and do not make assumptions that you cannot verify. Instead, keep your options open for future change, and do not paint yourself into a corner. There will be aspects of your design that you must fix early in the process, which may represent significant cost if redesign is required. Identify these areas quickly and invest the time necessary to get them right.
Key Architecture Principles
Consider the following key principles when designing your architecture:
- Build to change over build to last. Wherever possible, design your application so that it can change over time to address new requirements and challenges.
- Model to analyze and reduce risk. Use threat models to understand risks and vulnerabilities. Use design tools and modeling systems such as Unified Modeling Language (UML) where appropriate.
- Models and views are a communication and collaboration tool. Efficient communication of design principles and design changes is critical to good architecture. Use models and other visualizations to communicate your design efficiently and to enable rapid communication of changes to the design.
- Identify key engineering decisions.** Use the architecture frame in this guide to understand the key engineering decisions and the areas where mistakes are most often made. Invest in getting these key decisions right the first time so that the design is more flexible and less likely to be broken by changes.
Incremental and Iterative Approach to Architecture
Consider using an incremental and iterative approach to refining your architecture. Do not try to get it all right the first time—design just as much as you can in order to start testing the design against requirements and assumptions. Iteratively add details to the design over multiple passes to make sure that you get the big decisions right first, and then focus on the details. A common pitfall is to dive into the details too quickly and get the big decisions wrong by making incorrect assumptions, or by failing to evaluate your architecture effectively.
Use baseline architectures to get the big picture right, and use candidate architectures to iteratively test and improve your architecture. When testing your architecture, consider the following questions:
- What assumptions have I made in this architecture?
- What explicit or implied requirements is this architecture meeting?
- What are the key risks with this architectural approach?
- What countermeasures are in place to mitigate key risks?
- In what ways is this architecture an improvement over the baseline or the last candidate architecture?
Baseline and Candidate Architectures
A baseline architecture
describes the existing system—it is how your system looks today. If this is a new architecture, your initial baseline is the first high-level architectural design from which candidate architectures will be built. A candidate architecture includes the application type, the deployment architecture, the architectural style, technology choices, quality attributes, and cross-cutting concerns.
An architectural spike
is an end-to-end test of a small segment of the application. The purpose of an architectural spike is to reduce risk and to test potential paths. As you evolve your architecture, you may use spikes to explore different scenarios without impacting the existing design. An architectural spike will result in a candidate architecture that can be tested against a baseline. If the candidate architecture is an improvement, it can become the new baseline from which new candidate architectures can be created and tested. This iterative and incremental approach allows you to get the big risks out of the way first, iteratively render your architecture, and use architectural tests to prove that each new baseline is an improvement over the last.
Consider the following questions to help you test a new candidate architecture that results from an architectural spike:
- Does this architecture introduce new risks?
- Does this architecture mitigate additional known risks?
- Does this architecture meet additional requirements?
- Does this architecture enable architecturally significant use cases?
- Does this architecture address quality attribute concerns?
- Does this architecture address additional cross-cutting concerns?
Architecturally Significant Use Cases
Architecturally significant use cases are those that meet the following criteria:
- They are important for the success and acceptance of the deployed application.
- They exercise enough of the design to be useful in evaluating the architecture.
After you have determined architecturally significant use cases for your application, you can use them as a way to evaluate the success or failure of candidate architectures. If the candidate architecture addresses more use cases, or addresses existing use cases more effectively, it will help you to determine that this candidate architecture is an improvement over the baseline architecture.
Analyzing and Evaluating Architecture
Use architecture evaluation to determine the feasibility of your baseline and candidate architectures. Architecture evaluation is a key component of successful architecture iterations. Consider the following techniques for architecture evaluation:
- Architecturally significant use cases.** Test your design against use cases that are important to the success of your application, and which exercise a significant portion of the design.
- Scenario-based evaluations.** Use scenarios to analyze your design with a focus on quality attributes. Examples of scenario-based evaluations are: Architecture Trade-off Analysis Method (ATAM), Software Architecture Analysis Method (SAAM), and Active Reviews for Intermediate Designs (ARID).
Representing and Communicating the Architecture
Communicating your design is critical for architecture reviews, as well as for the use of your architecture during implementation. In the end, your architecture is only as good as the quality of communication of your ideas. You must communicate your architectural design to a variety of roles, including system designers, developers, system administrators, and management.
One way to think of an architectural view is as a map of the important decisions. The map is not the terrain; instead, it is an abstraction that helps you to share and communicate the architecture.
The Architectural Landscape
Understand the key forces that are shaping architectural decisions today, and which will change how architectural decisions are made in the future. These key forces are driven by user demand, as well as by business demand for faster results, better support for varying work styles and workflows, and improved adaptability of software design.
Consider the following key trends:
- User empowerment. A design that supports user empowerment is flexible, configurable, and focused on the user experience. Design your application with user personalization and options in mind. Allow the user to define how they interact with your application instead of dictating to them. Understand the key scenarios and make them as simple as possible; make it easy to find information and use the application.
- Market maturity. Take advantage of market maturity by leveraging existing platform and technology options. Build on higher-level application frameworks where it makes sense to, so that you can focus on what is uniquely valuable in your application, rather than building what already exists and can be reused. Leverage patterns that provide rich sources of proven solutions for common problems.
- Agility and adaptability. An agile, adaptable design takes advantage of loose coupling to allow reuse. Take advantage of pluggable designs to provide extensibility. Take advantage of service-orientation techniques such as SOA to provide interoperability.
- Future trends. When building your architecture, understand the future trends that might impact your design after deployment. For example, consider trends in rich UI and media, composition models such as mashups, increasing network bandwidth and availability, increasing use of mobile devices, continued improvement of hardware performance, interest in community and personal publishing models, the rise of cloud-based computing, and remote operation.