(This page has no text content)
Additional Resources 4 Easy Ways to Learn More and Stay Current Programming Newsletter Get programming related news and content delivered weekly to your inbox. oreilly.com/programming/newsletter Free Webcast Series Learn about popular programming topics from experts live, online. webcasts.oreilly.com O’Reilly Radar Read more insight and analysis about emerging technologies. radar.oreilly.com Conferences Immerse yourself in learning at an upcoming O’Reilly conference. conferences.oreilly.com ©2015 O’Reilly Media, Inc. The O’Reilly logo is a registered trademark of O’Reilly Media, Inc. #15305
Mark Richards Software Architecture Patterns Understanding Common Architecture Patterns and When to Use Them
978-1-491-92424-2 [LSI] Software Architecture Patterns by Mark Richards Copyright © 2015 O’Reilly Media, Inc. All rights reserved. Printed in the United States of America. Published by O’Reilly Media, Inc., 1005 Gravenstein Highway North, Sebastopol, CA 95472. O’Reilly books may be purchased for educational, business, or sales promotional use. Online editions are also available for most titles (http://safaribooksonline.com). For more information, contact our corporate/institutional sales department: 800-998-9938 or corporate@oreilly.com. Editor: Heather Scherer Production Editor: Colleen Lobner Copyeditor: Amanda Kersey Interior Designer: David Futato Cover Designer: Ellie Volckhausen Illustrator: Rebecca Demarest February 2015: First Edition Revision History for the First Edition 2015-02-24: First Release 2015-03-30: Second Release The O’Reilly logo is a registered trademark of O’Reilly Media, Inc. Software Architec‐ ture Patterns, the cover image, and related trade dress are trademarks of O’Reilly Media, Inc. While the publisher and the author have used good faith efforts to ensure that the information and instructions contained in this work are accurate, the publisher and the author disclaim all responsibility for errors or omissions, including without limi‐ tation responsibility for damages resulting from the use of or reliance on this work. Use of the information and instructions contained in this work is at your own risk. If any code samples or other technology this work contains or describes is subject to open source licenses or the intellectual property rights of others, it is your responsi‐ bility to ensure that your use thereof complies with such licenses and/or rights.
Table of Contents Introduction. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . v 1. Layered Architecture. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 Pattern Description 1 Key Concepts 3 Pattern Example 5 Considerations 7 Pattern Analysis 8 2. Event-Driven Architecture. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 Mediator Topology 11 Broker Topology 14 Considerations 17 Pattern Analysis 18 3. Microkernel Architecture. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 Pattern Description 21 Pattern Examples 23 Considerations 24 Pattern Analysis 25 4. Microservices Architecture Pattern. . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 Pattern Description 27 Pattern Topologies 29 Avoid Dependencies and Orchestration 32 Considerations 33 Pattern Analysis 34 iii
5. Space-Based Architecture. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 Pattern Description 38 Pattern Dynamics 39 Considerations 42 Pattern Analysis 43 A. Pattern Analysis Summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 iv | Table of Contents
Introduction It’s all too common for developers to start coding an application without a formal architecture in place. Without a clear and well- defined architecture, most developers and architects will resort to the de facto standard traditional layered architecture pattern (also called the n-tier architecture), creating implicit layers by separating source-code modules into packages. Unfortunately, what often results from this practice is a collection of unorganized source-code modules that lack clear roles, responsibilities, and relationships to one another. This is commonly referred to as the big ball of mud architecture anti-pattern. Applications lacking a formal architecture are generally tightly cou‐ pled, brittle, difficult to change, and without a clear vision or direc‐ tion. As a result, it is very difficult to determine the architectural characteristics of the application without fully understanding the inner-workings of every component and module in the system. Basic questions about deployment and maintenance are hard to answer: Does the architecture scale? What are the performance characteristics of the application? How easily does the application respond to change? What are the deployment characteristics of the application? How responsive is the architecture? Architecture patterns help define the basic characteristics and behavior of an application. For example, some architecture patterns naturally lend themselves toward highly scalable applications, whereas other architecture patterns naturally lend themselves toward applications that are highly agile. Knowing the characteris‐ tics, strengths, and weaknesses of each architecture pattern is neces‐ v
sary in order to choose the one that meets your specific business needs and goals. As an architect, you must always justify your architecture decisions, particularly when it comes to choosing a particular architecture pat‐ tern or approach. The goal of this report is to give you enough infor‐ mation to make and justify that decision. vi | Introduction
CHAPTER 1 Layered Architecture The most common architecture pattern is the layered architecture pattern, otherwise known as the n-tier architecture pattern. This pattern is the de facto standard for most Java EE applications and therefore is widely known by most architects, designers, and devel‐ opers. The layered architecture pattern closely matches the tradi‐ tional IT communication and organizational structures found in most companies, making it a natural choice for most business appli‐ cation development efforts. Pattern Description Components within the layered architecture pattern are organized into horizontal layers, each layer performing a specific role within the application (e.g., presentation logic or business logic). Although the layered architecture pattern does not specify the number and types of layers that must exist in the pattern, most layered architec‐ tures consist of four standard layers: presentation, business, persis‐ tence, and database (Figure 1-1). In some cases, the business layer and persistence layer are combined into a single business layer, par‐ ticularly when the persistence logic (e.g., SQL or HSQL) is embed‐ ded within the business layer components. Thus, smaller applications may have only three layers, whereas larger and more complex business applications may contain five or more layers. Each layer of the layered architecture pattern has a specific role and responsibility within the application. For example, a presentation layer would be responsible for handling all user interface and 1
browser communication logic, whereas a business layer would be responsible for executing specific business rules associated with the request. Each layer in the architecture forms an abstraction around the work that needs to be done to satisfy a particular business request. For example, the presentation layer doesn’t need to know or worry about how to get customer data; it only needs to display that information on a screen in particular format. Similarly, the business layer doesn’t need to be concerned about how to format customer data for display on a screen or even where the customer data is coming from; it only needs to get the data from the persis‐ tence layer, perform business logic against the data (e.g., calculate values or aggregate data), and pass that information up to the pre‐ sentation layer. Figure 1-1. Layered architecture pattern One of the powerful features of the layered architecture pattern is the separation of concerns among components. Components within a specific layer deal only with logic that pertains to that layer. For example, components in the presentation layer deal only with pre‐ sentation logic, whereas components residing in the business layer deal only with business logic. This type of component classification makes it easy to build effective roles and responsibility models into your architecture, and also makes it easy to develop, test, govern, and maintain applications using this architecture pattern due to well-defined component interfaces and limited component scope. 2 | Chapter 1: Layered Architecture
Key Concepts Notice in Figure 1-2 that each of the layers in the architecture is marked as being closed. This is a very important concept in the lay‐ ered architecture pattern. A closed layer means that as a request moves from layer to layer, it must go through the layer right below it to get to the next layer below that one. For example, a request origi‐ nating from the presentation layer must first go through the busi‐ ness layer and then to the persistence layer before finally hitting the database layer. Figure 1-2. Closed layers and request access So why not allow the presentation layer direct access to either the persistence layer or database layer? After all, direct database access from the presentation layer is much faster than going through a bunch of unnecessary layers just to retrieve or save database infor‐ mation. The answer to this question lies in a key concept known as layers of isolation. The layers of isolation concept means that changes made in one layer of the architecture generally don’t impact or affect components in other layers: the change is isolated to the components within that layer, and possibly another associated layer (such as a persistence layer containing SQL). If you allow the presentation layer direct access to the persistence layer, then changes made to SQL within the Key Concepts | 3
persistence layer would impact both the business layer and the pre‐ sentation layer, thereby producing a very tightly coupled application with lots of interdependencies between components. This type of architecture then becomes very hard and expensive to change. The layers of isolation concept also means that each layer is inde‐ pendent of the other layers, thereby having little or no knowledge of the inner workings of other layers in the architecture. To understand the power and importance of this concept, consider a large refactor‐ ing effort to convert the presentation framework from JSP (Java Server Pages) to JSF (Java Server Faces). Assuming that the contracts (e.g., model) used between the presentation layer and the business layer remain the same, the business layer is not affected by the refac‐ toring and remains completely independent of the type of user- interface framework used by the presentation layer. While closed layers facilitate layers of isolation and therefore help isolate change within the architecture, there are times when it makes sense for certain layers to be open. For example, suppose you want to add a shared-services layer to an architecture containing com‐ mon service components accessed by components within the busi‐ ness layer (e.g., data and string utility classes or auditing and logging classes). Creating a services layer is usually a good idea in this case because architecturally it restricts access to the shared services to the business layer (and not the presentation layer). Without a separate layer, there is nothing architecturally that restricts the presentation layer from accessing these common services, making it difficult to govern this access restriction. In this example, the new services layer would likely reside below the business layer to indicate that components in this services layer are not accessible from the presentation layer. However, this presents a problem in that the business layer is now required to go through the services layer to get to the persistence layer, which makes no sense at all. This is an age-old problem with the layered architecture, and is solved by creating open layers within the architecture. As illustrated in Figure 1-3, the services layer in this case is marked as open, meaning requests are allowed to bypass this open layer and go directly to the layer below it. In the following example, since the services layer is open, the business layer is now allowed to bypass it and go directly to the persistence layer, which makes perfect sense. 4 | Chapter 1: Layered Architecture
Figure 1-3. Open layers and request flow Leveraging the concept of open and closed layers helps define the relationship between architecture layers and request flows and also provides designers and developers with the necessary information to understand the various layer access restrictions within the architec‐ ture. Failure to document or properly communicate which layers in the architecture are open and closed (and why) usually results in tightly coupled and brittle architectures that are very difficult to test, maintain, and deploy. Pattern Example To illustrate how the layered architecture works, consider a request from a business user to retrieve customer information for a particu‐ lar individual as illustrated in Figure 1-4. The black arrows show the request flowing down to the database to retrieve the customer data, and the red arrows show the response flowing back up to the screen to display the data. In this example, the customer informa‐ tion consists of both customer data and order data (orders placed by the customer). Pattern Example | 5
The customer screen is responsible for accepting the request and dis‐ playing the customer information. It does not know where the data is, how it is retrieved, or how many database tables must be queries to get the data. Once the customer screen receives a request to get customer information for a particular individual, it then forwards that request onto the customer delegate module. This module is responsible for knowing which modules in the business layer can process that request and also how to get to that module and what data it needs (the contract). The customer object in the business layer is responsible for aggregating all of the information needed by the business request (in this case to get customer information). This module calls out to the customer dao (data access object) module in the persistence layer to get customer data, and also the order dao module to get order information. These modules in turn execute SQL statements to retrieve the corresponding data and pass it back up to the customer object in the business layer. Once the customer object receives the data, it aggregates the data and passes that infor‐ mation back up to the customer delegate, which then passes that data to the customer screen to be presented to the user. Figure 1-4. Layered architecture example From a technology perspective, there are literally dozens of ways these modules can be implemented. For example, in the Java plat‐ form, the customer screen can be a (JSF) Java Server Faces screen 6 | Chapter 1: Layered Architecture
coupled with the customer delegate as the managed bean compo‐ nent. The customer object in the business layer can be a local Spring bean or a remote EJB3 bean. The data access objects illustrated in the previous example can be implemented as simple POJO’s (Plain Old Java Objects), MyBatis XML Mapper files, or even objects encapsulating raw JDBC calls or Hibernate queries. From a Micro‐ soft platform perspective, the customer screen can be an ASP (active server pages) module using the .NET framework to access C# mod‐ ules in the business layer, with the customer and order data access modules implemented as ADO (ActiveX Data Objects). Considerations The layered architecture pattern is a solid general-purpose pattern, making it a good starting point for most applications, particularly when you are not sure what architecture pattern is best suited for your application. However, there are a couple of things to consider from an architecture standpoint when choosing this pattern. The first thing to watch out for is what is known as the architecture sinkhole anti-pattern. This anti-pattern describes the situation where requests flow through multiple layers of the architecture as simple pass-through processing with little or no logic performed within each layer. For example, assume the presentation layer responds to a request from the user to retrieve customer data. The presentation layer passes the request to the business layer, which simply passes the request to the persistence layer, which then makes a simple SQL call to the database layer to retrieve the customer data. The data is then passed all the way back up the stack with no additional pro‐ cessing or logic to aggregate, calculate, or transform the data. Every layered architecture will have at least some scenarios that fall into the architecture sinkhole anti-pattern. The key, however, is to analyze the percentage of requests that fall into this category. The 80-20 rule is usually a good practice to follow to determine whether or not you are experiencing the architecture sinkhole anti-pattern. It is typical to have around 20 percent of the requests as simple pass- through processing and 80 percent of the requests having some business logic associated with the request. However, if you find that this ratio is reversed and a majority of your requests are simple pass- through processing, you might want to consider making some of the Considerations | 7
architecture layers open, keeping in mind that it will be more diffi‐ cult to control change due to the lack of layer isolation. Another consideration with the layered architecture pattern is that it tends to lend itself toward monolithic applications, even if you split the presentation layer and business layers into separate deployable units. While this may not be a concern for some applications, it does pose some potential issues in terms of deployment, general robust‐ ness and reliability, performance, and scalability. Pattern Analysis The following table contains a rating and analysis of the common architecture characteristics for the layered architecture pattern. The rating for each characteristic is based on the natural tendency for that characteristic as a capability based on a typical implementa‐ tion of the pattern, as well as what the pattern is generally known for. For a side-by-side comparison of how this pattern relates to other patterns in this report, please refer to Appendix A at the end of this report. Overall agility Rating: Low Analysis: Overall agility is the ability to respond quickly to a constantly changing environment. While change can be isolated through the layers of isolation feature of this pattern, it is still cumbersome and time-consuming to make changes in this architecture pattern because of the monolithic nature of most implementations as well as the tight coupling of components usually found with this pattern. Ease of deployment Rating: Low Analysis: Depending on how you implement this pattern, deployment can become an issue, particularly for larger applica‐ tions. One small change to a component can require a redeployment of the entire application (or a large portion of the application), resulting in deployments that need to be planned, scheduled, and executed during off-hours or on weekends. As such, this pattern does not easily lend itself toward a contin‐ uous delivery pipeline, further reducing the overall rating for deployment. 8 | Chapter 1: Layered Architecture
Testability Rating: High Analysis: Because components belong to specific layers in the architecture, other layers can be mocked or stubbed, making this pattern is relatively easy to test. A developer can mock a presentation component or screen to isolate testing within a business component, as well as mock the business layer to test certain screen functionality. Performance Rating: Low Analysis: While it is true some layered architectures can per‐ form well, the pattern does not lend itself to high-performance applications due to the inefficiencies of having to go through multiple layers of the architecture to fulfill a business request. Scalability Rating: Low Analysis: Because of the trend toward tightly coupled and mon‐ olithic implementations of this pattern, applications build using this architecture pattern are generally difficult to scale. You can scale a layered architecture by splitting the layers into separate physical deployments or replicating the entire application into multiple nodes, but overall the granularity is too broad, making it expensive to scale. Ease of development Rating: High Analysis: Ease of development gets a relatively high score, mostly because this pattern is so well known and is not overly complex to implement. Because most companies develop appli‐ cations by separating skill sets by layers (presentation, business, database), this pattern becomes a natural choice for most business-application development. The connection between a company’s communication and organization structure and the way it develops software is outlined is what is called Conway’s law. You can Google “Conway’s law" to get more information about this fascinating correlation. Pattern Analysis | 9
(This page has no text content)
CHAPTER 2 Event-Driven Architecture The event-driven architecture pattern is a popular distributed asynchronous architecture pattern used to produce highly scalable applications. It is also highly adaptable and can be used for small applications and as well as large, complex ones. The event-driven architecture is made up of highly decoupled, single-purpose event processing components that asynchronously receive and process events. The event-driven architecture pattern consists of two main topolo‐ gies, the mediator and the broker. The mediator topology is com‐ monly used when you need to orchestrate multiple steps within an event through a central mediator, whereas the broker topology is used when you want to chain events together without the use of a central mediator. Because the architecture characteristics and imple‐ mentation strategies differ between these two topologies, it is impor‐ tant to understand each one to know which is best suited for your particular situation. Mediator Topology The mediator topology is useful for events that have multiple steps and require some level of orchestration to process the event. For example, a single event to place a stock trade might require you to first validate the trade, then check the compliance of that stock trade against various compliance rules, assign the trade to a broker, calcu‐ late the commission, and finally place the trade with that broker. All of these steps would require some level of orchestration to deter‐ 11
mine the order of the steps and which ones can be done serially and in parallel. There are four main types of architecture components within the mediator topology: event queues, an event mediator, event channels, and event processors. The event flow starts with a client sending an event to an event queue, which is used to transport the event to the event mediator. The event mediator receives the initial event and orchestrates that event by sending additional asynchronous events to event channels to execute each step of the process. Event process‐ ors, which listen on the event channels, receive the event from the event mediator and execute specific business logic to process the event. Figure 2-1 illustrates the general mediator topology of the event-driven architecture pattern. Figure 2-1. Event-driven architecture mediator topology It is common to have anywhere from a dozen to several hundred event queues in an event-driven architecture. The pattern does not specify the implementation of the event queue component; it can be a message queue, a web service endpoint, or any combination thereof. There are two types of events within this pattern: an initial event and a processing event. The initial event is the original event received by 12 | Chapter 2: Event-Driven Architecture
Comments 0
Loading comments...
Reply to Comment
Edit Comment