Real-world inspirations for architectural patterns

Real-world inspirations for architectural patterns #

As architectural patterns are usually technology-independent, they must mostly be shaped by the foundational principles of software engineering. And because the same principles are likely at work at every level of a software system, we may expect similar structures to appear on many levels of software, given similar circumstances – which is not always attainable, for the system-wide scope (which means that there are multiple clients and libraries) and distributed nature (which deals with faults of individual components) of many patterns of system architecture don’t have direct counterparts in smaller single-process software. Thus we expect to observe a fractal nature for the more generic patterns while narrowly specialized ones are present at only one or two scopes of software design.

Another thought to consider is that it’s not in human nature to invent something new – we are much more adept in imitating and combining whatever we see around us. That is why it’s so hard to find a genuine xenopsychology in literature or movies – to the extent that the eponymous Alien is just an overgrown parasitoid wasp. Hence there is another pathway to pursue – identifying the patterns which we know from software engineering in the world around us, as the authors of [POSA2] did decades ago.

Let’s go!

Basic metapatterns #

The basic patterns lay the foundation for any system by paving ways to divide it into components to conquer its complexity. We are going to observe them all around:

Monolith #

Monolith

Monolith means encapsulation – we use the thing without looking inside:

  • You interact with your dog (or your smartphone) through their interface without thinking of their internals.
  • A function exposes its name, arguments and, probably, some comments. The implementation is hidden from its users.
  • An object has a list of public methods.
  • A module or a library exports several functions for use by its clients.
  • A program is configured through its command line parameters and managed through its CLI. We don’t care how the Linux utilities (e.g. top or cat) work – we just run them.
  • A whole distributed system may be hidden behind a web page in your browser – and you never imagine its complexity unless you have worked on something of a kind.

Shards #

Shards

Shards is about having multiple instances of something, which often differ in their data:

  • A company employs many programmers to accelerate development of its projects.
  • Carrying two mobile phones from different operators fits this pattern as well.
  • This is how they make modern processors more powerful: by adding more cores, not by running them faster.
  • Objects in OOP are the perfect example of having multiple instances that vary in their data.
  • Running several shells in Linux is a kind of sharding.
  • A client application of a multi-user online game is a shard.

Layers #

Layers

Layers is the separation of responsibilities between external and internal components:

  • In winter we wear soft clothes on our body, a warm sweater over them, and a wind-proof jacket as the external layer.
  • An object comprises high-level public methods, low-level privates, and data.
  • An OS has a UI which runs over user-space software over an OS kernel over device drivers over the hardware.
  • Your web browser executes a frontend which communicates to a backend which uses a database.

Services #

Services

Services boil down to composition and separation of concerns:

  • We have legs, arms, and other specialized members.
  • A gadget contains specialized chips for activities it supports.
  • [GoF] advocates for an object to incorporate smaller objects (composition over inheritance).
  • Applications often delegate parts of their logic to specialized modules or libraries.
  • An OS dedicates a driver for each piece of hardware installed. Moreover, it provides many tools to its users – instead of tackling all the user needs within the kernel.
  • [DDD] describes the way to subdivide a large system into loosely coupled components.

Pipeline #

Pipeline

Pipeline is about the stepwise transformation of data:

  • The pattern got its name from real-world plumbing.
  • You’ll see similar arrangements in cellular metabolism.
  • It is the basis for functional programming.
  • Linux command line tools are often skillfully composed into pipelines.
  • Hardware is full of pipelines: from CPU and GPU to audio and video processing.
  • Finally, a UI wizard passes its users through a series of screens.

Extension metapatterns #

An extension pattern encapsulates one or two aspects of the system’s implementation. It may appear only on design levels which have those particular aspects:

Middleware #

Middleware

A Middleware abstracts scaling and/or intercommunication:

  • The network of post offices is a middleware – you push the letter into a mailbox and it automagically appears at its destination’s door.
  • A bus depot may mean a bus garage which deploys as many buses as needed to service the traffic or a bus station where people come to have a ride, regardless of the exact vehicle model they’ll take.
  • Hardware is full of another kind of buses that unify means of communication.
  • TCP and UDP sockets hide the details of the underlying network.
  • A distributed actor framework allows an actor to address another actor without knowing where it is deployed.

Shared Repository #

Shared Repository

