Skip to main content

48433 - Summary

1. Introduction to Software Architecture

1.1 Introduction

What Is Software Architecture?

Definition: the set of structures needed to reason about a system — its elements, their relations, and their properties (Bass, Clements & Kazman, 2022).

In short: it's the system's blueprint — not the code itself, but the map of what parts exist and how they connect, so you can understand the system without reading every line of code.

  • Not vague decisions: it's not just "early decisions" or "major decisions" — those labels are too fuzzy to define.
  • An abstraction: shows the public interface of each part, hides the private implementation.
  • Multiple views, one system: like the human body — skeletal, muscular, nervous, and circulatory systems are different diagrams, but all describe the same body.

Three Kinds of Architectural Structures

Every system needs three different diagram types, each answering a different question:

StructureShowsAnswers
Component-and-ConnectorWhat's running, and how the pieces talk to each otherWhat talks to what? What's shared/replicated?
ModuleHow the code is split into classes/packagesWho owns what code? What depends on what?
AllocationHow software maps onto hardware/teams/filesWhere does it run? Who builds it?

Component-and-Connector

Module elements

Deployment structure

Why Architecture Matters

Architecture is cheap to change on paper, and very expensive to change once built — so getting it right early matters more than almost anything else in a project.

  • Cheap to explore, expensive to change — test ideas on the model before building the real thing.
  • Shared language — lets business owners, architects, and developers discuss the same system.
  • Reusable abstraction — a good architecture can guide future, similar systems.

Three Key Effects

  1. Lasts a long time — hard to change once built.
  2. Determines what's possible later — constraints lock in early.
  3. Determines quality (performance, security, maintainability) — can't easily bolt these on afterward.

Trade-off: systems built for speed are hard to maintain; systems built for easy maintenance are hard to speed up. You usually can't optimise for both.

SOLID Principles

Five rules for designing classes so a codebase stays easy to change as it grows. Each one follows the same pattern: Rule → Problem it prevents → Fix.

S — Single Responsibility
  • Rule: One class = one job.
  • Problem: A class that both formats a report and saves it to disk has two reasons to change — a formatting update and a storage update both touch the same class.
  • Fix: Split it into two classes — one for content, one for output — so each only changes for one reason.
O — Open/Closed
  • Rule: Add new behaviour without editing existing, working code.
  • Problem: A LogOn function is hard-coded per modem type (DialHayes, DialCourrier...), so it needs editing every time a new modem is released.
  • Fix: Introduce an abstract Modem interface. New modems just implement it — LogOn itself never changes again.
L — Liskov Substitution
  • Rule: If code expects a parent type, you must be able to swap in a child type and nothing breaks.
  • Plain English: A child class is only allowed if it can do everything the parent promised, the same way.

LSP does not "auto-fix" your code. It is a design rule. When inheritance breaks callers, LSP tells you: stop inheriting that way — redesign so the child keeps the parent's promises.


Easy example: Birds

Imagine a function written for any Bird:

def make_it_fly(bird: Bird):
bird.fly() # promise: every Bird can fly
print("Flying!")

Bad design (breaks LSP):

class Bird:
def fly(self):
print("flap flap")

class Penguin(Bird): # ❌ real life: penguin is a bird
def fly(self): # ❌ code life: cannot keep the fly() promise
raise Exception("Can't fly!")

make_it_fly(Penguin()) # 💥 crashes

Real-world "is-a" lied. Callers expected fly() to work. Penguin broke that.

How LSP tells you to fix it:

Don't put fly() on a parent that not all children can honour. Split the types:

class Bird:                    # shared stuff only (eat, sleep, ...)
def eat(self):
print("eating")

class FlyingBird(Bird): # only birds that CAN fly
def fly(self):
print("flap flap")

class Sparrow(FlyingBird):
pass

class Penguin(Bird): # penguin is still a Bird — just not a FlyingBird
def swim(self):
print("swim swim")

def make_it_fly(bird: FlyingBird): # now only flying birds are accepted
bird.fly()
print("Flying!")

make_it_fly(Sparrow()) # ✅ works
# make_it_fly(Penguin()) # ✅ type system / design stops this mistake

What changed?

  • Before: parent promised something some children can't do → crash.
  • After (LSP fix): parent only promises what all children can do. Flying is moved to FlyingBird.

Same idea: Circle / Ellipse (lecture example)

  • Problem: Circle extends Ellipse looks right in maths, but Ellipse promises "set width and height separately." Circle can't keep that promise → wrong results.
  • LSP fix: Don't make Circle inherit Ellipse. Give both a shared parent like Shape with only shared behaviour (e.g. area()).

Remember: LSP = swap the child in, and old code still works. If it doesn't, inheritance is wrong — redesign the hierarchy.

I — Interface Segregation
  • Rule: Many small, client-specific interfaces beat one big one.
  • Problem: One large Service interface serves every client — a change made for Client A risks breaking Clients B and C too, even though they never use that part.
  • Fix: Split it into small, client-specific interfaces so each client only depends on what it actually uses.
D — Dependency Inversion
  • Rule: Depend on abstractions, never on concrete classes.
  • Problem: In procedural code, high-level modules depend directly on low-level details — a change to a detail can ripple all the way up.
  • Fix: Both high-level and low-level code depend on a shared abstract interface instead, so details can change freely without touching the high-level logic.

