Common Software Architectural Patterns you need to know
Architectural patterns are ways of capturing proven good design structures, so that they can be reused. Software architects have been looking for ways to capture and reuse the architectural knowledge that have proven successful in the past. This article is inspired by the book “ Software Architecture in Practice” by Len Bass, Paul Clements and Rick Kazman.
An architectural pattern
· is a package of design decisions that is found repeatedly in practice
· has well defined properties that can be reused
· describes a class of architectures
Developing an architecture can be seen as a process of selecting, tailoring, and combining patterns. The software architect must decide how to instantiate a pattern, how to make it fit with the specific context and the constraints of the problem.
In this article I will be talking about the most widely spread architectural patterns in the software project world.
1. Module patterns
1.1. Layered pattern
The layered pattern defines layers (groupings of modules that offer a cohesive set of services) and a unidirectional allowed-to-use relation among the layers. The pattern is usually shown graphically by stacking boxes representing layers on top of each other. Layered pattern can be found in general desktop applications and e-commerce web applications.
A layer is a module which is responsible for a cohesive set of services. The design should define what the layer usage rules are (e.g., “a layer is allowed to use any lower layer” or “a layer is allowed to use only the layer Immediately below it”) and any allowable exceptions. A system should consist of at least two layers and the allowed-to-use relation should not be circular. i.e. lower layers cannot use the layers above.
· The addition of layers adds up-front cost and complexity to a system.
· Layers contribute a performance penalty.
2. Component and connector pattern
2.1. Broker pattern
A broker is an intermediary that locates an appropriate server to fulfill a client’s request, forwards the request to the server and returns the results to the client. This pattern defines a run-time component, which is a broker, that mediates the communication between a number of clients and servers.
Client-side proxy is the intermediary that will manage the actual communication with the broker, including marshaling, sending, and un-marshaling of messages. While the server-side proxy would be the intermediary that manages the actual communication with the broker, including marshaling, sending, and un-marshaling of messages
· Brokers add a layer of indirection and hence latency, between clients and servers, and that layer may be a communication bottleneck.
· The broker can be a single point of failure.
· A broker adds up-front complexity.
· A broker may be a target for security attacks.
· A broker may be difficult to test.
2.2. Model view controller pattern
The model-view-controller (MVC) pattern separates application functionality into three kinds of components:
· A model — contains the application’s data
· A view — displays some portion of the underlying data and interacts with the user
· A controller — mediates between the model and the view and manages the notifications of state changes
The MVC components are connected to each other via some form of notification, such as events or callbacks. These notifications contain state updates. A change in the model needs to be communicated to the views so that they may be updated. An external event, such as a user input, needs to be communicated to the controller, which may in turn update the view and/or the model. Notifications can be either push or pull.
· The complexity may not be worth it for simple user interfaces.
· The model, view, and controller abstractions may not be good fits for some user interface toolkits.
2.3. Pipe and filter pattern
In this pattern data is transformed from a system’s external inputs to its external outputs through a series of transformations performed by its filters connected by pipes.
Filter is a component that transforms data read on its input ports to data written on its output ports. Filters can execute concurrently with each other. Fitters can Incrementally transform data in such a way that, they can start producing output as soon as they start processing Input. On the other hand, pipe is a connector that conveys data from a filter’s output ports to another filter’s input ports. A pipe has a single source for its input and a single target for its output. A pipe preserves the sequence of data items, and it does not alter the data passing through.
· The pipe-and-filter pattern is typically not a good choice for an interactive system. Having large numbers of independent filters can add substantial amounts of computational overhead.
· Pipe-and-fitter systems may not be appropriate for long-running computations.
2.4. Client server pattern
In this pattern, clients will initiate the interactions with the servers, invoking services as needed from those servers and waiting for the results of those requests. The World Wide Web is the best-known example of a system that is based on the client-server pattern.
Client is a component that invokes services of a server component. Clients have ports that describe the services they require. Whereas, a server is a component that provides services to clients. Servers have ports that describe the services they provide. Clients are connected to servers through request/reply connectors.
· Server can be a performance bottleneck.
· Server can be a single point of failure.
· Decisions about where to locate functionality (in the client or in the server) are often complex and costly to change after a system has been built.
2.5. Peer to peer pattern
In this pattern, computation is achieved by cooperating peers that request services from, and provide services to one another across a network. Peer-to-peer computing is often used in distributed computing applications such as file sharing (BitTorrent and eDonkey), instant messaging (VoIP applications like Skype), desktop grid computing, routing, and wireless ad hoc networking.
A peer is an independent component running on a network node. Special peer components can provide routing, indexing, and peer search capability. Request/reply connectors are used to connect to the peer network, search for other peers and invoke services from other peers.
· Managing security, data consistency, data/service availability, backup, and recovery are all more complex.
· Small peer-to-peer systems may not be able to consistently achieve quality goals such as performance and high availability.
2.6. Service Oriented Architecture pattern
In this pattern, computation is achieved through a set of cooperating components that provide and consume services over a network. The computation is often described using a workflow language.
The main benefit of SOA is interoperability. Because service providers and service consumers may run on different platforms, service-oriented architectures often integrate a variety of systems (including legacy systems). SOA also offers the necessary elements to interact with external services available over the Internet as well.
Service providers would provide one or more services through published interfaces. Whereas, the service consumers will invoke the services directly or through an intermediary.
· SOA-based systems are typically complex to build.
· You don’t control the evolution of independent services.
· There is a performance overhead associated- with the middleware, and services may be performance bottlenecks, and typically do not provide performance guarantees.
2.7. Publish subscribe pattern
In this pattern, Components publish and subscribe to events. When an event is announced by a component, the connector infrastructure dispatches the event to all registered subscribers. It is the job of the publish-subscribe run-time infrastructure to make sure that each published event is delivered to all the subscribers of that event. Thus, the main form of connector is an event bus. Any component may be a publisher or a subscriber.
Examples of system that use publish subscriber pattern;
· Graphical user interfaces, in which a user’s low-level input actions are treated as events that are routed to appropriate input handlers.
· MVC-based applications, in which view components are notified when the state of a model object changes
· Enterprise resource planning (ERP) systems, which integrate many components, each of which is only interested in a subset of system events
· Typically increases latency and has a negative effect on scalability and predictability of message delivery time.
· Less control over ordering of messages, and delivery of messages is not guaranteed.
3. Allocation pattern
3.1. Map reduce pattern
The map-reduce pattern provides a framework for analyzing a large distributed set of data that will execute in parallel, on a set of processors. This palatalization allows for low latency and high availability. The map performs the extract and transform portions of the analysis and the reduce performs the loading of the results. Map-reduce is the basis of the famous websites, including Google, Facebook, eBay, and Yahoo!
Map is a function with multiple instances deployed across multiple processors that performs the extract and transformation portions of the analysis. Reduce is a function that may be deployed as a single Instance or as multiple instances across processors to perform the load portion of extract-transform-load. The infrastructure is the framework responsible for deploying map and reduce instances, marshaling the data between them, and detecting and recovering from failure.
· If you do not have large data sets, the overhead of map-reduce is not justified.
· If you cannot divide your data set into similar sized subsets, the advantages of parallelism are lost.
· Operations that require multiple reduces are complex to orchestrate.
3.2. Multi-tier pattern
The execution structures of many systems are organized as a set of logical groupings of components. Each grouping is named as a tier. The grouping of components into tiers may be based on a variety of criteria, such as the type of component, sharing the same execution environment, or having the same run-time purpose.
Tier is a logical grouping of software components. Tiers may be formed on the basis of common computing platforms, in which case those platforms are also elements of the pattern. A software component may belong to exactly one tier. A major disadvantage of this pattern is considerable up-front cost and complexity.
Tiers make it easier to ensure security, and to optimize performance and availability in the systems. They also enhance the modifiability by reducing their coupling, as the computationally independent subgroups need to agree on protocols for interaction.
Hope you find this article useful and thank you for reading.