A Shared Repository provides data storage and/or data change notifications:

  • Everybody in the room may use a blackwhiteboard to express and exchange their ideas.
  • An Internet forum works in a similar way – people post their arguments there for others to see them and get notified on answers.
  • RAM and CPU caches are kinds of shared repositories. CPU caches are kept synchronized through notifications.
  • Observer [GoF] is about getting notified when a shared object changes.
  • Services or service instances may share a database.

Proxy #

Proxy

A Proxy isolates a system from its environment by translating between internal and external protocols and/or implementing generic aspects of communication:

  • You may need a translator to understand foreign people or have a secretary to deal with routine tasks. A local guide combines both roles.
  • An adapter makes several hardware plugs (or software frameworks) compatible.
  • Your Wi-Fi router is a proxy between your laptop and the Internet.
  • A compiler is a kind of proxy between source code and bytecode.

Orchestrator #

Orchestrator

An Orchestrator integrates several components by implementing high-level use cases and/or keeping them in sync:

  • A taxi driver orchestrates his car’s internals.
  • A Facade [GoF] provides a high-level interface for a system while a Mediator [GoF] integrates a system by spreading changes initiated by the system’s components.
  • A linker composes a working program out of disjunct modules.

Fragmented metapatterns #

A fragmented pattern uses small specialized components to approach a case which is hard to resolve with more generic means. The high degree of specialization leads to even fewer examples:

Polyglot Persistence #

Polyglot Persistence

Polyglot Persistence is about having multiple containers for data:

  • A warehouse or a cargo ship has dedicated storage areas with extra facilities for combustible, toxic, and frozen goods.
  • A computer has CPU caches, RAM, flash, and hard drives for temporary or permanent data storage.
  • There are map, list, and array – each with its pros and cons. A large class would often use two or three kinds of containers and not without reason.

Backends for Frontends #

Backends for Frontends

Backends for Frontends is about treating different kinds of clients individually:

  • A bank is likely to reserve a couple of employees to serve rich clients.
  • A Wi-Fi router has many management interfaces: web, mobile application, CLI, and probably TR-069.
  • A multiplayer game may provide desktop and mobile client applications.

Service-Oriented Architecture #

Service-Oriented Architecture

SOA applies OOP techniques, including component reuse, to deal with complex systems:

  • That’s what you have inside your car. Many of its internals rely on the car’s battery for power supply instead of having a small battery installed inside every component.
  • Cities are built in the same way – schools, markets, and railways serve multiple houses.
  • It’s the same with user space of operating systems: there is a shared UI framework which interfaces with as-many-as-needed applications, each of which calls shared libraries (DLLs).

Hierarchy #

Hierarchy

Hierarchy distributes system’s complexity over multiple levels:

  • This is how large companies and armies are managed.
  • Large projects are made of services which contain modules which contain classes which contain methods.

Implementation metapatterns #

An implementation pattern highlights the peculiar internal arrangements of a component. Such patterns are deeply specialized:

Plugins #

Plugins

Plugins make a component’s behavior flexible through delegating its parts to small external additions:

  • This is how we use tools for our work – a man becomes a digger when given a shovel.
  • Strategy [GoF] is the thing.

Hexagonal Architecture #

Hexagonal Architecture

Hexagonal Architecture protects the internals of a system from its environment:

  • A drill or a screwdriver has replaceable bits.
  • OS Abstraction Layer and Hardware Abstraction Layer in embedded systems or Anti-Corruption Layer in [DDD] are all about that.

Microkernel #

Microkernel

Microkernel shares the goods of resource providers among resource users:

  • It’s like a bank that takes money from the rich to distribute them among the poor.
  • This is what an OS is for. Its scheduler shares the CPU, the memory subsystem shares RAM, while the device drivers provide access to the peripherals.
  • Cloud services are based on sharing computation resources among clients.

Mesh #

Mesh

Mesh is like grassroots movements – self-organizing and survival through redundancy:

  • Ants and bees are small, autonomous, and efficient. Their strength comes from their numbers.
  • Road networks and power grids don’t collapse if some of their components are damaged as they are highly redundant.
  • Torrents, mobile communications, and the Internet infrastructure are known for their robustness.

Summary #

Architectural patterns have parallels in the natural world, our society and/or different levels of computer hardware and software. Learning about them helps us feel the driving forces behind patterns and be more flexible and creative in using the patterns we know and devising new ones.

CC BY Denys Poltorak. Editor: Lars Noodén. Download from Leanpub or GitHub. Powered by odt2wiki and Hugo Book.