Quick Reference

PrincipleCore Idea
SSingle ResponsibilityOne class = one job.
OOpen/ClosedExtend without modifying.
LLiskov SubstitutionSubclass must be a drop-in replacement.
IInterface SegregationSmall, focused interfaces.
DDependency InversionDepend on abstractions, not concretions.

Common Challenges Today

  • Systems outgrew simple diagrams — boxes-and-arrows aren't precise enough anymore.
  • More legacy/packaged systems need integrating, not building from scratch.
  • Loosely-coupled components (e.g. microservices) are now the norm.
  • Modelling is essential — too costly to experiment on real systems directly, so solutions are tested on models first.

TL;DR: Architecture = structures for reasoning about a system, seen through C&C / module / allocation views. It matters because it's cheap to explore early but locks in quality and flexibility later. SOLID gives concrete rules for keeping class design flexible. Modern systems demand more rigorous modelling due to scale and complexity.

1.2 C4 model

C4 model

The C4 model is a framework for visualizing software architecture. It acts like a set of maps that help software developers navigate large or complex codebases by zooming in from a high-level overview down to the specific code.

More Information: ![ProcessOn C4 model][https://www.processon.io/blog/c4-model-for-software-architecture]


It is structured into four levels of abstraction:

  • Level 1: System Context: This provides the "overview first" by showing the entire software system, its users, and its dependencies on other systems.
  • Level 2: Containers: This level zooms in to show the overall shape of the architecture and your technology choices. In the C4 model, a software system is made up of one or more "containers" (such as a client-side web app, server-side web app, mobile app, microservice, or database schema).
  • Level 3: Components: Zooming in further, this level displays the logical components and their interactions within a single container.
  • Level 4: Code: This is the most granular level, providing "details on demand" by showing the specific implementation details of the components, such as individual classes.
Example - Internal Banking System
Level 1: System ContextLevel 2: ContainersLevel 3: ComponentsLevel 4: Code
Example - Urban Marathon
L1 & L2 Containers Architecture
L3 Components Architecture
L4 Class Architecture

2. Application Architecture

2.1 Architecture Context

Architecture must consider:

  • Functional requirements: What the system must do.
  • Stakeholder goals: What users, customers, developers, and regulators need.
  • Constraints: Time, budget, skills, technology, and regulations.
  • Enablers: Existing skills, systems, or technologies that can help delivery.
  • Risks: Events that may prevent success.
  • Opportunities: Potential benefits to pursue.

Usage narrative: A short story describing who uses the system, what they do, and their expected outcome.

2.2 Requirements, Quality Attributes, and Risk Management

Functional Requirements

Functional requirements (FRs) describe what the system must do.

Example: The system must allow customers to place online orders.

Functions are assigned to components such as modules, services, databases, and interfaces.

Non-Functional Requirements

Non-functional requirements (NFRs) describe how well the system should work. Quality attributes are a major type of NFR.

  • FR: Process an online order.
  • NFR: Process it securely within two seconds.

NFRs should be specific, measurable, and prioritised. They often conflict: better security can reduce usability, higher availability can increase costs, and better performance can make modification harder.

Quality Attributes

Quality attributeMeaningCommon approaches
AvailabilityThe system is accessible and recovers from failure.Redundancy, retry, circuit breaker
DeployabilityThe system can be released and rolled back safely.CI/CD, blue-green, canary deployment
Energy efficiencyThe system minimises energy consumption.Power monitoring, disabling unused resources
ModifiabilityThe system is easy and inexpensive to change.Low coupling, high cohesion, layers
PerformanceThe system meets speed and resource requirements.Load balancing, throttling
SecurityThe system protects data and access.Validation, intrusion prevention
TestabilityFaults are easy to find and diagnose.Dependency injection, strategy pattern
UsabilityUsers can complete tasks easily.Feedback, undo, progress indicators, MVC

Important Concepts

  • CIA security triad: Confidentiality, Integrity, and Availability.
  • Deployment pipeline: Development → Integration → Staging → Production.
  • Low coupling: Modules have fewer dependencies.
  • High cohesion: Each module has one focused responsibility.
  • Performance measures: Latency, response time, throughput, and memory efficiency.

NFRs and Risk Management

Agile Scrum and DevOps

  • Scrum: Develops software through short sprints.
  • DevOps: Supports continuous testing, deployment, and monitoring.
  • Sprint planning covers requirements, design, NFRs, and risks.

Product Backlog

The product backlog tracks user stories, priorities, sprint allocation, progress, NFRs, and risks. It is continuously updated.

Common NFRs

NFRMeaning
PerformanceSystem response speed
ScalabilityAbility to handle more workload
SecurityProtection of data and access
UsabilityEase of use
MaintainabilityEase of updating and supporting the system

Risk Identification and Assessment

  • Identify: Find and classify potential risks.
  • Assess: Measure probability and impact.
  • Prioritise: Handle the most serious risks first.
  • Record: Add risks to the risk matrix.

Expected Monetary Value

Expected Monetary Value (EMV) estimates the financial effect of a risk:

EMV=Probability×Impact\text{EMV} = \text{Probability} \times \text{Impact}

For multiple outcomes:

Total EMV=(Probability×Impact)\text{Total EMV} = \sum(\text{Probability} \times \text{Impact})

Example:

(0.98×$25,000)(0.02×$5,000)=$24,400(0.98 \times \$25{,}000) - (0.02 \times \$5{,}000) = \$24{,}400

A positive EMV means the expected financial outcome is favourable.

Risk Response and Monitoring

  • Avoid: Remove the risk.
  • Mitigate: Reduce the risk.
  • Accept: Monitor the risk.
  • Transfer: Move the risk to another party.

Assign an owner and response plan, then continuously update the risk matrix.


3. Data Architecture

3.1 Data Modelling

Data modelling designs how data and its relationships should be represented. There are three levels.

Conceptual Data Model

This is the big-picture business view. It defines:

  • Key entities
  • Their relationships
  • Business rules

For a university system, the entities may include Student, Subject, Lecturer, and Enrolment.

At this level, we may say that a student can enrol in many subjects, and a subject can have many students. We do not yet decide on tables, column names, or database technology.

Logical Data Model

This is more detailed but still independent of a particular database system. It defines:

  • Tables or entities
  • Attributes
  • Primary keys
  • Foreign keys
  • Mandatory fields
  • Relationship rules
TableImportant fields
StudentStudentID, Name, Email
SubjectSubjectCode, SubjectName
EnrolmentStudentID, SubjectCode, EnrolmentDate

It explains what the data should look like logically, but not whether a field is VARCHAR(100) or which index will be created.

Physical Data Model

This is the implementation-level database design. It includes:

  • Exact data types, such as VARCHAR, INT, and DATE
  • Tables and associative tables
  • Primary and foreign keys
  • Indexes
  • Database-specific performance settings

3.2 Data Ingestion

Data ingestion means moving data from its original sources into a destination where it can be stored, processed, or analysed.

ETL and ELT

ETL: Extract, Transform, Load

ETL is the traditional approach:

  1. Extract data from source systems.
  2. Transform it by cleaning, standardising, validating, and combining it.
  3. Load the prepared data into a data warehouse.

For example, customer names and dates can be cleaned before being loaded into a reporting database.

The limitation is that data often needs a defined structure before it enters the warehouse. This makes ETL less flexible for real-time, image, video, log, or other unstructured data.

ELT: Extract, Load, Transform

ELT changes the order:

  1. Extract data.
  2. Load it in raw form into a central repository, usually a data lake.
  3. Transform it later when a particular use case needs it.

The main advantage is that the original data is retained. This is useful because:

  • Raw history and lineage are preserved.
  • Structured, semi-structured, unstructured, and streaming data can all be kept.
  • Teams can use data for new purposes later.
  • Data can be accessed before it is fully transformed.

ETL vs ELT

ETLELT
Transform before storage in a warehouseStore raw data first, then transform it
Less flexibleMore flexible
Traditionally batch-basedBetter suited to cloud and diverse data
Raw data may not be retainedRaw data and history are retained

3.3 Data Management Systems

Data Warehouse

A data warehouse is centralised storage designed for analytics, reporting, and business intelligence. It stores curated, structured, cleaned data.

For example, a retail company’s warehouse may combine sales, customer, product, and inventory data to create company-wide reports. It is optimised for large analytical queries, not daily transactional activity such as placing an order.

Data Mart

A data mart is a smaller, focused part of a data warehouse for one business area. Examples include finance, marketing, and HR data marts.

Types of data mart:

  • Dependent: Created from an existing data warehouse.
  • Independent: Created directly from source systems without a warehouse.
  • Hybrid: Combines warehouse data with other operational data.

Data Lake

A data lake stores large quantities of raw data in its original format. It can contain:

  • Tables
  • JSON or XML
  • PDFs
  • Images and videos
  • Logs
  • Sensor data

A warehouse uses more structure before analysis. A lake accepts raw data first and applies structure later when needed.

Warehouse vs Lake vs Mart

FeatureData warehouseData lakeData mart
Data typeMostly curated and structuredAny type, including raw files and mediaFocused subset, usually structured
Main purposeBI, reports, dashboardsExploration, ML, large-scale analyticsDepartment-specific analysis
UsersOrganisation-wide analysts and teamsEngineers, data scientists, analystsOne department or business group
Data schemaUsually schema-on-writeUsually schema-on-readUsually predefined
ExampleCompany-wide sales reportingRaw logs, images, sensor streamsMarketing campaign dashboard

Schema-on-Write vs Schema-on-Read

  • Schema-on-write: Define the structure before storing data. This is common in data warehouses.
  • Schema-on-read: Store data first, then decide its structure when analysing it. This is common in data lakes.

Large Organisations Often Use All Three

3.4 Types of Data Architectures

Data Fabric

A data fabric is an architecture that connects data across many systems, clouds, databases, data lakes, warehouses, APIs, and applications.

Its goal is to make data easier to find, access, govern, and use, even when it is physically stored in many places. Key features include:

  • Data integration: Connects different sources.
  • Data virtualisation: Lets users access data without knowing its physical location.
  • Data governance: Enforces security, privacy, quality, and compliance rules.
  • Data orchestration: Automates pipelines and workflows.
  • Metadata management: Records datasets’ meaning, ownership, and lineage.

Think of data fabric as an intelligent connecting layer over an organisation’s distributed data environment.

Data Mesh

A data mesh is a decentralised approach in which each business domain owns and manages its own data.

For example:

  • Marketing owns marketing data products.
  • Sales owns sales data products.
  • Customer service owns support data products.

Instead of one central data team becoming responsible for every dataset, domain teams take responsibility for making their data useful, documented, secure, and shareable.

Key principles:

  • Domain-oriented ownership: Teams own data from their business area.
  • Data as a product: Data should be reliable, documented, discoverable, and usable by others.
  • Self-service platform: Teams receive shared tools for storage, access, monitoring, and governance.
  • Federated governance: Shared organisation-wide rules exist, while data ownership remains distributed.

Data Fabric vs Data Mesh

Data fabricData mesh
Focuses on connecting and integrating data technicallyFocuses on distributing ownership organisationally
Uses automation, metadata, virtualisation, and orchestrationUses domain teams and data-product thinking
Answers: “How can all our data work together?”Answers: “Who should own and maintain each dataset?”

3.5 Big Data Solutions

Architectural Shifts in the Big Data Era

AreaTraditional approachModern approach
Data generationMostly relational, structured, batch dataRelational + NoSQL, structured + unstructured, batch + real time
IngestionOn-premises ETLCloud ELT and streaming
StorageCentralised warehouseCloud warehouses, distributed storage, data lakes
AnalyticsHistorical reports and data miningPredictive/prescriptive analytics, AI/ML, real-time insights
ConsumptionCentral dashboards and reportsSelf-service tools and AI-driven insights

Polyglot persistence means using different database technologies for different needs, rather than forcing every type of data into one relational database.

NoSQL Databases

NoSQL databases were developed for data that is massive, distributed, rapidly changing, or not neatly structured in tables.

Relational databases are still very important, especially when strong consistency and complex transactions are needed. However, they can be less suitable for huge amounts of sparse, semi-structured, or globally distributed internet-scale data.

Common NoSQL characteristics:

  • Can scale across many machines
  • Support fast reads and writes
  • Often have flexible or schema-less structures
  • Support replication and distribution
  • May accept trade-offs in strict ACID transactions for speed and scalability

Main NoSQL Types

TypeBest forExample use
Key-value storeVery fast, simple lookupsSessions, cache, chat data
Document databaseFlexible JSON-like recordsProduct catalogues, content management
Column storeLarge analytical or time-series dataEvent logs, IoT data
Graph databaseRelationship-heavy dataSocial networks, fraud detection, recommendations

Big Data Architecture Patterns

Batch Architecture

Batch architecture processes accumulated data at scheduled times.

For example, it can generate a sales report every night using all transactions from that day. It is best when immediate results are not required.

Streaming Architecture

Streaming architecture processes data continuously or almost immediately as it arrives.

For example, it can detect suspicious card transactions as they occur. It is best when a fast response is important.

Lambda Architecture

Lambda architecture combines batch and streaming processing:

  • The batch layer processes complete historical data accurately.
  • The speed layer processes recent live data quickly.
  • The results are combined for analysis.

For example, a social-media platform may analyse historical user behaviour in batch while also responding to new posts and interactions in near real time.

3.6 Data Dictionary Table

Purpose and Characteristics

A data dictionary documents each data element, including its:

  • Name
  • Format
  • Length
  • Business meaning

It provides a shared reference for:

  • Consistent database design
  • Data architecture implementation

4. Cloud Reference Architecture

4.1 On-Premisess vs Cloud

On-Premise

On-Premises

An on-premises system is hosted and managed using infrastructure owned by the organisation.

The organisation is responsible for:

  • physical servers;
  • networking equipment;
  • operating systems;
  • databases;
  • application deployment;
  • security;
  • backups and maintenance.

On-premises infrastructure provides greater control but usually requires higher initial costs, specialised staff and more maintenance.

Cloud

A cloud system uses infrastructure and services provided by companies such as AWS, Microsoft Azure or Google Cloud.

Cloud computing provides:

  • faster deployment;
  • elastic scaling;
  • pay-as-you-use pricing;
  • managed backups and recovery;
  • access to specialised services;
  • reduced infrastructure maintenance.

Possible concerns include security, privacy, ongoing costs, internet dependency and vendor lock-in.

ModelDescriptionCustomer managesExample
IaaSProvides virtual infrastructureOS, runtime, applications and dataAWS EC2
PaaSProvides a managed application platformApplications and dataGoogle App Engine
SaaSProvides a complete applicationConfiguration and usageGmail, Salesforce

Other Cloud Service Models

  • Network as a Service (NaaS)
  • Communications as a Service (CaaS)
  • Compute as a Service (CompaaS)
  • Data Storage as a Service (DSaaS)

4.2 Principles for cloud-native architecture

Cloud-native architecture means designing a system to take advantage of cloud capabilities instead of simply placing an existing application on a cloud server.

Principle 1: Design for Automation

Cloud systems should automate repetitive and error-prone activities.

Automation can be applied to:

  • infrastructure provisioning;
  • software building and testing;
  • application deployment;
  • scaling;
  • monitoring;
  • backup and recovery.

Examples include:

  • using Docker to package applications;
  • using Terraform to create infrastructure;
  • using CI/CD pipelines to test and deploy software;
  • using autoscaling to add or remove instances.

Automation makes deployment faster, more consistent and less vulnerable to human error.

Principle 2: Be Smart with State

State is information about a user’s current situation within an application.

Examples include:

  • login status;
  • shopping-cart contents;
  • form progress;
  • game-session progress.

If state is stored inside one application server, the information may be lost when the server crashes. It also becomes difficult to send the user to another server.

Therefore, application servers should be stateless where possible. Important state should be stored externally in systems such as:

  • Redis;
  • managed databases;
  • cloud storage.

For example, an online store can store shopping-cart information in Redis. Any application server can then retrieve the cart using the customer’s identifier.

Principle 3: Favour Managed Services

Managed services are operated and maintained by the cloud provider.

Examples include:

  • managed databases;
  • message queues;
  • cloud storage;
  • machine-learning services;
  • analytics services.

The provider normally handles:

  • infrastructure maintenance;
  • updates;
  • backups;
  • replication;
  • availability.

This allows the development team to focus on the product. However, using provider-specific services may create vendor lock-in.

Vendor lock-in can be reduced by:

  • using open standards;
  • using open-source-compatible services;
  • placing provider-specific code behind interfaces;
  • using containers;
  • documenting a migration strategy.
Principle 4: Practise Defence in Depth

Defence in depth means protecting the system with multiple security layers.

These layers may include:

  1. Edge firewall: blocks suspicious external traffic.
  2. Network segmentation: separates internal parts of the system.
  3. Authentication: verifies the identity of users and services.
  4. Authorisation: controls what each user or service can access.
  5. Application security: validates input and checks permissions.
  6. Endpoint security: protects individual devices and servers.
  7. Encryption: protects data during storage and transmission.
  8. Continuous monitoring: detects suspicious behaviour.

Cloud-native architecture should not automatically trust a component simply because it is located inside the organisation’s network.

Principle 5: Always Be Architecting

Cloud architecture should continuously evolve as:

  • user requirements change;
  • traffic increases;
  • security threats develop;
  • cloud services improve;
  • organisational needs change;
  • new technologies become available.

Architects should regularly review and improve the system rather than waiting for a major failure.

For example, a video-streaming platform must adapt its architecture to support new video formats, higher resolutions and increasing user demand.

Applying the Principles to C4 Diagrams

The container and component diagrams from previous weeks should be updated to reflect cloud decisions.

Possible changes include:

  • replacing a self-hosted database with a managed database;
  • adding object storage;
  • adding a message queue;
  • introducing authentication services;
  • adding caching;
  • separating state from application servers;
  • showing cloud-hosted APIs.

The design should then be justified using the five cloud-native principles.

4.3 Deployment Diagram

A deployment diagram shows how software systems and containers are installed and run on infrastructure in a particular environment, such as development, staging, or production.

  • Deployment nodes represent where software runs, including:

    • Physical servers or devices
    • Virtual machines and cloud services such as IaaS or PaaS
    • Containers such as Docker
    • Execution environments such as database servers, Java application servers, or Microsoft IIS
  • Deployment nodes can be nested. For example, a Docker container may run inside a virtual machine hosted on AWS.

  • The diagram can also include infrastructure components, such as:

    • DNS services
    • Load balancers
    • Firewalls
  • AWS, Azure, or other cloud-provider icons may be used, but all icons should be explained in the diagram’s key or legend.

In simple terms: A deployment diagram explains where each part of a system runs and how the infrastructure components are arranged.

4.3.1 Example Bank Deployment Diagram

4.3.2 Example Pet Clinic Diagram

4.4 System Landscape Diagram

A System Landscape Diagram shows how multiple software systems and people fit together across an organisation, department, or enterprise.

Unlike a standard C4 System Context Diagram, which focuses on one specific system, a System Landscape Diagram provides a broader overview without making any single system the main focus.

  • Scope: An entire enterprise, organisation, department, or similar area.
  • Main elements: People, software systems, and the relationships between them.
  • Purpose: To understand how systems interact and support the wider organisation.
  • Audience: Both technical and non-technical stakeholders, inside and outside the development team.
  • Further detail: Each important system can be explored separately using the standard C4 model.

5. Security and Privacy

5.1 Dynamic Diagram

A dynamic diagram shows how system elements interact at runtime to complete a feature, use case, or user story. Interactions are numbered to show the order of communication. It can include systems, containers, or components.

Purpose: understand how data moves through the system before analysing security threats.

Simple example

User → Login Controller → Security Component → Database → Response

5.2 Threat Modelling

Threat modelling is the process of identifying what could go wrong in a system and how to reduce the risk.

Focus on:

  • Entry points — where users or systems can access the application
  • Trust boundaries — where data moves between different trust levels
  • Data flow — how information moves through the system
  • Threats — possible security problems
  • Mitigations — controls used to reduce those threats

5.3 Security Principles

Minimise Attack Surface

Reduce the number of possible places an attacker can target.

Examples:

  • Disable unnecessary services
  • Close unused ports
  • Limit exposed APIs
  • Restrict admin access
Secure the Weakest Link

A system's security can depend on its least secure component.

Example:

Strong encryption + Secure database + Weak password = Still vulnerable

The tutorial asks you to consider both principles when analysing a system.

5.4 STRIDE Threat Model

STRIDE is used to classify common security threats. Apply it to components and data flows in the architecture to identify possible threats.

STRIDEMeaningSecurity PropertySimple Meaning
SSpoofingAuthenticationPretending to be another user
TTamperingIntegrityChanging data or code
RRepudiationNon-repudiationDenying an action
IInformation DisclosureConfidentialityAccessing information without permission
DDenial of ServiceAvailabilityMaking a service unavailable
EElevation of PrivilegeAuthorizationGaining permissions you should not have

5.5 Mitigation

A mitigation is a security control used to reduce or prevent a threat.

ThreatPossible Mitigation
SpoofingAuthentication / MFA
TamperingIntegrity checks
RepudiationLogging and audit records
Information DisclosureAccess control / encryption
Denial of ServiceRate limiting
Elevation of PrivilegeAuthorization controls

5.6 Connection to C4 Diagrams

Security and privacy should be included in architecture diagrams such as:

  • Application/Data Container Diagram
  • Component Diagram
  • Deployment Diagram

The goal is to show not only how the system is built, but also how it is protected.

Key process to remember

Dynamic Diagram = How the system works Threat Modelling = What could go wrong STRIDE = Classify the threat Mitigation = How to protect against it


6. Architecture Styles and Communication Patterns

Week 6 focuses on:

  • recognising bad architecture
  • understanding dependencies
  • choosing suitable architecture styles
  • choosing how components communicate

6.1 Architecture Smells

Architecture smells are warning signs that a system may be difficult to maintain, change, or scale.

Architecture SmellSimple MeaningMarathon ExampleImprovement
Feature ConcentrationOne component does too many thingsBackend API handles registration, schedules, volunteers, vendors, tracking, notifications, feedback, and resultsSplit into focused components or services
Scattered FunctionalityOne responsibility is spread across multiple componentsNotification responsibilities exist across Web App, Mobile App, Backend API, and Notification ProviderCentralise notification rules
Dense StructureToo many direct dependencies between componentsBackend API directly connects to apps, database, authentication, payment, timing, notification, and mapping systemsUse focused integration components and asynchronous messaging
Cyclic DependencyComponents eventually depend back on each otherNo cyclic dependency identified in the current Marathon architectureRecheck after architecture changes
Unstable DependencyA core component depends directly on less-stable or external systemsBackend API directly depends on Payment, Notification, Mapping, and Timing servicesUse adapters, queues, retries, timeouts, and failure handling
Easy way to identify them
Single Responsibility Principle

To avoid Feature Concentration, each container or component should have one clear responsibility. This keeps changes and fixes focused and localised.

Instead of one Backend API owning every capability:

Backend API
├─ Registration
├─ Tracking
├─ Results
├─ Volunteers
├─ Vendors
└─ Notifications

separate the responsibilities:

Backend API
├─ Registration Component
├─ Event Management Component
├─ Volunteer Component
├─ Vendor Component
├─ Tracking Component
└─ Results Component

The updated Marathon solution follows this structure.

Marathon Database example

The original Marathon Database stores registration, schedules, volunteers, vendors, timing records, results, and feedback, creating Feature Concentration.

The improved architecture separates:

This keeps normal operational data separate from rapidly changing race-tracking data.

6.2 Dependencies

If A → B:

  • A depends on B
  • A must know how to connect to B
  • B does not need to know about A
  • communication can move both ways, but A normally initiates it
Marathon examples
ComponentDepends On
Web ApplicationBackend API
Mobile ApplicationBackend API
Backend APIMarathon Database

6.3 Architecture Styles

Compare architecture styles by advantages, disadvantages, and suitable use cases, then justify which styles should be used in the system.

StyleMeaning / Marathon UseAdvantagesDisadvantages
LayeredSeparates presentation, business, and data responsibilitiesClear structure; easier testing and maintenanceLayers may become tightly coupled; limited independent scaling
Service-OrientedUsed for Payment, Mapping, Notification, and Authentication integrationsReusable services and standard interfacesMore coordination and governance
Event-DrivenUsed for timing, tracking, race updates, and alertsHandles traffic spikes, asynchronous processing, and real-time eventsHarder tracing, testing, ordering, and error handling
MicroservicesSeparate capabilities such as Registration, Tracking, or ResultsIndependent deployment/scaling and failure isolationMore deployment, networking, monitoring, and data complexity
Marathon selected approach

The sample solution uses a hybrid architecture:

6.4 Communication Patterns

The tutorial introduces four main communication methods:

PatternSimple MeaningMarathon Example
RepositoryComponents read and write shared stored dataBackend API → Operational Database
APIConsumer sends a request to a providerWeb/Mobile → Backend API
Persistent ConnectionConnection remains open for real-time communicationNotification Service → Mobile App
Queue / BrokerA middleman carries messages asynchronouslyTiming Events → Event Broker → Tracking Processor

6.5 Repository Communication

Multiple containers read and write data through a shared repository, usually a database.

Limitations

  • mainly supports CRUD
  • constant polling can waste resources
  • multiple writers can create consistency problems

CRUD: Create, Read, Update, Delete.

6.6 API Communication

With APIs, Consumer → Provider. The consumer initiates communication and can pull or push information.

Marathon examples

These use APIs over HTTPS/JSON in the sample architecture.

REST APIs

REST is the main API style discussed in the tutorial.

URL = resource/noun HTTP method = action/verb

MethodExampleMeaning
GET/ticketsRetrieve tickets
GET/tickets/123Retrieve one ticket
POST/ticketsCreate
PUT/tickets/123Update
DELETE/tickets/123Delete

Important response codes:

CodeMeaning
200Success
400Bad request
401Not authenticated
403No permission
404Not found

REST APIs are also stateless: each request is processed independently without relying on previous requests. Data is commonly exchanged using JSON.

API Limitation → Persistent Connections

REST communication is initiated by the consumer. That creates a problem for real-time updates.

The server should not need to wait for the Mobile App to ask for an update. This is where persistent connections are useful.

6.7 Persistent Connections / WebSockets

A persistent connection remains open:

After the consumer creates the connection:

  • the client can send messages
  • the server can send messages
  • either side can close it

Used for timely Marathon:

  • race updates
  • emergency alerts
  • mobile notifications

Limitations

  • Ambiguous interface: WebSockets do not strongly define what messages or events should look like, so both sides must agree on the format.
  • Difficult to scale: persistent connections make the backend more stateful and harder to divide across services.

6.8 Queues and Brokers

Instead of services communicating directly (Producer → Consumer), use a middleman:

Message queues can provide:

  • reliability
  • ordering
  • prioritisation
  • load balancing
  • buffering
  • playback
  • translation
Marathon timing example

This is an important example of event-driven communication:

Why use a broker? If thousands of runners cross checkpoints at once, the broker helps buffer events and decouple the timing devices from processing.

Publish / Subscribe

With Pub/Sub:

  • a publisher produces events
  • a subscriber receives events
  • a service can be both

Events are organised into topics/channels. The publisher does not need to know every subscriber.

Marathon notification example

Instead of Backend API → Notification Provider, the improved architecture uses:

Notification delivery becomes asynchronous, so sending a notification does not need to block the user's main request.

6.9 Marathon Communication Summary

Source → DestinationPatternWhy
Web → Backend APIAPIImmediate response
Mobile → Backend APIAPICurrent race information
Backend → Operational DBRepositoryStore authoritative data
Backend → PaymentAPIPayment confirmation
Backend → MappingAPIRoute information
Timing → IoTBroker / MQTTHigh-volume device communication
IoT → Event ProcessingQueue/BrokerScalable asynchronous processing
Processor → Tracking DBRepositoryFrequent tracking updates
Backend → NotificationsQueue/BrokerAvoid blocking user requests
Notification → MobilePersistent connectionReal-time updates
Main Week 6 takeaway

Architecture Style = how the system is organised. Architecture Smell = warning that the organisation has a problem. Dependency = which component relies on another. Communication Pattern = how components exchange information.

For the Marathon system:

Immediate request?
→ API

Store/retrieve data?
→ Repository

Real-time two-way/update communication?
→ Persistent Connection

High-volume or asynchronous events?
→ Queue / Broker

This is the core logic connecting the Week 6 tutorial concepts to the Marathon Management System sample solution.


7. Architecture Evaluation

Week 7 focuses on:

  • checking whether a design can meet requirements and handle realistic situations
  • comparing architecture alternatives with ATAM
  • finding failure risks with HAZOP
  • documenting decisions and updating the C4 model

7.1 Purpose of Architecture Evaluation

Architecture evaluation checks whether a system design can meet requirements, handle realistic situations, and avoid major failures.

Mistakes are easier and cheaper to fix early.

7.2 ATAM — Architecture Trade-off Analysis Method

ATAM evaluates how well an architecture handles different scenarios and helps compare alternatives.

ATAM = Which architecture is better for this situation, and what trade-offs do we accept?

Tutor sample — architectural alternatives
ScenarioAlternativesBenefitsTrade-offsDecisionJustification
Large burst of timing eventsA: Direct to Backend API
B: IoT Data Ingestion + Event Stream
A: Simple
B: Buffers traffic, scalable, reliable
A: API overload/lost events
B: More infrastructure and ordering complexity
BProtects Backend API and supports race-day scaling
Notification Provider unavailableA: Synchronous API call
B: Queue + asynchronous delivery
A: Immediate result
B: Retries and failure isolation
A: Provider failure affects app
B: Delivery may be delayed
BImproves resilience
Tracking data grows heavilyA: Use Operational DB
B: Separate Tracking Data Store
A: Simple
B: Independent scaling
A: Tracking may slow core DB
B: More integration complexity
BProtects registration/admin workloads
Event burst

Instead of sending timing events straight to the Backend API:

use a buffer so the API is not overwhelmed:

The Event Stream acts as a buffer, so the Backend API is not overwhelmed.

Notification failure

Instead of a synchronous call:

use a queue so the user request does not fail immediately if the provider is down:

Large tracking data

Separate high-volume tracking data from operational data:

This prevents tracking traffic from slowing important operational functions.

7.3 Trade-offs

A design is rarely best at everything.

DecisionImprovesTrade-off
Event StreamScalability, reliabilityMore complexity
Separate Tracking DBPerformanceData consistency becomes harder
Notification queueAvailabilityNotifications may be delayed
ValidationCorrectness / securityMore processing

So architecture evaluation asks:

Are these disadvantages acceptable compared with the benefits?

7.4 HAZOP — Hazard and Operability Analysis

HAZOP looks for possible failures in interactions between system components.

HAZOP = What can go wrong when data moves through the system?

You normally examine an interaction such as:

Then apply guide words.

7.5 HAZOP Guide Words

Guide WordMeaningSimple Example
NoNothing arrivesNo timing event
MoreExtra / duplicate dataSame event received twice
Part ofMissing informationCheckpoint ID missing
Other thanInformation exists but is wrongWrong runner ID
EarlyArrives too earlyEvent received before expected time
LateArrives too lateTracking event delayed
Before / AfterWrong sequenceCP2 processed before CP1

7.6 HAZOP Analysis

Tutor sample — HAZOP analysis
InteractionGuide WordDeviationCauseConsequenceRiskMitigation
Timing Device → IoT IngestionNoNo event receivedDevice / network / battery failureRunner time / location missingHighBuffer locally and resend
Timing Device → IoT IngestionMoreDuplicate eventsRetry / repeated deliveryDuplicate resultsHighUnique event ID + deduplication
Timing Device → IoT IngestionPart ofRequired field missingFaulty / incomplete messageCannot match event correctlyHighValidate required fields
Timing Device → IoT IngestionOther thanWrong runner / checkpoint IDMisconfiguration / tamperingWrong tracking / resultsHighAuthenticate and validate
IoT Ingestion → Event StreamLateEvent delayedCongestion / overload / retriesTracking becomes inaccurateMediumMonitor latency and scale
Event Stream → ProcessingBefore / AfterEvents processed in wrong orderAsync / parallel processingWrong progress / resultsHighTimestamps + sequence numbers
No

Nothing arrives, so the system cannot record the runner event.

More

The same event arrives multiple times.

Use a unique event ID and ignore duplicates.

Part of

Expected:

Runner ID
Checkpoint ID
Time

Received:

Runner ID
Time

Some required data is missing.

Other than

All fields exist, but one is wrong.

Actual runner: 521
Received ID: 125
Late
Runner crosses checkpoint: 10:30
System receives event: 10:36

The event is correct, but too delayed.

Before / After

Expected:

CP1 → CP2 → CP3

Received:

CP2 → CP1 → CP3

Use timestamps and sequence numbers to reorder events.

7.7 HAZOP Answer Structure

A proper HAZOP answer should follow the structure used in the tutor solution:

7.8 ATAM vs HAZOP

ATAMHAZOP
Main purposeCompare architecture choicesFind failure risks
Starts withScenarioInteraction
QuestionWhich design is better?What can go wrong?
Looks atBenefits + trade-offsDeviation + cause + consequence
ResultArchitectural decisionRisk mitigation
ExampleDirect API vs Event StreamWhat if event arrives late?

ATAM = Choose / improve the design HAZOP = Try to find how the design can fail

7.9 Architectural Decisions

After evaluation, important decisions should be documented.

Tutor sample — architectural decisions
IssueDecisionRationale
Timing bursts overload APIUse IoT Ingestion + Event StreamBuffers traffic and allows scaling
Provider failure blocks requestsUse queued notificationsSupports retries and isolates failure
Tracking affects main DBUse separate Tracking StoreIndependent scaling
Duplicate / incomplete eventsValidate and deduplicateProtect result integrity
Events arrive out of orderReorder using timestamps / sequenceCorrect progress / results
Results published too earlyRequire verificationPrevent incorrect official results

A useful documentation pattern is:

7.10 Evaluation Changes the Architecture

The tutor's final architecture adds components because of the problems found during evaluation.

ProblemArchitecture Improvement
Event burstIoT Data Ingestion + Event Broker
Invalid eventsValidation + Dead-Letter Queue
Duplicate / out-of-order eventsTracking Event Processor
Provider failureNotification Worker + Queue
Large tracking volumeSeparate Tracking Data Store
Hard-to-detect failuresMonitoring and Alerting

The updated C4 diagram includes the Event Broker, DLQ, Tracking Processor, Notification Worker, monitoring, separate tracking storage, audit logs, and identity service.

7.11 Dead-Letter Queue

A Dead-Letter Queue (DLQ) stores messages that cannot be processed correctly.

Instead of losing the failed event, the system keeps it for:

  • investigation
  • retry
  • correction

The tutor's architecture sends invalid timing events and failed processing / notifications to the DLQ.

7.12 Monitoring

Monitoring checks whether the architecture is operating correctly.

The sample monitors:

  • queue depth
  • ingestion latency
  • event processing
  • notification delivery
  • DLQ failures

Not every problem can be prevented, so the system must also detect problems quickly.

7.13 Connection to C4

Earlier weeks:

Week 7:

Week 7 is about testing and improving the architecture you already designed.

Main Week 7 takeaway

Architecture Evaluation checks whether a design can handle realistic scenarios and failures. ATAM compares architectural alternatives, benefits, and trade-offs to choose an appropriate design. HAZOP examines interactions using guide words such as No, More, Part of, Other than, Late, and Before / After to identify causes, consequences, risks, and mitigations. The results are then used to improve the architecture, update the C4 model, and document architectural decisions and rationale.