COMP433 · Ch. 5 · System design
COMP433 · Software Engineering · Chapter 5

System design: from the problem to a defensible solution.

Requirements engineering and analysis describe the problem; system design chooses a solution. This companion follows that move: setting design goals from the non-functional requirements, decomposing the system into cohesive, loosely coupled subsystems, and selecting an architectural style whose known shape and trade-offs match those goals. It develops in full the architectural styles and the 4+1 view model that the Chapter 4 companion only previews, and it builds one worked example from design goals through to a justified architecture.

courseCOMP433
chapter5 of the syllabus
instructorHisham Ihshaish
sourcesBruegge & Dutoit; Sommerville ch.6

Contents

1.From analysis to design

From analysis to design: choosing a solution.

Requirements engineering and analysis answer what the system must do; system design answers how it will be built. The two work on different domains: analysis models the problem, design models the solution.

Where it fits

Between analysis and implementation. Design takes the analysis model (use cases, domain classes, the requirements) as input and produces the subsystem decomposition and architecture that implementation then follows.

Problem domain versus solution domain

Analysis stays in the problem domain: it describes the world the system serves, in the vocabulary of the user. Design moves to the solution domain: it describes the software and hardware that will be built, in the vocabulary of the developer. The same noun can live in both, but it means different things; a Patient in analysis is a domain concept, while a Patient in design is a class with a chosen persistence strategy, an interface, and a home in some subsystem.

 AnalysisDesign
QuestionWhat must the system do?How will it be structured to do it?
DomainProblem domain: the world the system serves.Solution domain: the software and hardware to be built.
OutputRequirements, use cases, analysis (domain) classes.Design goals, subsystem decomposition, architecture, design classes.
VocabularyOf the user and the domain.Of the developer: components, layers, interfaces, nodes.

Design is multi-perspective

A design is never judged on functionality alone. The same set of functions can be realised by many structures, and the structures differ in qualities the user never sees directly but always feels: response time, security, the cost of the next change, the effort to test. Design is therefore a multi-perspective activity that weighs these qualities against one another. The non-functional requirements are where most of them originate, which is why design begins by turning those requirements into explicit, prioritised design goals.

The scope of system design

System design proceeds in a structured way rather than by jumping to code. The skeleton of the process is short:

  1. Identify the design goals from the non-functional requirements and from general engineering principles, and prioritise them, because they will conflict.
  2. Model the new system as a set of subsystems, choosing a decomposition and an architectural style whose shape serves those goals.
  3. Address each main design goal in turn: hardware/software mapping, data management, access control and security, the global flow of control, and the boundary (start-up, shutdown, failure) conditions.

The next sections take these in order: first the goals and the two principles that govern every decomposition (cohesion and coupling), then the decomposition itself, then the architectural styles that give a decomposition its recognised shape.

2.The issues of system design

The questions a design must answer.

System design is the set of decisions that turn an analysis model into an implementable structure. It is worth naming those decisions, because a design is incomplete until each has an answer.

The two that dominate, and that the rest of this companion develops, are the design goals and the subsystem decomposition (which carries the choice of architectural style and the cohesion and coupling of the parts). The full set of issues a complete system design resolves is:

IssueThe question it answers
Design goalsWhich qualities matter most for this system, and in what priority when they conflict?
Subsystem decompositionInto what cohesive, loosely coupled subsystems is the system divided, and in what architectural style are they arranged?
Hardware / software mappingWhich subsystems run on which nodes, and how do the nodes communicate?
Data managementWhat data is persistent, and is it held in files, a relational database, or another store?
Access control and securityWho may access which data and operations, and how is that enforced?
Global control flowIs control procedure-driven, event-driven, or thread-based across the system?
Boundary conditionsHow does the system start up, shut down, and handle failure?

The hardware/software mapping is exactly what the deployment diagram records, and the subsystem structure is what the component diagram records: the two structural diagrams from Chapter 4 are the notation for two of these issues. This chapter concentrates on the first two, where the architectural choices are made.

3.Design goals and trade-offs

Design goals: naming what matters, before it conflicts.

A design goal is a quality the design must optimise, drawn from the non-functional requirements and from general engineering principles. Goals are made explicit precisely because they conflict, and a design is a defensible set of trade-offs between them.

Goal, requirement, design goal: the distinction

Three terms are easy to blur, and keeping them apart is what lets a design be checked. A goal is a general, often imprecise and non-verifiable statement of intent, usually about a quality: “the system should be secure”, “it should be fast”. A non-functional requirement sharpens that same quality into something precise and verifiable: “an unauthenticated request must never reach a patient record”, “95% of searches return in under 200 ms”. A design goal is that quality carried into design as a property the structure must optimise. So the chain runs goal (intent) → non-functional requirement (precise, verifiable) → design goal (what the architecture optimises). This is also why a bare goal is not yet checkable and a good design goal usually is.

Where design goals come from: two sources

Design goals arise from two places, and a complete design weighs both:

Cohesion and coupling are therefore not a separate topic from design goals: they are the general design goals, the ones you pursue on every project, while the system-specific goals come from the non-functional requirements of the system in front of you.

Stakeholders want different goals

The goals are not shared equally. Different stakeholders press for different, often opposing, qualities, and the designer's first job is to surface the conflict rather than pretend it away:

StakeholderThe design goals they tend to prioritise
End user (who operates)Functionality, usability, user-friendliness, ease of learning, ease of use, ease of remembering, runtime efficiency (performance), reliability, fault tolerance, robustness.
Customer / client (who pays)Low cost and cost-effectiveness, delivery on schedule and rapid development, increased productivity, functionality, flexibility, portability, backward compatibility, traceability of requirements, good documentation.
Developer / maintainer (who builds and maintains)Minimum number of errors, maintainability (modifiability), readability, understandability, reusability and reuse of components, adaptability, well-defined interfaces, reliability, portability, minimal complexity.

That is the full catalogue of design goals worth knowing, sorted by the stakeholder who cares most. Several goals (reliability, portability, functionality) matter to more than one stakeholder, which is exactly why they collide. A design lists the ones that matter for this system, attributes each to a stakeholder, and prioritises them; the next two tables show why prioritising is unavoidable.

Goals trade off against each other

Because resources are finite, raising one quality usually lowers another. Recognising these trade-offs, and deciding which way to resolve each one for this system, is the substance of design. The pairings below are indicative, not one-to-one: a quality is rarely bought at the cost of exactly one other. Robustness, for instance, is paid for in efficiency and in cost and in complexity at once.

Raising this……tends to cost thisWhy, with a concrete example
RobustnessEfficiency, cost, complexityThe redundancy, extra validation and fault-tolerance that make a system robust are paid for on three fronts at once: more work per request (efficiency), more hardware and licences to run the spares (cost), and more moving parts to get right (complexity). Example: a payment service that re-validates every request, retries failed calls and keeps a hot standby survives a crashed node, but each payment does more work, it needs roughly twice the hardware, and the failover logic is one more thing that can be wrong, against a single-instance, trust-the-input design that is faster and simpler but falls over on the first fault.
FunctionalityUsability and simplicityEvery feature adds a control, a mode, a path to test. Example: a camera app that also edits video, manages files and posts to social media buries the one-tap shutter under menus; the stripped-down camera is easier to use precisely because it does less.
Performance (efficiency)Portability and readabilitySpeed often means code tied to one machine and hard to follow. Example: rewriting an image filter in hand-tuned CPU-specific SIMD assembly can double throughput, but it no longer compiles elsewhere and few on the team can safely change it.
SecurityUsability and performanceEvery check is a step for the user and a cost per call. Example: two-factor login plus an authorisation check on every request keeps intruders out, but adds a login step for the user and a permission lookup on each call.
Low cost / fast deliveryRobustness and maintainabilityShortcuts ship sooner and cheaper, then charge interest. Example: dropping the test suite and staging server to hit a demo date works once, but the first production outage, and every feature slowed by the shortcut schema afterwards, costs more than they would have.

How each goal is achieved in the architecture

A goal is only worth stating if there is a structural move that serves it. The architecture is where most non-functional goals are won or lost, so each one points to a recognised technique:

Design goalHow to achieve it (architecturally)What that looks like in practice
PerformanceLocalise critical operations and minimise communication between components; use large rather than fine-grain components.Group the ten steps of checkout into one coarse CheckoutService so a purchase is a single in-process call, instead of ten chatty calls hopping across the network, each paying latency.
SecurityUse a layered architecture with the critical assets in the inner layers.Put patient records in the innermost layer, so every request has to pass through the authentication and authorisation layers above before it can reach them; there is no shortcut to the data.
SafetyLocalise the safety-critical features in a small number of subsystems.Confine an infusion pump's dosage-calculation logic to one small, heavily reviewed subsystem, rather than scattering it, so the safety case only has to certify that one part.
Availability (and robustness)Include redundant components and mechanisms for fault tolerance.Run two web servers behind a load balancer with a replicated database, so one node failing does not take the service down (this is the backup node in the deployment diagram).
MaintainabilityUse fine-grain, replaceable components.Keep each tax rule in its own small, replaceable component, so a rate change touches one component and its tests, not a tangled monolith.

Notice these techniques pull against each other, which is the whole point of prioritising. Performance wants large components and few calls; maintainability wants fine-grain replaceable ones. You cannot maximise both, so the design commits: the CheckoutService that makes a purchase fast is the very coarseness that makes it harder to change one step of it later. Naming which goal wins for this system is the decision the architecture records.

A design goal is only useful if it can be attributed to a stakeholder and, ideally, measured. "The system should be secure" is not yet a goal; "an unauthenticated request must never reach the patient record, enforced at a single gateway" is one a design can be checked against.

4.Cohesion and coupling

Cohesion and coupling: the two measures of a decomposition.

These two are the general design goals promised in the previous section, the ones pursued on every project regardless of its non-functional requirements. Every decomposition is judged by them: cohesion looks inside a subsystem, coupling looks between subsystems. A good design maximises the first and minimises the second, and doing so is what reduces overall complexity while keeping the system open to change.

Cohesion: relatedness within a subsystem

Cohesion measures the strength of functional relatedness among the classes inside one subsystem. High cohesion means the classes perform similar or related tasks and clearly belong together. Low cohesion means unrelated classes have been grouped with no clear theme, usually a sign that the subsystem is really several subsystems in disguise.

Coupling: interdependence between subsystems

Coupling measures the degree of interdependence between subsystems. High coupling means a change to one subsystem forces changes in others. Low coupling means a change in one has minimal or no effect on the rest. Low coupling is what lets a subsystem be understood, tested, replaced, or reused on its own.

Figure 1
The same five responsibilities, coupled two ways. Hover any box or link.
High coupling · low cohesion A B C D E Low coupling · high cohesion Presentation Business logic Data store
The left and right designs deliver the same behaviour. The left tangles five modules so each depends on most others (high coupling) and the middle module mixes unrelated work (low cohesion); a change anywhere propagates. The right groups related work into cohesive layers and lets each call only the one below, so a change stays contained. The shape on the right is what every architectural style in this chapter is reaching for.

Why aim for high cohesion?

How to achieve high cohesion and low coupling

High cohesion is achieved when most of the interaction is kept within a subsystem rather than across its boundary: gather the classes that talk to each other constantly into the same subsystem, and you raise cohesion and lower coupling at the same time.

Low coupling is achieved by making subsystems self-contained and having them depend on each other's interfaces, not their internals. A calling subsystem should know what another offers (its public operations) and nothing about how it works (its attributes and representation). This is the principle of information hiding.

Information hiding

Information hiding, the foundation of modular programming, says a subsystem should hide its internal data and representation behind a stable set of public operations. Callers depend only on those operations, defined as an interface. The benefit is direct: the internals can be rewritten, optimised, or replaced without touching any caller, because nothing outside ever depended on them. Coupling drops to the width of the interface, and the interface is the one thing the design keeps stable.

5.Subsystem decomposition

Decomposition: dividing the system into parts.

A subsystem is a replaceable part of the system that provides a coherent service through a well-defined interface. Decomposition is the act of dividing the system into such parts, guided by the two measures of the previous section.

Subsystems, services, and interfaces

A subsystem is a group of cohesive classes (or components) that together provide a service: a related set of operations offered to other subsystems. The service is exposed as the subsystem's interface: the set of public operations other subsystems may call. Other subsystems depend on the interface, never on the classes behind it; that is information hiding applied at the architectural scale.

Layers and partitions

There are two ways to relate subsystems, and most architectures use both:

Build dependencies

Decomposition has a concrete consequence at build time. If subsystem A uses subsystem B, then B must be compiled and available before A can be built. The "uses" relationships therefore form a build-dependency graph, and building the system means processing that graph in dependency order. This is exactly what build tools (make, ant, maven, gradle) compute: a topological sort of the dependency graph.

Figure 2
Build dependencies between seven subsystems. Hover a subsystem.
A B C D E F G
An arrow from A to B reads "A depends on B": B must be built first. The graph is acyclic, so it has a valid build order (here D and E, then F, then G; B and C, then A). A cycle in this graph would mean two subsystems each need the other built first, which no build tool can satisfy, and is the structural sign of coupling that must be broken.
6.Architectural design

Architectural design: the overall structure.

Architectural design decides how the system is organised as a set of communicating subsystems and how responsibility is allocated across them. It is the critical link between requirements engineering and design: the earliest decisions, and the most expensive to reverse.

Where it fits

The first design activity. It sits directly after analysis and before detailed design, and it sets the frame every later decision works inside. Get it wrong and no amount of detailed design recovers the lost quality.

What it produces

The output of architectural design is an architectural model: a description of how the system is organised as a set of components and how those components relate. In UML that model is carried by the structural diagrams from Chapter 4, the component and deployment diagrams, plus the chosen style. The model is an abstraction; it deliberately omits internal detail so the overall structure can be discussed and reasoned about as a whole.

Why architecture matters

Architectural design decisions

Architectural design is a creative process, so it cannot be reduced to a fixed procedure; but a small set of questions recurs across every design process, and the answers are the architectural decisions that shape the system's non-functional behaviour. Sommerville frames them as eight:

  1. Is there a generic application architecture (an architectural style) that can act as a template for the system being designed?
  2. What will be the fundamental approach used to structure the system?
  3. How will the structural components in the system be decomposed into sub-components (subsystems)?
  4. What strategy will be used to control the operation of the components in the system?
  5. How will the system be distributed across hardware cores or processors (the layer-to-tier mapping)?
  6. What architectural pattern or style might be used?
  7. What architectural organisation is best for delivering the non-functional requirements of the system?
  8. How should the architecture of the system be documented (and evaluated against the design goals)?

Every one of these answers affects the non-functional characteristics, which is why architectural design is where most design goals are won or lost. (Source: Sommerville, 9th ed.)

7.Architectural style vs architecture

Style versus architecture: pattern and instance.

The two words are often used loosely, but the distinction is the same one a class diagram draws between a class and its objects.

A style is chosen because its known trade-off matches the system's prioritised design goals. The point of cataloguing styles is that the matching can then be done by recognition rather than from scratch: once the goals are clear, the field of sensible structures narrows to a few named candidates. The catalogue below is that field.

The common styles, developed one by one in the next section: layered, client-server, peer-to-peer, three-tier / four-tier, model-view-controller (MVC), repository, pipe-and-filter, and service-oriented (SOA).

8.The catalogue of architectural styles

The style catalogue: shapes with known trade-offs.

Each style below is a recurring arrangement of subsystems with a known shape, the roles its parts play, and the design goals it serves and sacrifices. Hover any glyph in a diagram for what it is.

Layered (n-layer)

A layer is a subsystem that offers a service to the layer above it and uses the service of the layer below. Stacking layers produces an architecture where dependencies point in one direction, downward, so each layer can be understood and replaced given only the interface of the one beneath it. A generic four-layer arrangement separates the interface, its presentation logic, the application, and the platform underneath:

Figure 3
A generic layered architecture: each layer uses only the one below.
User interface User interface management Application logic / services System support (OS, database) uses
A partition divides one layer into weakly coupled, same-level subsystems (by area of responsibility); a layer divides by level of abstraction. The classic illustration is an operating system: layer 0 the scheduler, layer 1 the pager, layer 2 communication with the console, layer 3 the I/O device manager, layer 4 the user programs, with a GUI-services partition sitting beside the user-programs layer.
NameLayered architecture
DescriptionOrganises the system into layers with related functionality associated with each layer. A layer provides services to the layer above it, so the lowest-level layers represent core services that are likely to be used throughout the system.
When usedWhen building new facilities on top of existing systems; when the development is spread across several teams with each team responsible for a layer of functionality; when there is a requirement for multi-level security.
AdvantagesAllows replacement of entire layers so long as the interface is maintained. Redundant facilities (e.g. authentication) can be provided in each layer to increase the dependability of the system.
DisadvantagesIn practice, providing a clean separation between layers is often difficult, and a high-level layer may have to interact directly with lower-level layers rather than through the one immediately below it. Performance can be a problem because of the multiple levels of interpretation of a service request as it is processed at each layer.

The pattern table above is Sommerville's standard form (name, description, when used, advantages, disadvantages); the same form is given for each of the styles below, so the whole catalogue reads consistently.

Closed (opaque) versus open (transparent) layering

A layered architecture comes in two variants that differ only in which lower layers a layer is allowed to call. The choice is a direct trade between coupling and runtime efficiency, and it is tied to different design goals.

Figure 3b
Closed layering (direct addressing) versus open layering (indirect addressing).
Closed · direct addressing Layer 1 Layer 2 Layer 3 OS / libraries Open · indirect addressing Layer 1 Layer 2 Layer 3 OS / libraries
Closed layering minimises coupling and maximises portability and maintainability; open layering minimises call overhead and maximises runtime efficiency. The choice is made by reading which design goal leads: maintainability and flexibility point to closed, raw runtime efficiency points to open.

Hierarchical relationships: depends-on versus calls

Two different relationships connect layers, and UML draws them with different lines, a point worth getting exactly right:

A single pair of subsystems can have both relationships at once: A may both depend on B at build time and call B at run time, drawn as a solid and a dashed line between the same two boxes.

Client-server

Client-server is a special case of the layered style in which the layers are split across machines. One or more servers provide a service; many clients call on it. The server owns the shared data and the logic that protects it; each client owns its own user interface and calls the server when it needs the service.

Figure 4
Client-server: many clients, one shared server. Hover a part or a link.
Client<<client>> Client<<client>> Client<<client>> Database server<<server>> request / reply
When to use: data in a shared database must be reached from many places. Cost and limits: the server centralises control and is a single point of failure and a performance bottleneck; clients cannot talk to each other, and the server cannot push to clients when data changes (it can only answer requests). Those last two limits are exactly what the peer-to-peer style removes.
NameClient-server
DescriptionThe functionality of the system is organised into services, with each service delivered from a separate server. Clients are users of these services and access servers to make use of them.
When usedWhen data in a shared database has to be accessed from a range of locations. Because servers can be replicated, it may also be used when the load on a system is variable.
AdvantagesServers can be distributed across a network. General functionality (e.g. a printing service) can be available to all clients and need not be implemented by all services.
DisadvantagesEach service is a single point of failure, so susceptible to denial-of-service attacks or server failure. Performance may be unpredictable because it depends on the network as well as the system. There may be management problems if servers are owned by different organisations.

Read against the design goals, the client-server style scores as follows (the deck's feature assessment):

Design featureLevelWhy
Service portabilityHighThe server runs on many operating systems and networking environments.
Location transparencyReasonableThe server might itself be distributed, but presents a single "logical" service to the user.
PerformanceReasonableThe client is optimised for interactive, display-intensive tasks; the server for CPU-intensive operations.
ScalabilityHighOne server can handle a large number of clients.
Client portabilityReasonableThe client interface can support a variety of end devices (phone, laptop, wearable).
ReliabilityReasonableThe server survives some client and communication failures; one client crashing does not bring the system down.

In UML the relationship is drawn as an association between Client (role requester) and Server (role provider), with the server exposing its public operations service1()…serviceN(). The client knows the server's interface; the server does not need to know the client's.

Peer-to-peer

Peer-to-peer generalises client-server by collapsing the two roles into one. A peer is both client and server: it requests services from other peers and provides services to them. There is no central authority, so there is no single bottleneck and no single point of failure, and peers can communicate directly.

Figure 5
Peer-to-peer: every node is both client and server.
Peer Peer Peer Peer Peer
Two readings of "peer" are current: a peer can be either a client or a server at a given moment, or a peer can be both at once. When to use: no natural central authority, and resilience or scale matters (file sharing, blockchains, messaging). Cost: consistency, discovery, and security are all harder without a central point to enforce them.

Modelling "a peer can be a client as well as a server". Two inheritance models are proposed, and only one is correct. Model 1 makes Peer the parent and has Client and Server inherit from it: this reads "a peer is either a client or a server", which is not what peer-to-peer means. Model 2 (correct) makes Peer inherit from both Client and Server: this reads "a peer is a client as well as a server", which is the definition. The right model is the one whose inheritance, read aloud, states the requirement.

NamePeer-to-peer (P2P)
DescriptionThe system is organised as a set of equal nodes (peers), each acting as both client and server, that communicate directly with one another rather than through a central server. Any peer may initiate a request to any other.
When usedWhen there is no natural central authority, or a central server is to be avoided, and the data or load is spread across many equal participants: file sharing, blockchains, and some messaging and collaboration systems.
AdvantagesNo single point of failure and no central bottleneck; the system scales with the number of peers; storage and compute are pooled across the nodes.
DisadvantagesSecurity, consistency and peer discovery are all harder with no central point to enforce them; the overall behaviour is harder to reason about; every node must implement both roles.

Three-tier, four-tier: layer versus tier

A layer is a logical type: a subsystem at one level of abstraction. A tier is a physical allocation: the node a layer is deployed on. The two are often used interchangeably, but the distinction is exact. A three-layered style becomes a three-tier architecture only when its three layers are placed on three separate nodes:

Figure 6
Layer (logical type) mapped onto tier (physical node).
Layers (logical types) Presentation Business logic Data Tiers (physical nodes) Client node<<node>> Application server<<node>> Database server<<node>> deployed on
The same three layers can be deployed two-tier (layers share fewer nodes), three-tier (one node each), or four-tier (an extra web or security tier in front). More tiers buy independent scaling and isolation at the cost of network hops and operational complexity. The choice of tiers is a deployment decision over a fixed layer design, which is why the deployment diagram is where it is drawn.
NameThree-tier (and four-tier)
DescriptionA layered architecture whose layers are allocated to separate hardware nodes (tiers): presentation on the client, application and business logic on a middle server, and data on a database server. A four-tier variant inserts a further node, typically a web or security/gateway tier, in front of the application tier.
When usedFor distributed, usually web-based, systems where presentation, logic and data must run on separate machines for scale, security or manageability, and many clients are served at once.
AdvantagesEach tier can be scaled, secured and replaced on its own; the presentation tier never reaches the database directly (an opaque, layered path); supports large numbers of concurrent clients.
DisadvantagesMore infrastructure to deploy and operate; every request crosses tier boundaries, adding latency; the middle tier can become a bottleneck and must be sized for the load.

Model-View-Controller (MVC)

The problem. In an interactive system the presentation (the boundary objects: screens, forms, reports) and the data (the entity objects) tend to become tightly coupled. Change the data and you are forced to change every screen that shows it; change a screen and you reach into the data objects. The user interface cannot be re-implemented without touching the data representation, and the data cannot be reorganised without touching the interface. That coupling is exactly what makes such systems expensive to change.

The solution: decouple. MVC separates presentation and interaction from the system data by splitting an interactive application into three logical components, so that data can change independently of its representation and the same data can be shown in several ways at once. It is the dominant style for user interfaces.

Figure 7
MVC: three roles in a triangle, not a stack. Hover a role.
user actions updates notifies / updates Controller View Model
Sequence of one interaction: the user acts on the View; the View passes the action to the Controller; the Controller updates the Model; the Model notifies the View, which re-reads the Model and redraws. MVC vs three-tier: MVC is non-hierarchical (triangular) - the View is updated directly from the Model; three-tier is hierarchical (linear) - the presentation layer never talks to the data layer directly, every call passes through the middle layer. MVC dates from the late 1970s (Smalltalk); three-tier from 1990s web applications.
Figure 7b
MVC in a web application: the three roles mapped onto a browser and a web server. Hover any box or arrow.
Browser <<client>> web server Controller maps requests to actions Model business logic + database View renders HTML / forms 1: HTTP request 2: update 3: state 4: select view 5: HTTP response (HTML page)
The same three roles as the triangle, now placed in a web application, which is the concrete form you are commonly asked to draw. The browser is the client; the Controller, Model and View all run on the web server. One request flows 1 to 5: the browser sends an HTTP request to the Controller (1); the Controller updates the Model (2) and selects a View (4); the View reads the Model's state (3) and returns the rendered HTML page to the browser (5). The Model still holds all business logic and never formats HTML; the View never holds business rules; the Controller owns the request-to-action mapping.

How a view stays current: subscribe and notify. The Model does not call the views; that would couple it back to the presentation it is meant to be independent of. Instead each View subscribes to the Model. When the Model's data changes, it notifies its subscribers, and each notified View re-reads the Model and redraws itself. This is the observer mechanism, and it is what lets several views of one model (a table, a chart, a summary) all refresh from a single change without the Model knowing any of them by name. It is also why the relationship is drawn as a triangle rather than a stack: the View is updated directly from the Model, not through the Controller.

NameModel-View-Controller (MVC)
DescriptionSeparates presentation and interaction from the system data. The system is structured into three logical components that interact with each other. The Model component manages the system data and associated operations on that data. The View component defines and manages how the data is presented to the user. The Controller component manages user interaction (keystrokes, mouse clicks, etc.) and passes these interactions to the View and the Model.
When usedUsed when there are multiple ways to view and interact with the same data. Also used when the future requirements for interaction and presentation of the data are not known.
AdvantagesAllows the data to change independently of its representation and vice versa. Supports presentation of the same data in different ways, with a change made in one representation shown in all of them.
DisadvantagesCan involve additional code and code complexity when the data model and the interactions are simple.

Which design goal does MVC buy? Modifiability: by decoupling the entity objects from the boundary objects it removes the coupling that makes interactive systems expensive to change, at the price of extra structure (the disadvantage above) when the interface is trivial. That is the trade-off the design-goals table calls out: you spend simplicity to buy independent change.

Repository

In the repository style, all shared data is held in one central store, and the subsystems interact only through it; none calls another directly. The subsystems are therefore loosely coupled to each other (they are coupled only to the repository's schema), and the repository is the single source of truth.

Figure 8
Repository: subsystems share state only through a central store.
Repository<<repository>> Editor Compiler Analyser Debugger
The classic example is an IDE: editor, compiler, analyser, and debugger all work on one shared project model, and a change one tool makes is immediately visible to the others. When to use: tools or components that must share a large, evolving body of data. Cost: the repository is a single point of failure and a bottleneck, and every subsystem is coupled to its schema, so the schema is hard to change.
NameRepository
DescriptionAll data in a system is managed in a central repository that is accessible to all system components. Components do not interact directly, only through the repository.
When usedWhen you have a system in which large volumes of information are generated that has to be stored for a long time. Also used in data-driven systems where the inclusion of data in the repository triggers an action or tool.
AdvantagesComponents can be independent: they need not know of the existence of other components. Changes made by one component can be propagated to all components. All data can be managed consistently (e.g. backups done at the same time) as it is all in one place.
DisadvantagesThe repository is a single point of failure, so problems in it affect the whole system. There may be inefficiencies in organising all communication through the repository. Distributing the repository across several computers may be difficult.

Pipe-and-filter

In the pipe-and-filter style, data flows through a chain of independent filters, each transforming its input and passing the result down a pipe to the next. Filters share nothing but the stream between them, so each can be developed, replaced, or reordered on its own.

Figure 9
Pipe-and-filter: a chain of independent transforms.
Source Filter Filter Sink
When to use: batch or stream processing where work is a sequence of transforms (Unix pipelines, compilers, data-processing pipelines). Cost: poor fit for interactive systems, and a common data format has to be agreed for the stream that passes between filters.
NamePipe and filter
DescriptionThe processing of the data is organised so that each processing component (filter) is discrete and carries out one type of data transformation. The data flows (as in a pipe) from one component to another for processing.
When usedCommonly used in data-processing applications (both batch- and transaction-based) where inputs are processed in separate stages to generate related outputs.
AdvantagesEasy to understand and supports transformation reuse. The workflow style matches the structure of many business processes. Evolution by adding transformations is straightforward. Can be implemented as a sequential or a concurrent system.
DisadvantagesThe data-transfer format has to be agreed between communicating transformations. Each transformation must parse its input and unparse its output to the agreed form, which increases overhead and may make it impossible to reuse transformations that use incompatible data structures.

Two canonical examples: the Unix shell command ls -a | cat, where ls and cat are filters and the | is the pipe; and an invoice/payments system, where "read issued invoices" feeds "identify payments", which forks to "issue receipts" and to "find payments due → issue payment reminder".

Service-oriented (SOA) and microservices

In a service-oriented architecture the system is built from independent services, each owning a slice of functionality and communicating over the network through published interfaces. Microservices are the modern, fine-grained form. Because each service is deployed and scaled on its own, the style buys independent evolution and elastic scale; the price is operational complexity and the distributed-system problems (partial failure, latency, eventual consistency) that a single-process design never has. It is best read as client-server generalised to many small, independently deployable servers.

NameService-oriented architecture (SOA) / microservices
DescriptionThe system is decomposed into independent services, each owning one capability and exposing it through a published, network-accessible interface. Services are composed to deliver the application and may be developed, deployed and scaled independently; microservices are the fine-grained modern form.
When usedFor large systems that must evolve and scale part by part, be built and owned by several independent teams, or reuse capabilities across more than one application.
AdvantagesEach service can be developed, deployed, scaled and replaced on its own; teams work independently; services may use different technologies and be reused across systems.
DisadvantagesFull distributed-system complexity: partial failure, network latency and eventual consistency; harder to test and monitor end to end; the operational overhead of many independently deployed units.
9.Choosing a style: goals to structure

Choosing a style: matching shape to goal.

A style is chosen because its known trade-off serves the system's prioritised design goals. The choice is a matching exercise: read the top one or two goals, and the field narrows to a few candidates.

If the leading design goal is…Candidate style(s)Why it fits
Maintainability and replaceabilityLayeredOne-way dependencies; a layer can be replaced behind its interface without disturbing the rest.
Shared data reached from many placesClient-server, RepositoryA single store owns the data and the rules that protect it.
Independent scaling of partsThree-tier, SOA / microservicesTiers or services sit on separate nodes and scale on their own.
Resilience, no single point of failurePeer-to-peerNo central authority to fail or bottleneck.
Decoupling presentation from dataModel-View-ControllerThree roles let the UI and the data change independently.
Sequential data transformationPipe-and-filterIndependent filters chained by a shared stream; easy to reorder and extend.
Tools sharing a large, evolving modelRepositoryOne source of truth that every tool reads and writes.
Independent deployment and team autonomySOA / microservicesEach service is owned, deployed, and scaled separately.

Real architectures almost always blend styles rather than pick one. A typical web system is layered overall, with MVC inside its presentation layer, a repository (relational database) at its data layer, and the whole deployed three-tier. The styles compose because each governs a different concern; the skill is naming which style is doing which job, and why.

10.The 4+1 view model

The 4+1 view model: one architecture, several projections.

No single diagram captures an architecture. Kruchten's 4+1 view model (1995) describes it from several viewpoints at once, each addressing a different stakeholder concern, and each maps onto a UML diagram from Chapter 4.

ViewThe concern it answersUML diagram
LogicalWhat functionality does the system provide?class and object diagrams
ProcessHow does it behave and coordinate at run time?activity and sequence diagrams
DevelopmentHow is the software organised for building?component (and package) diagrams
PhysicalHow does the software map onto hardware?deployment diagrams
+ ScenariosDo the four views actually work together?use case diagrams

The "+1" is the set of scenarios (use cases) that animate the other four and check they agree: a scenario is walked through the logical, process, development, and physical views to confirm the architecture actually supports it. This is the same idea as Sommerville's four perspectives (context, interaction, structural, behavioural): a system is understood only by looking at it from more than one direction at once, and the views are kept honest by the scenarios that cut across them.

11.Worked example: designing an architecture

From goals to a justified architecture: the seminar system.

The pieces in order, on one system: read the goals, decompose, choose styles whose trade-offs serve the goals, and justify each choice. The realised structure is the seminar-registration architecture drawn in the Chapter 4 companion.

Stage 1: Design goals, from the non-functional requirements

The system holds student records, serves many concurrent users at registration time, and must outlive several rounds of interface change. Turning those non-functional requirements into prioritised design goals gives: security of student data; maintainability (the interface will change often); independent scaling of the web front under load; and reuse of the university's existing authentication and database. These are the goals every later decision is justified against.

Stage 2: Subsystem decomposition (cohesion and coupling)

Group classes for high cohesion and low coupling: a <<UI>> presentation subsystem; three business-domain subsystems (Seminar, Schedule, Student), each cohesive around one concept; and shared <<infrastructure>> subsystems (Security, Persistence). Each business component reaches data only through the Persistence interface and security only through AccessControl, so coupling is held to the width of those interfaces.

Figure 10
Realised architecture: three layers, with MVC in the presentation layer. Hover any part.
presentation layer (MVC) Registration UI <<UI, MVC>> business-domain layer Seminar<<component>> Schedule<<component>> Student<<component>> infrastructure & data layer Security<<infrastructure>> Persistence<<infrastructure>> University DB<<database>> uses DataAccess <<JDBC>>
The decomposition, laid out as the three layers. The presentation layer is built MVC; the three business components are cohesive around one concept each and reach data only through the Persistence component's DataAccess interface (repository style, one shared University DB); Security is the cross-cutting infrastructure component. This is the structural view; the reasoning for why it takes this shape is the table below.

Stage 3: Chosen styles, each tied to a goal

DecisionStyleGoal it serves
Three layers overall (presentation, business, data)LayeredMaintainability: the interface layer can be rebuilt behind a stable interface without touching business logic.
Presentation layer split into model, view, controllerMVCMaintainability: decouples the changing interface from the stable domain model.
Data held in one shared university databaseRepositoryReuse and a single source of truth for student records.
Layers deployed on separate client, application, and database nodesThree-tierIndependent scaling of the web front; security, since the database sits behind the application tier and is never exposed to the client.
Authentication delegated to a shared Security componentinfrastructure subsystemReuse of the university identity service; one enforcement point for access control.

Stage 4: Deployment (the three tiers)

The three layers are allocated to three separate nodes: presentation on the client, the business logic on an application server, and the data on a database server. That allocation is what makes the layered design a three-tier architecture, and it is drawn as a deployment diagram.

Figure 11
Three-tier deployment of the seminar system.
Client<<device>> <<artifact>>Browser Application Server<<device>> <<artifact>>seminar.war Database Server<<device>> <<artifact>>university.db <<HTTPS>> <<JDBC>>
Each layer on its own node: the client runs the browser, the application server holds the deployed seminar.war, and the database server holds university.db. The client reaches the application server over <<HTTPS>> and never touches the database directly, that opaque path is the security the third tier buys.

Stage 5: The trade-offs accepted

Three tiers add two network hops and two more nodes to operate, accepted for the scaling and security they buy. Layering adds a call through the middle layer on every data access, accepted for the maintainability. Naming the trade-off, rather than hiding it, is what makes the design defensible: the goals in Stage 1 are the standard each of these costs is judged against.

12.Pitfalls

Where system designs go wrong.

13.Practice questions

Practice questions: work each one, then check yourself.

Questions across the main points of system design, from precise definitions to distinguishing concepts to reasoning about a scenario. Work each one fully before opening the answer; the answers are deliberately tight, in the form a strong solution takes.

Q1Define cohesion and coupling. For each, say whether a good design seeks it high or low, and give one reason.

Cohesion measures the strength of functional relatedness among the classes within one subsystem; a good design seeks it high, because a subsystem that does one related thing is easier to understand, maintain, and reuse. Coupling measures the degree of interdependence between subsystems; a good design seeks it low, because then a change to one subsystem has minimal or no effect on the others, so each can be understood, tested, and replaced on its own. High cohesion tends to produce low coupling, because gathering related work into one subsystem keeps most interaction internal.

Q2Distinguish a layer from a partition.

A layer is a subsystem that provides a service to the layer above and uses the service of the layer below; layers divide the system vertically, by level of abstraction, and a layer depends only on lower layers and has no knowledge of higher ones. A partition divides one layer horizontally into several independent, same-level subsystems (weakly coupled peers) that provide services to one another; partitions divide by area of responsibility, not level of abstraction.

Q3Closed versus open layering: define direct and indirect addressing, and state the design goal each serves.

Closed (opaque) layering uses direct addressing: a layer may call operations only from the layer directly below it. It is more portable and gives low coupling, serving maintainability and flexibility. Open (transparent) layering uses indirect addressing: a layer may call operations from any layer below it. It is more efficient but increases coupling, serving runtime efficiency.

Q4Distinguish "depends on" from "calls" between subsystems, and give the UML line convention for each.

"Depends on" is a compile-time dependency: the depended-on subsystem must be built first (the relationship a build tool such as make or maven orders). UML draws it with a solid line. "Calls" is a runtime dependency: at execution one subsystem invokes another (a browser calls a web server). UML draws it with a dashed line. The same pair may have both at once.

Q5Distinguish architectural style from software architecture, and relate both to subsystem decomposition.

Subsystem decomposition is the identification of subsystems, services, and their relationships. An architectural style is a pattern for a subsystem decomposition (layered, client-server, repository, etc.). A software architecture is an instance of an architectural style applied to one specific system. Style is to architecture as class is to object.

Q6For performance, security, availability and maintainability, state how each is achieved architecturally. Why can you not maximise performance and maintainability at once?

Performance: localise critical operations, minimise inter-component communication, and use large (coarse-grain) components. Security: use a layered architecture with the critical assets in the inner layers. Availability: include redundant components and fault-tolerance mechanisms. Maintainability: use fine-grain, replaceable components. Performance and maintainability conflict directly: performance wants large components and few calls, maintainability wants fine-grain replaceable ones, so the two goals must be prioritised rather than both maximised.

Q7What limitation of client-server does peer-to-peer remove? Using inheritance, model "a peer is a client as well as a server", and say why the alternative model is wrong.

Client-server provides no peer-to-peer communication: calls are triggered only by a client, never by the server, so the server cannot, for example, notify a client when shared data changes. Peer-to-peer removes this by making every node both client and server. The correct model has Peer inherit from both Client and Server ("a peer is a client as well as a server"). The wrong model makes Peer the parent of Client and Server, which reads "a peer is either a client or a server", not what peer-to-peer means.

Q8Distinguish a layer from a tier. What turns a three-layered style into a three-tier architecture?

A layer is a logical type (a subsystem at one level of abstraction); a tier is its physical allocation (the hardware node it runs on). A three-layered style (user interface, middleware, database) becomes a three-tier architecture only when its three layers are deployed on three separate hardware nodes. A four-tier architecture inserts a further node, typically an application server for session management and dynamic content between the web server and the database.

Q9MVC versus three-tier: which is hierarchical and which is not, and what does that mean for how the view gets its data?

MVC is non-hierarchical (triangular): the View sends user actions to the Controller, the Controller updates the Model, and the View is updated directly from the Model. Three-tier is hierarchical (linear): the presentation layer never communicates directly with the data layer; all communication passes through the middle (middleware) layer. So in MVC the view reads the model directly; in three-tier the presentation tier must go through the middle tier to reach data.

Q10A development environment has an editor, a compiler, an analyser and a debugger that must all work on one large, evolving project model. Name the most suitable architectural style and justify it, then state its main risk.

The repository style: all the tools read and write a single central project repository and never call each other directly, so they are loosely coupled and a change one tool makes is immediately available to the others, exactly what is needed when components share a large, evolving body of data. Its main risk is that the repository is a single point of failure and a potential bottleneck, and every tool is coupled to its schema, so the schema becomes hard to change.

Single-best-answer questions

Choose the one best answer for each, then check the answers below. (More than one answer marked is wrong.)

  1. Between two subsystems, a runtime “calls” dependency is drawn in UML as: (a) a solid line; (b) a dashed line; (c) a hollow triangle; (d) a filled diamond.
  2. In a closed (opaque) layered architecture, a layer may call operations from: (a) any layer below it; (b) only the layer directly below it; (c) any layer, above or below; (d) only the layer directly above it.
  3. Which architectural style is non-hierarchical (triangular), with the view updated directly from the model? (a) three-tier; (b) pipe-and-filter; (c) model-view-controller; (d) layered.
  4. Subsystems that share data only through one central store, and never call one another directly, use the ______ style: (a) client-server; (b) repository; (c) peer-to-peer; (d) pipe-and-filter.
  5. Localising critical operations and using large-grain components, to minimise communication between components, chiefly serves: (a) maintainability; (b) security; (c) performance; (d) portability.
  6. A style becomes a tiered architecture only when its layers are: (a) drawn with dashed lines; (b) allocated to separate hardware nodes; (c) made highly cohesive; (d) merged into one subsystem.
AnswersAnswers, with the one-line reason

1 (b) a dashed line marks a runtime call; a solid line marks a compile-time “depends on”. 2 (b) closed layering is direct addressing, the layer directly below only. 3 (c) MVC is triangular, the view reads the model directly; three-tier is linear. 4 (b) a single central store with no direct calls is the repository. 5 (c) coarse-grain components and fewer calls serve performance (and pull against maintainability). 6 (b) layers are logical; a tier is a layer allocated to its own hardware node.

14.References

References.

Bruegge and Dutoit's system-design framework and Sommerville's chapter on architectural design anchor this material; the works below are those directly referenced, alongside the standard practitioner references.