Add AISE502 course materials: script, slides 1-6 (FHGR theme), semester plan, project exercise
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
20
.gitignore
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
# Claude Code session data
|
||||
.claude/
|
||||
|
||||
# macOS
|
||||
.DS_Store
|
||||
|
||||
# LaTeX build artefacts (PDFs are kept as deliverables)
|
||||
*.aux
|
||||
*.log
|
||||
*.out
|
||||
*.toc
|
||||
*.nav
|
||||
*.snm
|
||||
*.vrb
|
||||
*.fls
|
||||
*.fdb_latexmk
|
||||
*.bbl
|
||||
*.blg
|
||||
*.synctex.gz
|
||||
*.synctex(busy)
|
||||
BIN
FHGR_Logo_Large.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
FHGR_Logo_small.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
Folien/AISE502_Vorlesung_1_Folien.pdf
Normal file
719
Folien/AISE502_Vorlesung_1_Folien.tex
Normal file
@ -0,0 +1,719 @@
|
||||
% !TEX encoding = UTF-8 Unicode
|
||||
% ============================================================================
|
||||
% AISE502 -- AI in Software Engineering II
|
||||
% Lecture 1 slides, typeset with the official FHGR beamer theme
|
||||
% (beamerthemeFHGR.sty, University of Applied Sciences of the Grisons).
|
||||
% Slide content is unchanged; only the presentation layer is the FHGR template.
|
||||
% ============================================================================
|
||||
\documentclass[aspectratio=169]{beamer}
|
||||
|
||||
\usetheme[showsection, titlebg=pics/theme_pics/titlepage.png]{FHGR}
|
||||
|
||||
% ============================================
|
||||
% PACKAGES
|
||||
% The theme already loads tikz, graphicx, xcolor, tabularx, colortbl,
|
||||
% listings, hyperref, environ and xparse -- only the extras are needed here.
|
||||
% ============================================
|
||||
\usepackage[british]{babel}
|
||||
\usepackage{booktabs}
|
||||
\usepackage{amsmath}
|
||||
\usepackage{amssymb}
|
||||
\usepackage{tcolorbox}
|
||||
\usetikzlibrary{shapes.geometric, arrows.meta, positioning, fit, backgrounds, calc}
|
||||
|
||||
% ============================================
|
||||
% SEMANTIC COLOURS, MAPPED ONTO THE FHGR PALETTE
|
||||
% The names used throughout the slides are kept, so no slide text changes;
|
||||
% they now resolve to the FHGR brand colours defined by the theme.
|
||||
% ============================================
|
||||
\colorlet{bankblue}{blue} % FHGR blue (4B92A4)
|
||||
\colorlet{bankgreen}{green} % FHGR green (817E65)
|
||||
\colorlet{bankred}{red} % FHGR red (C60219)
|
||||
\colorlet{codegray}{gray} % FHGR gray (595959)
|
||||
\colorlet{backcolour}{linen} % FHGR linen (E1D3B5)
|
||||
\definecolor{aiviolet}{HTML}{6B4E71} % muted plum, kept distinct for the AI lens
|
||||
|
||||
% Attribution labels in English (theme default is German)
|
||||
\renewcommand{\source}[1]{\par\hfill {\tiny\color{FHGRDeco} Source:\,\itshape #1}}
|
||||
\renewcommand{\imagesource}[1]{\par\hfill {\tiny\color{FHGRDeco} Image source:\,\itshape #1}}
|
||||
|
||||
% ============================================
|
||||
% CUSTOM TCOLORBOXES (same semantics as the script, FHGR colours)
|
||||
% ============================================
|
||||
\newtcolorbox{keypoint}{
|
||||
colback=bankblue!7!white,
|
||||
colframe=bankblue,
|
||||
title=Key Concept,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{examplebox}[1][]{
|
||||
colback=bankgreen!10!white,
|
||||
colframe=bankgreen,
|
||||
title={Example: #1},
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{definitionbox}[1][]{
|
||||
colback=linen!40!white,
|
||||
colframe=camel!85!black,
|
||||
title={Definition: #1},
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{thinkbox}{
|
||||
colback=lightGray!35!white,
|
||||
colframe=darkGray,
|
||||
title=Discussion,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{hinweisbox}{
|
||||
colback=bankred!5!white,
|
||||
colframe=bankred,
|
||||
title=Important Note,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{ailinse}[1][]{
|
||||
colback=aiviolet!7!white,
|
||||
colframe=aiviolet,
|
||||
title={AI Lens: #1},
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{projektbox}{
|
||||
colback=bankblue!4!white,
|
||||
colframe=bankblue!70!black,
|
||||
title=Project Link: Portfolio Intelligence Platform,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
% ============================================
|
||||
% TITLE METADATA
|
||||
% ============================================
|
||||
\title[AI in Software Engineering II]{AISE502: AI in Software Engineering II}
|
||||
\subtitle{Lecture 1: Architecture as a Decision Problem\\[0.4ex]{\small Script: Part I, Sections 1--2}}
|
||||
\author{Dr.\ Florian Herzog}
|
||||
\shortname{AISE502}
|
||||
\fullname{Fachhochschule Graub\"unden, Chur -- Autumn Semester 2026}
|
||||
|
||||
\begin{document}
|
||||
|
||||
% ============================================
|
||||
% TITLE SLIDE
|
||||
% ============================================
|
||||
\FHGRTitlePage
|
||||
|
||||
% ============================================
|
||||
% AGENDA
|
||||
% ============================================
|
||||
\begin{frame}{Agenda}
|
||||
\begin{enumerate}
|
||||
\item The module: aims, assessment, semester plan, project
|
||||
\item Four production systems -- two facts
|
||||
\item The decision problem
|
||||
\item What software architecture is (and is not)
|
||||
\item The framework at a glance
|
||||
\item The two AI axes of this module
|
||||
\item Six load-bearing assumptions (A1--A6)
|
||||
\item From questions to dimensions
|
||||
\end{enumerate}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% SECTION 1: THE MODULE
|
||||
% ============================================
|
||||
\section{The Module}
|
||||
|
||||
\begin{frame}{The module in one question}
|
||||
\begin{keypoint}
|
||||
\emph{How do I design, justify, and operate the structure of a software system so that it meets its quality attributes and remains maintainable for years -- even when individual components (AI) are non-deterministic, fallible, and expensive?}
|
||||
\end{keypoint}
|
||||
|
||||
\vspace{0.4cm}
|
||||
This module makes that question \textbf{decidable} -- with a framework of five elements:
|
||||
\begin{itemize}
|
||||
\item a \textbf{demand side} (what the application requires),
|
||||
\item a \textbf{supply side} (what a structure can deliver),
|
||||
\item a \textbf{matching rule}, a \textbf{decision record}, and a \textbf{measurement contract}.
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\textcolor{codegray}{\small Lectures in German -- all materials, the script, and the exam in English.}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Learning objectives}
|
||||
After this module you can \dots
|
||||
\begin{itemize}
|
||||
\item explain why architecture selection is a \textbf{matching problem} -- no pattern is good or bad in itself
|
||||
\item construct a \textbf{requirements profile} $R(a)$: scenarios with response measures, utility tree, weights
|
||||
\item derive the \textbf{capability profile} $C(p)$ of seven architectural patterns from their tactics
|
||||
\item run the \textbf{three-stage, non-compensatory match} and defend the result
|
||||
\item record decisions as \textbf{ADRs} and attach a \textbf{measurement contract} (fitness functions, DORA)
|
||||
\item engineer \textbf{AI components} into a system (Axis B) and use \textbf{AI tools} in the process (Axis A) -- with the same discipline
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Assessment}
|
||||
\begin{columns}[T]
|
||||
\begin{column}{0.48\textwidth}
|
||||
\begin{block}{Project (50\,\%)}
|
||||
\begin{itemize}
|
||||
\item Portfolio Intelligence Platform (group work, all semester)
|
||||
\item Requirements dossier (A1, week 3)
|
||||
\item Architecture dossier: ADR $+$ measurement contract (A2, week 7)
|
||||
\item Implementation (weeks 8--13)
|
||||
\item Final presentation with \textbf{architecture defence} (week 14)
|
||||
\end{itemize}
|
||||
\end{block}
|
||||
\end{column}
|
||||
\begin{column}{0.48\textwidth}
|
||||
\begin{block}{Written examination (50\,\%)}
|
||||
\begin{itemize}
|
||||
\item End of semester, 60 minutes
|
||||
\item \textbf{Open book:} script and own notes, on paper
|
||||
\item \textbf{Closed internet}
|
||||
\item Focus: architecture reasoning -- profiles, matching, trade-offs
|
||||
\end{itemize}
|
||||
\end{block}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{The semester at a glance}
|
||||
\small
|
||||
\begin{center}
|
||||
\begin{tabular}{@{}p{1.5cm}p{4.3cm}p{4.2cm}p{2.7cm}@{}}
|
||||
\toprule
|
||||
\textbf{Weeks} & \textbf{Lectures} & \textbf{Exercise / project} & \textbf{Deliverables} \\
|
||||
\midrule
|
||||
1--3 & Part I: the framework -- dimensions, scenarios, weights & Kickoff; requirements workshops & \textbf{A1} (week 3) \\
|
||||
4--7 & Part II: seven patterns; the match & Architecture study; the match; design & \textbf{A2 $+$ design gate} (week 7) \\
|
||||
8--13 & Parts III--V: classes, fit at scale, the AI dimension & Implementation sprints $+$ coaching & Milestones (weeks 9/11/13) \\
|
||||
14 & Synthesis, exam preparation & \textbf{Presentations $+$ defence} & \textbf{A3} \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\textbf{Design phase} (weeks 1--7): 2 lessons lecture $+$ 2 exercise -- design first, code later.\\
|
||||
\textbf{Implementation phase} (weeks 8--13): 3 lessons lecture $+$ 1 coaching.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{The course project}
|
||||
\begin{projektbox}
|
||||
You will design and build an \textbf{AI-native advisory platform}: answers generated by LLMs over a grounded knowledge base, with deterministic services for portfolio analytics around them. Everything this module teaches -- profiles, matching, ADRs, measurement -- you will apply to \emph{this} system, and defend at the end.
|
||||
\end{projektbox}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\textbf{This week (kickoff exercise):}
|
||||
\begin{itemize}
|
||||
\item form teams; set up repository and tooling (including agentic coding tools)
|
||||
\item build domain understanding; sketch a first ontology
|
||||
\item collect \emph{raw} stakeholder wishes -- unfiltered, unweighted
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\textcolor{codegray}{\small Next week those wishes become \emph{scenarios}; in week 3 they become your requirements profile (deliverable A1).}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% SECTION 2: FOUR SYSTEMS, TWO FACTS
|
||||
% ============================================
|
||||
\section{Four Production Systems -- Two Facts}
|
||||
|
||||
\begin{frame}{Discussion}
|
||||
\begin{thinkbox}
|
||||
\begin{itemize}
|
||||
\item Which software architectures can you name -- and which is the \emph{best} one?
|
||||
\item Is a monolith outdated? Are microservices the professional default?
|
||||
\item Netflix and Amazon run microservices. Should your two-person startup?
|
||||
\item How would you even \emph{decide} -- and how would you defend the decision a year later?
|
||||
\end{itemize}
|
||||
\end{thinkbox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Four production systems, four structures}
|
||||
\footnotesize
|
||||
\begin{center}
|
||||
\begin{tabular}{@{}p{2.2cm}p{4.5cm}p{6.4cm}@{}}
|
||||
\toprule
|
||||
\textbf{System} & \textbf{Structure} & \textbf{Documented outcome} \\
|
||||
\midrule
|
||||
Stack Overflow & \texttt{.NET} monolith, $\sim 9$ on-premise web servers & $\sim 1.3$ billion page views/month at $\sim 12$\,ms render -- scaled \emph{up}, not \emph{out} \\
|
||||
Monzo & $\sim 2{,}800$ Go microservices; one language, one monorepo & retail banking at scale -- viable through extreme technological homogeneity \\
|
||||
Segment & $> 140$ microservices, one per analytics destination & public 2018 \textbf{rollback to a monolith}: complexity crushed a small team \\
|
||||
Prime Video & serverless orchestration: Step Functions, Lambda, S3 & consolidation into one process cut infrastructure cost by $> 90\,\%$ \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\textcolor{codegray}{\scriptsize Sources: Craver 2016; Sewell 2024; Noonan 2018; Kolny 2023 -- each described by the system's own engineers.}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Reading the four cases}
|
||||
\begin{columns}[T]
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankgreen}{\textbf{Same problem, opposite structures}}
|
||||
\begin{itemize}
|
||||
\item Monzo and Stack Overflow both serve millions of users, interactively, at high availability
|
||||
\item one does it with $\sim 2{,}800$ deployment units -- the other with essentially \textbf{one}
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankred}{\textbf{Fashionable structure, expensive failure}}
|
||||
\begin{itemize}
|
||||
\item Prime Video: distributed boundaries in the middle of a tightly coupled data flow
|
||||
\item Segment: services cut along \emph{configuration instances}, not domain seams
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
|
||||
\vspace{0.4cm}
|
||||
\begin{hinweisbox}
|
||||
Neither fact proves monoliths good or microservices bad. Each failure was a \textbf{mismatch} between a workload and a structure -- not a bad pattern.
|
||||
\end{hinweisbox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Two facts -- and the maxim they force}
|
||||
\textbf{Fact 1: Structures differ radically for similar-looking problems.}\\
|
||||
\textcolor{codegray}{\small The grade portal and Instagram share the same load question -- at different magnitudes.}
|
||||
|
||||
\vspace{0.3cm}
|
||||
\textbf{Fact 2: No structure dominates.}\\
|
||||
\textcolor{codegray}{\small For every pattern there is a documented context where it failed expensively -- and one where its unfashionable opposite succeeded at scale (Instagram, Shopify).}
|
||||
|
||||
\vspace{0.4cm}
|
||||
\begin{keypoint}
|
||||
\textbf{Maxim 1.} Patterns are neither good nor bad; only the \textbf{fit} between a requirements profile and a capability profile is.
|
||||
\end{keypoint}
|
||||
|
||||
\vspace{0.3cm}
|
||||
The decision problem: choose among \textbf{non-dominated} alternatives whose value depends on the \textbf{match} -- knowing the choice is \textbf{expensive to reverse}.
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% SECTION 3: WHAT ARCHITECTURE IS
|
||||
% ============================================
|
||||
\section{What Software Architecture Is}
|
||||
|
||||
\begin{frame}{What is ``software architecture''?}
|
||||
The term has a documented tendency to mean \emph{everything and therefore nothing} (Fowler 2003).
|
||||
|
||||
\vspace{0.3cm}
|
||||
\begin{definitionbox}[Software architecture (ISO/IEC/IEEE 42010:2022)]
|
||||
``Fundamental concepts or properties of an entity in its environment and governing principles for the realization and evolution of this entity and its related life cycle processes.''
|
||||
\end{definitionbox}
|
||||
|
||||
\vspace{0.3cm}
|
||||
The standard also creates one \textbf{obligation} this module builds on directly:\\
|
||||
a conformant architecture description \textbf{must record architecture decisions \emph{and their rationale}} (Clause 6.10).
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Four definition families -- each contributes one element}
|
||||
\footnotesize
|
||||
\begin{columns}[T]
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankblue}{\textbf{1. Normative (ISO 42010)}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item shared vocabulary: stakeholders, concerns, views
|
||||
\item obligation: record decisions $+$ rationale
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\textcolor{bankblue}{\textbf{2. Decision-centric (Booch)}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item the \emph{significant} decisions -- significance $=$ \textbf{cost of change}
|
||||
\item lost decision knowledge (\emph{knowledge vaporization}) $\to$ erosion
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankblue}{\textbf{3. Social (Fowler/Johnson)}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item the experts' \emph{shared understanding}; ``the important stuff''
|
||||
\item perceived \textbf{irreversibility} is the core -- architects work to \emph{remove} it
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\textcolor{bankblue}{\textbf{4. Structural-analytic (SEI)}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item ``the set of structures needed to reason about the system''
|
||||
\item functionality is structure-neutral; structure determines \emph{how well}
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
|
||||
\vspace{0.05cm}
|
||||
\begin{keypoint}
|
||||
Distilled: \emph{architecture is the set of hard-to-reverse structural decisions that determine the quality behaviour of a system.}
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Architecture -- design -- implementation: a cost-of-change boundary}
|
||||
\begin{center}
|
||||
\footnotesize
|
||||
\begin{tabular}{@{}llll@{}}
|
||||
\toprule
|
||||
\textbf{Level} & \textbf{Example decision} & \textbf{Reversal cost} & \\
|
||||
\midrule
|
||||
\textcolor{bankred}{Architecture} & monolith vs.\ microservices & months (a migration) & hard to reverse \\
|
||||
\textcolor{bankblue}{Design} & choice of logging library & days (behind an interface) & revisable \\
|
||||
\textcolor{bankgreen}{Implementation} & a variable name & seconds & trivial \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.3cm}
|
||||
\begin{itemize}
|
||||
\item The boundary is \textbf{gradual and context-dependent}: a database choice is architectural without a persistence abstraction -- closer to design in a hexagonal system
|
||||
\item That is the point: \textbf{good architecture pushes decisions from irreversible towards reversible}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Two refusals -- enforced throughout the module}
|
||||
\begin{columns}[T]
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankred}{\textbf{No fashion}}
|
||||
\begin{itemize}
|
||||
\item the dominance claim behind every hype cycle is falsified by the four production cases
|
||||
\item no pattern is chosen because it is modern
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankred}{\textbf{No taste}}
|
||||
\begin{itemize}
|
||||
\item a claim that cannot be measured or falsified has no place in an architectural decision
|
||||
\item ``elegant'' is not an argument -- a response measure is
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
|
||||
\vspace{0.4cm}
|
||||
\begin{hinweisbox}
|
||||
Every judgement in this module must trace to a \textbf{measurable} property of a \textbf{documented} context.
|
||||
\end{hinweisbox}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% SECTION 4: THE FRAMEWORK
|
||||
% ============================================
|
||||
\section{The Framework at a Glance}
|
||||
|
||||
\begin{frame}{The framework: five elements}
|
||||
\begin{definitionbox}[Architecture--application fit]
|
||||
\footnotesize
|
||||
\begin{enumerate}
|
||||
\item \textbf{Requirements profile} $R(a) = \bigl(w_1, \dots, w_{12};\; S(a);\; K(a)\bigr)$ -- priority weights (High/Medium/Low), workload shape, hard constraints: the \emph{demand side}
|
||||
\item \textbf{Capability profile} $C(p) = \bigl(c_1, \dots, c_{12};\; S(p)\bigr)$ -- ordinal ratings $\{++, +, \circ, -, --\}$ plus native workload shape: the \emph{supply side}
|
||||
\item \textbf{Fit} $\mathrm{fit}(a,p)$ -- an ordinal, \emph{non-compensatory} match, computed by rules, not arithmetic
|
||||
\item \textbf{Architecture Decision Record (ADR)} -- the permanent, auditable record of decision $+$ rationale
|
||||
\item \textbf{Measurement contract} -- fitness functions and thresholds under which the decision is continuously tested
|
||||
\end{enumerate}
|
||||
\end{definitionbox}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\small Both profiles range over the \textbf{same twelve dimensions} -- introduced today, completed next week.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{The framework as a pipeline -- and the map of the script}
|
||||
\begin{center}
|
||||
\resizebox{0.94\textwidth}{!}{%
|
||||
\begin{tikzpicture}[
|
||||
node distance=0.9cm and 1.0cm,
|
||||
sysbox/.style={rectangle, draw, rounded corners=4pt, text width=3.2cm, minimum height=1.3cm, align=center, font=\small\sffamily, line width=0.8pt},
|
||||
core/.style={sysbox, fill=bankblue!20, draw=bankblue},
|
||||
comp/.style={sysbox, fill=bankgreen!15, draw=bankgreen},
|
||||
meas/.style={sysbox, fill=violet!15, draw=aiviolet},
|
||||
arr/.style={-{Stealth[length=2.5mm]}, thick, gray!60!black},
|
||||
farr/.style={-{Stealth[length=2.5mm]}, thick, dashed, bankred}
|
||||
]
|
||||
\node[core] (klass) {Application class\\ \scriptsize (Part III)};
|
||||
\node[core, right=0.9cm of klass] (profil) {Requirements profile $R(a)$\\ \scriptsize scenarios, utility tree};
|
||||
\node[core, right=0.9cm of profil] (match) {Matching $\mathrm{fit}(a,p)$\\ \scriptsize against $C(p)$ (Parts II, IV)};
|
||||
\node[comp, below=1.4cm of match] (adr) {Architecture decision\\ \scriptsize ADR with rationale};
|
||||
\node[meas, left=0.9cm of adr] (fitness) {Measurement contract\\ \scriptsize fitness functions in CI/CD};
|
||||
\node[meas, left=0.9cm of fitness] (ops) {Operation\\ \scriptsize DORA, SLOs, Lehman trends};
|
||||
\draw[arr] (klass) -- (profil);
|
||||
\draw[arr] (profil) -- (match);
|
||||
\draw[arr] (match) -- (adr);
|
||||
\draw[arr] (adr) -- (fitness);
|
||||
\draw[arr] (fitness) -- (ops);
|
||||
\draw[farr] (ops.north) -- node[midway, right=2pt, font=\scriptsize\sffamily, text=bankred, align=left] {profile drift (A5):\\ re-measure, evolve, supersede} (klass.south);
|
||||
\end{tikzpicture}%
|
||||
}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\small Demand is matched against supply; the match ends in a \textbf{recorded decision} with a \textbf{measurement contract} -- and operation continuously tests whether the decision's promises hold. The dashed edge is not decoration.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{The two AI axes of this module}
|
||||
\begin{ailinse}[Where AI enters -- twice]
|
||||
\begin{itemize}
|
||||
\item \textbf{Axis A -- AI as a tool in the development process:} assistants and agents generate code, tests, documentation -- changing \emph{how} we make and guard architectural decisions.
|
||||
\item \textbf{Axis B -- AI as a runtime component of the system:} an LLM, an ML model, an optimiser \emph{inside} the architecture -- bringing non-determinism, seconds-scale latency, per-call cost -- changing \emph{what} we must decide about.
|
||||
\end{itemize}
|
||||
\end{ailinse}
|
||||
|
||||
\vspace{0.3cm}
|
||||
\begin{itemize}
|
||||
\item Both axes are treated systematically in Part V of the script
|
||||
\item Until then, \textcolor{aiviolet}{\textbf{AI Lens}} boxes flag where each axis touches the classical material
|
||||
\item Your project lives on \textbf{both} axes: you build an AI-native system, using AI tools
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% SECTION 5: SIX ASSUMPTIONS
|
||||
% ============================================
|
||||
\section{Six Load-Bearing Assumptions}
|
||||
|
||||
\begin{frame}{Six load-bearing assumptions}
|
||||
The framework rests on six assumptions -- each anchored in established literature, each justifying \textbf{one element} of the framework.
|
||||
|
||||
\vspace{0.3cm}
|
||||
\begin{center}
|
||||
\small
|
||||
\begin{tabular}{@{}llp{5.4cm}@{}}
|
||||
\toprule
|
||||
& \textbf{Assumption (short)} & \textbf{Justifies} \\
|
||||
\midrule
|
||||
A1 & architecture $=$ hard-to-reverse decisions & the ADR (element 4) \\
|
||||
A2 & everything is a trade-off & the matching problem (element 3) \\
|
||||
A3 & quality attributes drive architecture & the twelve dimensions \\
|
||||
A4 & requirements $=$ measurable scenarios & the demand-side method (element 1) \\
|
||||
A5 & a decision is a tested hypothesis & the measurement contract (element 5) \\
|
||||
A6 & AI extends the space, not the method & D12 $+$ eval harness -- nothing else \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\textcolor{codegray}{\small The next three slides give each assumption its evidence.}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{A1 -- Decisions. \quad A2 -- Trade-offs.}
|
||||
\small
|
||||
\textbf{A1 -- Architecture is the set of significant, hard-to-reverse design decisions.}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item significance measured by \textbf{cost of change}; ``decisions you wish you could get right early''
|
||||
\item lost decision knowledge is a documented cause of erosion $\to$ every decision becomes an \textbf{ADR}
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.25cm}
|
||||
\textbf{A2 -- Everything in software architecture is a trade-off} \textcolor{codegray}{(First Law, Richards \& Ford)}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item \dots and if you think you have found something that is not, \emph{you have not yet identified the trade-off}
|
||||
\item the star ratings show it: microservices lead overall yet one star on cost and simplicity; layered is the exact mirror -- \textbf{dominance does not occur} $\to$ a matching problem exists
|
||||
\item corollary: a proposal claiming \emph{only benefits} is incomplete \emph{by assumption}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{A3 -- Quality attributes. \quad A4 -- Scenarios.}
|
||||
\small
|
||||
\textbf{A3 -- Quality attributes, not functionality, drive architecture.}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item functionality is largely \textbf{structure-neutral}; structure determines \emph{how well}: performance, availability, modifiability, security
|
||||
\item non-functional properties can rarely be refactored in afterwards
|
||||
\item $\to$ the coordinate system consists of quality attributes -- never feature lists
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.25cm}
|
||||
\textbf{A4 -- Requirements are architecturally usable only as measurable scenarios.}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item ``the system shall be scalable'' decides nothing and tests nothing
|
||||
\item decision-relevant only as a six-part scenario with a \textbf{response measure} -- number and unit
|
||||
\item empirically, such requirements are vague and implicit -- they must be \emph{elicited} (next week: QAW, utility tree)
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{A5 -- A tested hypothesis. \quad A6 -- AI absorbed.}
|
||||
\small
|
||||
\textbf{A5 -- An architecture decision is a hypothesis, continuously tested over the life cycle.}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item Lehman: change continually or decay; maintenance $\approx 40$--$80\,\%$ of life-cycle cost $\to$ design-time fit \textbf{decays}
|
||||
\item re-measure: fitness functions in CI/CD, the four DORA metrics; change \emph{within} an architecture is cheap -- change \emph{of} it stays steep (Segment, Prime Video)
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.3cm}
|
||||
\textbf{A6 -- AI components extend the quality attribute space but do not change the method.}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item non-deterministic, fallible, latency-heavy, priced per call, subject to drift -- yet ISO/IEC 25010:2023 already carries the vocabulary (Safety, Flexibility, Security/resistance)
|
||||
\item AI is \textbf{absorbed}: one new dimension (D12) $+$ one new test artefact (eval harness) -- \emph{the method stays}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Maxim 2}
|
||||
\begin{keypoint}
|
||||
\textbf{Maxim 2.} Because everything is a trade-off (A2) and quality drives structure (A3), architecture selection is \textbf{matching}; because decisions are costly to reverse (A1) and decay over time (A5), the match must be \textbf{documented} and \textbf{continuously measured}.
|
||||
\end{keypoint}
|
||||
|
||||
\vspace{0.4cm}
|
||||
\begin{center}
|
||||
\large
|
||||
demand $\;\to\;$ supply $\;\to\;$ match $\;\to\;$ record $\;\to\;$ test
|
||||
\end{center}
|
||||
|
||||
\vspace{0.3cm}
|
||||
\centering\small\textcolor{codegray}{This chain is the red line of the whole script -- every part instantiates one link at scale.}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% SECTION 6: FROM QUESTIONS TO DIMENSIONS
|
||||
% ============================================
|
||||
\section{From Questions to Dimensions}
|
||||
|
||||
\begin{frame}{Imagine you are on the on-call rota \dots}
|
||||
Forget frameworks for a moment. You are responsible -- personally -- for a system real people use. These questions \emph{will} find you:
|
||||
|
||||
\vspace{0.2cm}
|
||||
\small
|
||||
\begin{itemize}\setlength\itemsep{3pt}
|
||||
\item \emph{The grade-release portal: what happens at 08:00 on publication day, when the whole semester refreshes the same page at once?}
|
||||
\item \emph{An e-banking transfer: can the same payment ever be booked twice -- or disappear halfway?}
|
||||
\item \emph{One component crashes at noon: does the whole application go dark, or does one widget show a spinner while everything else keeps working?}
|
||||
\item \emph{The regulator calls: ``prove to us, step by step, what happened to this one transaction.'' How long does that take you?}
|
||||
\item \emph{A new feature request arrives: how many places in the code must change -- one module, or seventeen?}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{\dots and the questions keep coming}
|
||||
\small
|
||||
\begin{itemize}\setlength\itemsep{3pt}
|
||||
\item \emph{Two students must ship a working MVP in one semester: does the structure let them -- or does it demand a platform team they do not have?}
|
||||
\item \emph{The monthly cloud bill triples: which part of the structure is spending the money, and what was it doing at 03:00?}
|
||||
\item \emph{The team grows from three to thirty: do releases get faster -- or does everyone now wait for everyone else?}
|
||||
\item \emph{Product adds a feature whose core is an LLM call: it takes eight seconds, costs money on every single request, and is sometimes confidently wrong. Where does that live in the architecture?}
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{hinweisbox}
|
||||
Every one of these questions has ended budgets, products, or careers.
|
||||
\end{hinweisbox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Three observations turn the list into a method}
|
||||
\begin{enumerate}\setlength\itemsep{3pt}
|
||||
\item \textbf{The questions recur} -- across wildly different systems: the grade portal and Instagram share the first question, merely at different magnitudes.
|
||||
\item \textbf{None of them asks \emph{what} the system does} -- functionality is structure-neutral (A3); every question is about \emph{how well}, \emph{at what cost}, \emph{under which failure}.
|
||||
\item \textbf{Each can be answered with a number} -- requests per second, double bookings per million, per cent of functionality lost, hours to an audit trail, modules touched per feature, cost per request \dots
|
||||
\end{enumerate}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{keypoint}
|
||||
The twelve profile dimensions D1--D12 are exactly this: the recurring questions -- \textbf{grouped, named, and equipped with defined measures}. Nothing more mysterious than that.
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{The twelve dimensions: five groups (preview)}
|
||||
\small
|
||||
\begin{center}
|
||||
\begin{tabular}{@{}llp{6.6cm}@{}}
|
||||
\toprule
|
||||
\textbf{Group} & \textbf{Dimensions} & \textbf{The underlying question} \\
|
||||
\midrule
|
||||
Load and speed & D1, D2, D3 & does the structure survive its own success? \\
|
||||
Correctness and trust & D4, D5, D6 & can it be trusted -- with money, uptime, history? \\
|
||||
Change and delivery & D7, D8, D9 & what does the \emph{next} change cost? \\
|
||||
Economics and organisation & D10, D11 & what does it cost to run -- and can teams work in parallel? \\
|
||||
The new dimension & D12 & how cheaply can it host a slow, fallible, per-call-priced AI component? \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{itemize}
|
||||
\item Next week: all twelve, one by one -- each with its question, its vocabulary, and its \textbf{measurement instrument}
|
||||
\item Both profiles -- demand $R(a)$ and supply $C(p)$ -- will be vectors over \emph{these} twelve dimensions
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Discussion}
|
||||
\begin{thinkbox}
|
||||
Pick an app you use daily.
|
||||
\begin{itemize}
|
||||
\item Which \textbf{three dimensions} dominate it?
|
||||
\item On which dimension would its operator accept a \emph{bad} rating without losing sleep?
|
||||
\item Compare with your neighbour -- where you disagree, you have found a \textbf{weight} discussion. Next week's utility tree resolves exactly that.
|
||||
\end{itemize}
|
||||
\end{thinkbox}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% SUMMARY
|
||||
% ============================================
|
||||
\section{Summary}
|
||||
|
||||
\begin{frame}{Summary}
|
||||
\small
|
||||
\begin{enumerate}\setlength\itemsep{2pt}
|
||||
\item Four production systems: structures differ radically, none dominates -- failures were \textbf{mismatches}
|
||||
\item \textbf{Maxim 1:} patterns are neither good nor bad; only the \emph{fit} is
|
||||
\item Architecture $=$ the \textbf{hard-to-reverse structural decisions} that determine quality behaviour
|
||||
\item The framework: $R(a)$ (demand) $\to$ $C(p)$ (supply) $\to$ $\mathrm{fit}(a,p)$ $\to$ \textbf{ADR} $\to$ \textbf{measurement contract}
|
||||
\item AI enters twice: \textbf{Axis A} (tool in the process), \textbf{Axis B} (component in the system)
|
||||
\item Six assumptions A1--A6 carry the framework; the twelve dimensions are \textbf{recurring engineering questions} -- grouped, named, measurable
|
||||
\item \textbf{Maxim 2:} match, then document, then measure
|
||||
\end{enumerate}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Next week}
|
||||
\begin{columns}[T]
|
||||
\begin{column}{0.55\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Lecture 2 -- the twelve dimensions, completed}}
|
||||
\begin{itemize}
|
||||
\item D1--D12 one by one: question, vocabulary, instrument
|
||||
\item why exactly these twelve (ISO/IEC 25010:2023)
|
||||
\item six-part quality attribute scenarios
|
||||
\item ASR, Quality Attribute Workshop
|
||||
\item the utility tree: from scenarios to \textbf{weights}
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\begin{column}{0.42\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Reading}}
|
||||
\begin{itemize}
|
||||
\item this week: script Part I, Sections 1--2
|
||||
\item ahead: Part I, Section 3
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.3cm}
|
||||
\textcolor{bankblue}{\textbf{Exercise}}
|
||||
\begin{itemize}
|
||||
\item kickoff: teams, repo, domain, ontology sketch, raw stakeholder wishes
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% END
|
||||
% ============================================
|
||||
\FHGRClosingPage[][{\color{white}\parbox{0.9\paperwidth}{\centering Thank you!\\[3ex]
|
||||
{\normalsize\mdseries Dr.\ Florian Herzog\\[0.9ex]
|
||||
Fachhochschule Graub\"unden, Chur\\[2.4ex]
|
||||
{\small AISE502 -- AI in Software Engineering II}}}}]
|
||||
|
||||
\end{document}
|
||||
BIN
Folien/AISE502_Vorlesung_2_Folien.pdf
Normal file
856
Folien/AISE502_Vorlesung_2_Folien.tex
Normal file
@ -0,0 +1,856 @@
|
||||
% !TEX encoding = UTF-8 Unicode
|
||||
% ============================================================================
|
||||
% AISE502 -- AI in Software Engineering II
|
||||
% Lecture 2 slides, typeset with the official FHGR beamer theme
|
||||
% (beamerthemeFHGR.sty, University of Applied Sciences of the Grisons).
|
||||
% Slide content is unchanged; only the presentation layer is the FHGR template.
|
||||
% ============================================================================
|
||||
\documentclass[aspectratio=169]{beamer}
|
||||
|
||||
\usetheme[showsection, titlebg=pics/theme_pics/titlepage.png]{FHGR}
|
||||
|
||||
% ============================================
|
||||
% PACKAGES
|
||||
% The theme already loads tikz, graphicx, xcolor, tabularx, colortbl,
|
||||
% listings, hyperref, environ and xparse -- only the extras are needed here.
|
||||
% ============================================
|
||||
\usepackage[british]{babel}
|
||||
\usepackage{booktabs}
|
||||
\usepackage{amsmath}
|
||||
\usepackage{amssymb}
|
||||
\usepackage{tcolorbox}
|
||||
\usetikzlibrary{shapes.geometric, arrows.meta, positioning, fit, backgrounds, calc}
|
||||
|
||||
% ============================================
|
||||
% SEMANTIC COLOURS, MAPPED ONTO THE FHGR PALETTE
|
||||
% The names used throughout the slides are kept, so no slide text changes;
|
||||
% they now resolve to the FHGR brand colours defined by the theme.
|
||||
% ============================================
|
||||
\colorlet{bankblue}{blue} % FHGR blue (4B92A4)
|
||||
\colorlet{bankgreen}{green} % FHGR green (817E65)
|
||||
\colorlet{bankred}{red} % FHGR red (C60219)
|
||||
\colorlet{codegray}{gray} % FHGR gray (595959)
|
||||
\colorlet{backcolour}{linen} % FHGR linen (E1D3B5)
|
||||
\definecolor{aiviolet}{HTML}{6B4E71} % muted plum, kept distinct for the AI lens
|
||||
|
||||
% Attribution labels in English (theme default is German)
|
||||
\renewcommand{\source}[1]{\par\hfill {\tiny\color{FHGRDeco} Source:\,\itshape #1}}
|
||||
\renewcommand{\imagesource}[1]{\par\hfill {\tiny\color{FHGRDeco} Image source:\,\itshape #1}}
|
||||
|
||||
% ============================================
|
||||
% CUSTOM TCOLORBOXES (same semantics as the script, FHGR colours)
|
||||
% ============================================
|
||||
\newtcolorbox{keypoint}{
|
||||
colback=bankblue!7!white,
|
||||
colframe=bankblue,
|
||||
title=Key Concept,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{examplebox}[1][]{
|
||||
colback=bankgreen!10!white,
|
||||
colframe=bankgreen,
|
||||
title={Example: #1},
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{definitionbox}[1][]{
|
||||
colback=linen!40!white,
|
||||
colframe=camel!85!black,
|
||||
title={Definition: #1},
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{thinkbox}{
|
||||
colback=lightGray!35!white,
|
||||
colframe=darkGray,
|
||||
title=Discussion,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{hinweisbox}{
|
||||
colback=bankred!5!white,
|
||||
colframe=bankred,
|
||||
title=Important Note,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{ailinse}[1][]{
|
||||
colback=aiviolet!7!white,
|
||||
colframe=aiviolet,
|
||||
title={AI Lens: #1},
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{projektbox}{
|
||||
colback=bankblue!4!white,
|
||||
colframe=bankblue!70!black,
|
||||
title=Project Link: Portfolio Intelligence Platform,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
% Measurement line used on every dimension slide
|
||||
\newcommand{\measured}[2]{%
|
||||
\vspace{0.12cm}
|
||||
\begin{tcolorbox}[colback=gray!8!white, colframe=gray!70!black, boxrule=0.6pt, arc=2pt, top=1pt, bottom=1pt, left=4pt, right=4pt]
|
||||
\footnotesize \textbf{Measured:} #1\\ \textbf{Instrument:} #2
|
||||
\end{tcolorbox}}
|
||||
|
||||
% ============================================
|
||||
% TITLE METADATA
|
||||
% ============================================
|
||||
\title[AI in Software Engineering II]{AISE502: AI in Software Engineering II}
|
||||
\subtitle{Lecture 2: The Twelve Dimensions -- and How Requirements Become Measurable\\[0.4ex]{\small Script: Part I, Sections 2--3}}
|
||||
\author{Dr.\ Florian Herzog}
|
||||
\shortname{AISE502}
|
||||
\fullname{Fachhochschule Graub\"unden, Chur -- Autumn Semester 2026}
|
||||
|
||||
\begin{document}
|
||||
|
||||
% ============================================
|
||||
% TITLE SLIDE
|
||||
% ============================================
|
||||
\FHGRTitlePage
|
||||
|
||||
% ============================================
|
||||
% AGENDA
|
||||
% ============================================
|
||||
\begin{frame}{Agenda}
|
||||
\small
|
||||
\begin{enumerate}\setlength\itemsep{1pt}
|
||||
\item Recap: the framework and the nine questions
|
||||
\item Load and speed: D1--D3
|
||||
\item Correctness and trust: D4--D6
|
||||
\item Change and delivery: D7--D9
|
||||
\item Economics and organisation: D10--D11
|
||||
\item The new dimension: D12 (AI integrability)
|
||||
\item Why exactly these twelve -- ISO/IEC 25010:2023
|
||||
\item From wishes to scenarios: ASR, QAW, the six-part form
|
||||
\item The utility tree: from scenarios to weights
|
||||
\item Workload shape, hard constraints -- $R(a)$ assembled
|
||||
\end{enumerate}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% RECAP
|
||||
% ============================================
|
||||
\section{Recap}
|
||||
|
||||
\begin{frame}{Recap: where we are}
|
||||
\footnotesize
|
||||
\textbf{Last week:}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item Maxim 1: patterns are neither good nor bad -- only the \textbf{fit} is
|
||||
\item the framework: $R(a) \to C(p) \to \mathrm{fit}(a,p) \to$ ADR $\to$ measurement contract
|
||||
\item six assumptions A1--A6; the chain \emph{demand $\to$ supply $\to$ match $\to$ record $\to$ test}
|
||||
\item nine recurring on-call questions $\to$ five groups of dimensions
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\textbf{Today} we build the coordinate system and the demand side:
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item the twelve dimensions \textbf{D1--D12}, one by one -- each with vocabulary and \textbf{instrument}
|
||||
\item then the method that turns stakeholder wishes into \textbf{weights}: scenarios, QAW, utility tree
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{keypoint}
|
||||
Rule of the day (A4, applied to the theory itself): \textbf{no instrument, no dimension.}
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% D1-D3 LOAD AND SPEED
|
||||
% ============================================
|
||||
\section{Load and Speed: D1--D3}
|
||||
|
||||
\begin{frame}{D1 -- Read scalability \hfill \normalsize\textcolor{gray}{group: load and speed}}
|
||||
\emph{\textcolor{bankblue}{What happens at 08:00 on grade-release day, when the whole semester refreshes at once?}}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item the ability to serve a growing volume of \textbf{read} requests -- requests that look at data without changing it
|
||||
\item most interactive systems are \textbf{read-dominated by orders of magnitude}: thousands check a result for every one who appeals it
|
||||
\item reads are friendly: they can be served from \textbf{copies} -- replicas and \emph{caches} (fast stores holding ready-made answers)
|
||||
\item Stack Overflow: $\sim 1.3$ billion page views/month from a handful of servers; Instagram: a monolith -- \textbf{the single write path is the hard part}
|
||||
\end{itemize}
|
||||
|
||||
\measured{throughput at $k\times$ replication (does doubling servers double throughput?); cache hit ratio; p95 read latency}{step-profile load tests; production RED metrics (Rate, Errors, Duration)}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{D2 -- Write scalability and elasticity}
|
||||
\emph{\textcolor{bankblue}{Black Friday: checkout traffic jumps to dozens of times the baseline for one weekend -- and is gone on Monday.}}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item the D1 question for requests that \textbf{change} state -- the harder half: a write cannot be served from a copy; every order must reach the \emph{one authoritative record}, durably and in order
|
||||
\item \textbf{elasticity} adds the time axis: how quickly capacity follows load -- up \emph{and back down}
|
||||
\item reference point: Shopify's BFCM weekend, peaks $\sim 280$ million requests/minute, carried by replicated ``pods'' of a monolith
|
||||
\item the opposite end: \textbf{scale-to-zero} -- costing nothing while unused (the serverless promise)
|
||||
\end{itemize}
|
||||
|
||||
\measured{sustained ingest rate (durably absorbed writes/s); time-to-capacity after a load step; cost of idling at zero}{load tests with load steps; elasticity-lag measurement}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{D3 -- Latency and predictability}
|
||||
\emph{\textcolor{bankblue}{How long does one click take -- and how long does it take on a bad day?}}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item \textbf{latency}: time between request and response; \textbf{predictability}: the distribution matters, not the average
|
||||
\item \textbf{averages lie}: a system can average $120$\,ms while every twentieth request takes four seconds -- and the most active users hit those most often
|
||||
\item vocabulary: \textbf{p50/p95/p99} percentiles; \textbf{tail-latency ratio} p99/p50; \textbf{cold start} $=$ extra delay when the serving component must first wake up
|
||||
\item stakes: Amazon $\sim 1\,\%$ of sales lost per additional $100$\,ms; Akamai: up to $7\,\%$ of conversions
|
||||
\end{itemize}
|
||||
|
||||
\measured{p50/p95/p99 response times; cold-start frequency; tail-latency ratio}{distributed tracing (OpenTelemetry) -- following one request across every component; latency budgets as CI gates}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% D4-D6 CORRECTNESS AND TRUST
|
||||
% ============================================
|
||||
\section{Correctness and Trust: D4--D6}
|
||||
|
||||
\begin{frame}{D4 -- Consistency and transactional integrity}
|
||||
\emph{\textcolor{bankblue}{An e-banking transfer: can the same payment ever be booked twice -- or vanish halfway?}}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item can concurrency and partial failure \textbf{corrupt the data} -- can the numbers silently stop being true?
|
||||
\item classic failure, the \textbf{lost update}: two processes read the same balance, both write -- the second silently overwrites the first
|
||||
\item vocabulary: \textbf{invariant} (must always hold: debit $=$ credit); \textbf{transactional integrity} (all or nothing); \textbf{staleness} (seconds a copy may lag)
|
||||
\item a single database hands you transactions \emph{for free}; every distribution boundary takes part of that away
|
||||
\end{itemize}
|
||||
|
||||
\measured{anomaly rate under concurrent load; invariant-violation count (\textbf{target 0} for ledgers); staleness bound}{Jepsen-style tests (concurrent ops $+$ injected failures); reconciliation jobs}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{D5 -- Availability and fault isolation}
|
||||
\emph{\textcolor{bankblue}{One component crashes at noon: does the whole app go dark, or does one widget show a spinner?}}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item availability: share of time the system does its job; fault isolation: \textbf{how much of the product dies when one part dies}
|
||||
\item \textbf{blast radius}: \% of functionality lost per component failure -- in a single process it is $100\,\%$ \emph{by construction}; \textbf{MTTR}: mean time to recovery
|
||||
\item operations vocabulary: \textbf{SLO} (``$99.9\,\%$ of requests succeed this month''), \textbf{error budget} (the tolerated $0.1\,\%$), \textbf{burn rate}
|
||||
\item run continuously in the pipeline, such an automated check of an architectural property is a \textbf{fitness function} -- a term we will use constantly
|
||||
\end{itemize}
|
||||
|
||||
\measured{SLO attainment; error-budget burn; blast radius; MTTR}{chaos experiments -- deliberately kill components under load and measure what users lose}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{D6 -- Security and auditability}
|
||||
\emph{\textcolor{bankblue}{The regulator asks: prove what happened to this one transaction, end to end.}}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item keeping attackers out is necessary \emph{everywhere}; what discriminates between \textbf{structures} is \textbf{auditability} -- the ability to reconstruct history
|
||||
\item \textbf{audit trail}: complete, tamper-evident record of who changed what, when, on whose authority -- a \emph{legal duty} in supervised industries (FINMA, PCI DSS)
|
||||
\item \textbf{audit scope}: the portion of the system auditors must examine -- confining sensitive flows to a small region shrinks the scope, and the bill
|
||||
\item some structures record every change as an event \emph{as their normal mode}; others reassemble history from scattered log files
|
||||
\end{itemize}
|
||||
|
||||
\measured{time to reconstruct a complete audit trail for one transaction; \% of state changes journaled (append-only)}{audit drills -- run like fire drills; immutable logs; PCI/FINMA scope reviews}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% D7-D9 CHANGE AND DELIVERY
|
||||
% ============================================
|
||||
\section{Change and Delivery: D7--D9}
|
||||
|
||||
\begin{frame}{D7 -- Evolvability and maintainability}
|
||||
\emph{\textcolor{bankblue}{A feature request arrives: how many places in the code must change?}}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item prices the \textbf{next} change -- which, over a lifetime dominated by evolution (A5), dominates most others
|
||||
\item central measure, worth memorising: \textbf{change dispersion} $=$ modules touched by an average feature -- \emph{one is excellent, seventeen is an architecture problem}
|
||||
\item underlying variable: \textbf{coupling} -- metrics: CBO (coupling between objects), Martin's \emph{instability}
|
||||
\item \textbf{declared-boundary violations} (code bypassing declared module boundaries): target 0, enforceable in CI with ArchUnit / Spring Modulith
|
||||
\end{itemize}
|
||||
|
||||
\measured{change dispersion over the version history; coupling metrics (CBO, instability); boundary violations (target 0)}{ArchUnit / Spring Modulith verification as CI gates; CK metric suite}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{D8 -- Simplicity and time-to-market}
|
||||
\emph{\textcolor{bankblue}{Two students must ship a working MVP in one semester. Does the structure let them?}}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item how much machinery must \emph{exist, be understood, and be kept alive} before the first unit of value reaches a user
|
||||
\item a structure that requires a container orchestrator, a message broker, and a dozen repositories before ``hello, world'' has \textbf{failed this dimension for that team} -- however well it would carry Shopify's Black Friday
|
||||
\item this is where A2 bites hardest: the structures that win D8 tend to concede D2 or D11 -- a small team's rational choice \emph{differs} from a platform company's
|
||||
\end{itemize}
|
||||
|
||||
\measured{time from empty repository to first production release; onboarding time to first merged contribution; count of distinct runtime technologies}{delivery calendar; team surveys; tech-radar count}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{D9 -- Testability and deployability}
|
||||
\emph{\textcolor{bankblue}{Can a developer know within seconds that a change is safe -- and release it this afternoon without coordinating with three teams?}}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item two abilities, \textbf{deliberately fused}: fast, trustworthy verification \emph{and} independent, low-risk release
|
||||
\item vocabulary: \textbf{hermetic test} (fully self-contained -- no shared staging, no live external service); \textbf{deployment frequency}; \textbf{change failure rate} (share of releases that break something)
|
||||
\item why fused: DORA 2017 found precisely this pair -- test without an integrated environment, deploy independently -- predicted delivery performance \emph{more strongly than automation itself}; both are surface expressions of \textbf{coupling}
|
||||
\end{itemize}
|
||||
|
||||
\measured{test feedback time; \% hermetic tests; deployment frequency; change failure rate}{pipeline telemetry; DORA capability items}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% D10-D11 ECONOMICS AND ORGANISATION
|
||||
% ============================================
|
||||
\section{Economics and Organisation: D10--D11}
|
||||
|
||||
\begin{frame}{D10 -- Operating cost efficiency}
|
||||
\emph{\textcolor{bankblue}{The cloud bill tripled. Which part of the structure spends the money -- and what was it doing at 03:00?}}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item prices the running system -- \textbf{machines and people}
|
||||
\item vocabulary: \textbf{cost per request}; \textbf{idle cost} (capacity doing nothing -- the 03:00 question); \textbf{TCO}; \textbf{FTE}
|
||||
\item the hidden term matters most: a self-managed container platform is dominated not by compute prices but by \textbf{platform-team FTEs} -- the ``microservice premium'' materialises as staffing
|
||||
\item Prime Video's $> 90\,\%$ cost cut: the same dimension, seen from the infrastructure side
|
||||
\end{itemize}
|
||||
|
||||
\measured{TCO split build/platform/run; cost per request; idle cost; platform-team FTEs}{FinOps reporting -- making cloud spend visible and attributable per team and feature}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{D11 -- Team scaling (Conway fit)}
|
||||
\emph{\textcolor{bankblue}{The team grows from three to thirty. Do releases speed up -- or does everyone wait on everyone?}}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item \textbf{Conway's law}, in one sentence: a system's structure ends up mirroring the communication structure of the organisation that builds it
|
||||
\item consequence: \emph{every architecture decision is a team-structure decision} -- whether the architect intends it or not
|
||||
\item operational core: how many teams can design, build, and \textbf{release without waiting for each other}?
|
||||
\item DORA: \emph{deployments per developer per day} \textbf{rises} with team count in loosely coupled organisations -- and \textbf{falls} in tightly coupled ones
|
||||
\end{itemize}
|
||||
|
||||
\measured{deployments per developer per day as the team count grows; number of teams releasing without cross-team coordination}{DORA scaling analysis; Team Topologies review}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% D12 THE NEW DIMENSION
|
||||
% ============================================
|
||||
\section{The New Dimension: D12}
|
||||
|
||||
\begin{frame}{D12 -- AI integrability}
|
||||
\emph{\textcolor{bankblue}{The new feature's core is an LLM call: eight seconds, paid per request, sometimes confidently wrong. How hard does the structure fight it?}}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\footnotesize
|
||||
How cheaply can the structure host a component that is \textbf{slow, fallible, priced per call}? It needs three things:
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item a \textbf{queue}: a waiting line, so an eight-second call -- or a provider outage -- does not block everything behind it
|
||||
\item a \textbf{port}: a narrow, contract-shaped interface isolating the non-determinism, so deterministic tests can substitute a \emph{fake}
|
||||
\item a \textbf{measurement point}: cost and quality of \emph{every single call} observable -- providers price per \textbf{token}, so cost accrues \emph{per request}
|
||||
\end{itemize}
|
||||
|
||||
\measured{seconds-scale latency tolerance; isolability of non-determinism behind contracts; token-cost observability per request}{\textbf{eval harness}: versioned test inputs with expected qualities; pass rate $\geq$ threshold as a CI gate -- the AI counterpart of a regression suite}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{One system, one profile}
|
||||
\begin{examplebox}[a retail e-banking application, walked through the five groups]
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item \textbf{Load and speed:} payday-morning peaks; reads $\gg$ writes; two seconds tolerated, not ten $\to$ D1, D3 matter; D2 modest
|
||||
\item \textbf{Correctness and trust:} a double-booked transfer is existential; the audit trail is a legal duty $\to$ D4, D6 \emph{as high as they go}; D5 high
|
||||
\item \textbf{Change and delivery:} monthly, formally reviewed releases -- but decades of regulatory change $\to$ D7 high, D9 moderate
|
||||
\item \textbf{Economics and organisation:} platform organisation exists anyway; dozens of teams $\to$ D10 medium, D11 high
|
||||
\item \textbf{AI:} a chat assistant is attractive -- but a confidently wrong answer about a balance is a \emph{safety} problem $\to$ D12 medium, hard guardrails
|
||||
\end{itemize}
|
||||
\end{examplebox}
|
||||
|
||||
\vspace{0.05cm}
|
||||
\footnotesize The judgements are debatable; the point is not: \textbf{a real system has a \emph{profile}} -- demanding on a few dimensions, relaxed on others. Writing it down rigorously is the second half of today.
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% WHY EXACTLY THESE TWELVE
|
||||
% ============================================
|
||||
\section{Why Exactly These Twelve}
|
||||
|
||||
\begin{frame}{Quality attributes, not functions}
|
||||
\footnotesize
|
||||
\begin{columns}[T]
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Functional requirement}}
|
||||
\begin{itemize}
|
||||
\item \emph{what} the system shall do
|
||||
\item compute interest, post a booking, render a feed
|
||||
\item largely \textbf{structure-neutral} (A3)
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Quality attribute requirement}}
|
||||
\begin{itemize}
|
||||
\item \emph{how well}, under which conditions, at what cost
|
||||
\item the misleading classic term: ``non-functional''
|
||||
\item this is what \textbf{structure determines}
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
|
||||
\vspace{0.3cm}
|
||||
\begin{examplebox}[the same function, three structures]
|
||||
``Post a booking'' can run inside a layered monolith, as a \emph{saga} across microservices, or as an event-sourced log. The \textbf{function is identical} -- the consistency guarantee, the latency distribution, the audit trail, and the cost of the next change are \textbf{radically different}.
|
||||
\end{examplebox}
|
||||
|
||||
\vspace{0.15cm}
|
||||
All twelve dimensions are quality attributes or workload/constraint characteristics -- \textbf{never features}.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{The names: ISO/IEC 25010:2023}
|
||||
\footnotesize
|
||||
The naming standard for quality attributes -- nine characteristics, each with sub-characteristics:
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{center}
|
||||
\footnotesize
|
||||
functional suitability $\cdot$ performance efficiency $\cdot$ compatibility $\cdot$ interaction capability $\cdot$ reliability $\cdot$ \textbf{security} $\cdot$ maintainability $\cdot$ \textbf{flexibility} $\cdot$ \textbf{safety}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.15cm}
|
||||
Three 2023 changes matter directly for this module:
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item \textbf{Safety} became a new top-level characteristic (fail safe, hazard warning) -- exactly what a confidently-wrong AI component requires
|
||||
\item \emph{portability} became \textbf{Flexibility}, with an explicit new \emph{scalability} sub-characteristic
|
||||
\item \textbf{Security} gained \emph{resistance} -- sustaining operation under attack: the normative hook for prompt-injection robustness
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{keypoint}
|
||||
The 2023 vocabulary covers AI-bearing systems \textbf{without private extensions} -- A6 starts with the quality model itself.
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Three admission conditions}
|
||||
\small
|
||||
A candidate became one of the twelve only if it passed all three:
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{enumerate}\setlength\itemsep{2pt}
|
||||
\item \textbf{Standard anchoring} -- maps to ISO/IEC 25010:2023 vocabulary (reaching beyond it -- cost, organisation -- is stated explicitly)
|
||||
\item \textbf{Discrimination} -- must distinguish at least two of the seven patterns; a dimension on which all patterns score alike carries no matching information
|
||||
\item \textbf{Instrumentation} -- must have a defined \textbf{response measure and measurement instrument}: every rating is a testable prediction, not an adjective
|
||||
\end{enumerate}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{hinweisbox}
|
||||
\footnotesize \textbf{No instrument, no dimension} -- this excludes ``elegance'' and ``future-proofness''. And ISO 25010 is a \emph{taxonomy}, not a \emph{metric}: do not argue about the box a concern belongs to -- write it as a \textbf{scenario with a response measure} and the question dissolves.
|
||||
\end{hinweisbox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{The reference card (1/2): D1--D6}
|
||||
\begin{center}
|
||||
\scriptsize
|
||||
\begin{tabular}{@{}p{0.6cm}p{2.9cm}p{4.6cm}p{4.4cm}@{}}
|
||||
\toprule
|
||||
\textbf{\#} & \textbf{Dimension} & \textbf{Response measure (examples)} & \textbf{Instrument} \\
|
||||
\midrule
|
||||
D1 & Read scalability & throughput at $k\times$ replication; cache hit ratio & load tests; RED metrics \\
|
||||
D2 & Write scalability \& elasticity & sustained ingest rate; time-to-capacity; scale-to-zero cost & load steps; elasticity lag \\
|
||||
D3 & Latency \& predictability & p50/p95/p99; cold starts; tail ratio p99/p50 & distributed tracing; latency budgets in CI \\
|
||||
D4 & Consistency \& integrity & anomaly rate; invariant violations ($0$ for ledgers); staleness bound & Jepsen-style tests; reconciliation jobs \\
|
||||
D5 & Availability \& fault isolation & SLO attainment; error-budget burn; blast radius; MTTR & SLOs; chaos experiments \\
|
||||
D6 & Security \& auditability & time to reconstruct an audit trail; \% changes journaled & audit drills; immutable logs; scope reviews \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\footnotesize\textcolor{codegray}{Full version with ISO anchors: the script's canonical reference card (Table 3).}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{The reference card (2/2): D7--D12}
|
||||
\begin{center}
|
||||
\scriptsize
|
||||
\begin{tabular}{@{}p{0.6cm}p{2.9cm}p{4.6cm}p{4.4cm}@{}}
|
||||
\toprule
|
||||
\textbf{\#} & \textbf{Dimension} & \textbf{Response measure (examples)} & \textbf{Instrument} \\
|
||||
\midrule
|
||||
D7 & Evolvability \& maintainability & change dispersion; coupling (CBO, instability); boundary violations ($0$) & ArchUnit / Spring Modulith in CI \\
|
||||
D8 & Simplicity \& time-to-market & empty repo $\to$ first release; onboarding time; technology count & delivery calendar; surveys \\
|
||||
D9 & Testability \& deployability & test feedback time; \% hermetic tests; deployment frequency; change failure rate & pipeline telemetry; DORA items \\
|
||||
D10 & Operating cost efficiency & TCO build/platform/run; cost per request; idle cost; platform FTEs & FinOps reporting \\
|
||||
D11 & Team scaling (Conway) & deployments per developer per day; teams releasing without coordination & DORA scaling; Team Topologies \\
|
||||
D12 & AI integrability & seconds-scale latency tolerance; isolable non-determinism; token-cost observability & eval-harness pass rate in CI; cost budgets \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% DEMAND SIDE: ASR, QAW, SCENARIOS
|
||||
% ============================================
|
||||
\section{From Wishes to Scenarios}
|
||||
|
||||
\begin{frame}{The demand side: what we are building}
|
||||
\begin{center}
|
||||
\Large
|
||||
$R(a) \;=\; \bigl(\underbrace{w_1, \dots, w_{12}}_{\text{priority weights}};\;\; \underbrace{S(a)}_{\text{workload shape}};\;\; \underbrace{K(a)}_{\text{hard constraints}}\bigr)$
|
||||
\end{center}
|
||||
|
||||
\vspace{0.4cm}
|
||||
None of these is written down by intuition -- each is \textbf{produced} by a defined method:
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{center}
|
||||
\small
|
||||
\begin{tabular}{@{}lll@{}}
|
||||
\toprule
|
||||
\textbf{Step} & \textbf{Method} & \textbf{Produces} \\
|
||||
\midrule
|
||||
1 & elicitation (QAW) & a prioritised pool of candidate \textbf{ASRs} \\
|
||||
2 & six-part scenarios & the candidates in \textbf{falsifiable form} \\
|
||||
3 & utility tree & the twelve \textbf{weights} $w_1, \dots, w_{12}$ \\
|
||||
4 & inventory & workload shape $S(a)$, constraints $K(a)$ \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Architecturally significant requirements (ASR)}
|
||||
\begin{definitionbox}[Architecturally significant requirement]
|
||||
A requirement with a \textbf{profound effect on the architecture} -- one whose late accommodation would be disproportionately expensive -- and typically \textbf{difficult to achieve}.
|
||||
\end{definitionbox}
|
||||
|
||||
\vspace{0.3cm}
|
||||
\small
|
||||
Empirical finding (Chen et al.\ 2013; 90 practitioners, $> 500$ organisations):
|
||||
\begin{itemize}
|
||||
\item ASRs are typically \textbf{poorly specified, vague, and implicit}
|
||||
\item they hide inside business goals: \emph{``we plan to enter three new markets next year''} $\;\to\;$ a scalability ASR \emph{and} a compliance ASR
|
||||
\item they cannot be read off a requirements document -- they must be \textbf{elicited}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Eliciting ASRs: the Quality Attribute Workshop (QAW)}
|
||||
\small
|
||||
The SEI's established format -- its essence is two design choices:
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{columns}[T]
|
||||
\begin{column}{0.44\textwidth}
|
||||
\textcolor{bankblue}{\textbf{1. Who is in the room}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item \emph{not} the development team alone
|
||||
\item the stakeholders whose concerns the architecture must balance:
|
||||
\item users, operators, auditors, regulators, product owners
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\begin{column}{0.52\textwidth}
|
||||
\textcolor{bankblue}{\textbf{2. The sequence}}
|
||||
\begin{enumerate}\setlength\itemsep{1pt}
|
||||
\item business and mission drivers first
|
||||
\item identify architectural drivers
|
||||
\item scenario \textbf{brainstorming}
|
||||
\item consolidation
|
||||
\item \textbf{prioritisation by stakeholder vote}
|
||||
\item refinement of the top candidates into the measurable six-part form
|
||||
\end{enumerate}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
|
||||
\vspace{0.3cm}
|
||||
\emph{Produced:} the raw material of $R(a)$ -- prioritised candidate ASRs, \textbf{not yet measurable}.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{The measurable form: the six-part scenario}
|
||||
\begin{definitionbox}[Quality attribute scenario]
|
||||
\footnotesize
|
||||
\begin{enumerate}\setlength\itemsep{0pt}
|
||||
\item \textbf{Source of stimulus} -- who or what triggers it: a user, another system, an attacker
|
||||
\item \textbf{Stimulus} -- the arriving event: a request, a failure, a load spike
|
||||
\item \textbf{Environment} -- the operating condition: normal, overload, degraded
|
||||
\item \textbf{Artifact} -- the part of the system stimulated
|
||||
\item \textbf{Response} -- the desired observable reaction
|
||||
\item \textbf{Response measure} -- the quantity, \textbf{with number and unit}, by which success is judged
|
||||
\end{enumerate}
|
||||
\end{definitionbox}
|
||||
|
||||
\vspace{0.05cm}
|
||||
\begin{hinweisbox}
|
||||
\small The \textbf{response measure} is the non-negotiable part: ``the system shall be scalable'' names an \emph{aspiration}; a scenario with a response measure names a \emph{test}.
|
||||
\end{hinweisbox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Worked scenario 1: availability in a payment service}
|
||||
\begin{examplebox}[banking]
|
||||
\footnotesize
|
||||
\emph{Source:} a heartbeat monitor. \emph{Stimulus:} reports the failure of one application server. \emph{Environment:} normal operation, mid-day load. \emph{Artifact:} the payment service. \emph{Response:} requests are redirected to replicas; operations staff notified; in-flight transactions complete or roll back atomically. \emph{\textbf{Response measure:}} failover $< 30$\,s; \textbf{zero} transactions lost or double-posted.
|
||||
\end{examplebox}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\footnotesize
|
||||
``The payment service shall be highly available'' hides \textbf{three architectural decisions} the scenario exposes:
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item replicas (redundancy tactic) \quad $\cdot$ \quad failure detection (heartbeat tactic)
|
||||
\item transactional atomicity \emph{across} the failover -- a guarantee some patterns provide structurally, others do not
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.1cm}
|
||||
The response measure is \textbf{directly executable} as a chaos experiment: kill an instance under load, measure.\\
|
||||
\textbf{One artefact, three roles:} requirement, design driver, test specification.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Worked scenario 2: safety in an AI advisory platform}
|
||||
\begin{examplebox}[Axis B]
|
||||
\footnotesize
|
||||
\emph{Source:} a customer. \emph{Stimulus:} submits a request for which the LLM generates a \textbf{factually wrong} recommendation. \emph{Environment:} normal operation. \emph{Artifact:} the advisory platform. \emph{Response:} the deterministic validation layer detects and blocks the answer and escalates to a human advisor. \emph{\textbf{Response measure:}} detection rate $\geq 99\,\%$ on the \emph{versioned evaluation set}, $< 2$\,s added latency.
|
||||
\end{examplebox}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\footnotesize Two things are notable:
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item the six-part form needed \textbf{no extension} for a non-deterministic component -- \textbf{A6 at work}: the stimulus is probabilistic (the model \emph{will} sometimes hallucinate), and the requirement is placed \textbf{on the system around the model}, not on the model
|
||||
\item the response measure \emph{presupposes an artefact}: a versioned evaluation set -- the \textbf{eval harness} (D12)
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\textcolor{codegray}{In ISO/IEC 25010:2023 terms: a \emph{Safety} scenario (fail safe, hazard warning).}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% UTILITY TREE
|
||||
% ============================================
|
||||
\section{The Utility Tree}
|
||||
|
||||
\begin{frame}{The utility tree: prioritising scenarios}
|
||||
\small A workshop produces more scenarios than any analysis can carry. The \textbf{utility tree} (ATAM) prioritises them top-down; every leaf is rated H/M/L on \textbf{business importance} (what does failure cost us?) and \textbf{achievement difficulty} (how hard, architecturally?).
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{center}
|
||||
\resizebox{0.72\textwidth}{!}{%
|
||||
\begin{tikzpicture}[
|
||||
sysbox/.style={rectangle, draw, rounded corners=4pt, align=center, font=\scriptsize\sffamily, line width=0.8pt, inner sep=4pt},
|
||||
root/.style={sysbox, fill=bankblue!20, draw=bankblue, font=\small\sffamily\bfseries, minimum height=1.1cm, minimum width=1.9cm},
|
||||
attr/.style={sysbox, fill=bankgreen!15, draw=bankgreen, minimum width=2.6cm, minimum height=0.85cm},
|
||||
leafhh/.style={sysbox, fill=bankred!15, draw=bankred, text width=6.6cm},
|
||||
leaf/.style={sysbox, fill=gray!12, draw=gray!60!black, text width=6.6cm},
|
||||
arr/.style={-{Stealth[length=2.2mm]}, thick, gray!60!black}
|
||||
]
|
||||
\node[root] (util) at (0,0) {Utility};
|
||||
\node[attr] (cons) at (3.6,2.7) {Consistency \&\\integrity};
|
||||
\node[attr] (avail) at (3.6,0.9) {Availability};
|
||||
\node[attr] (perf) at (3.6,-0.9) {Performance};
|
||||
\node[attr] (mod) at (3.6,-2.7) {Modifiability};
|
||||
\node[leafhh] (l1) at (9.2,2.7) {\textbf{(H,\,H)} No booking lost or double-posted under concurrent node failure; invariant violations $= 0$};
|
||||
\node[leafhh] (l2) at (9.2,0.9) {\textbf{(H,\,H)} Failover of the payment service $< 30$\,s with zero transaction loss};
|
||||
\node[leaf] (l3) at (9.2,-0.9) {(H,\,M) Card authorisation p95 $< 2$\,s at $3\times$ baseline load};
|
||||
\node[leaf] (l4) at (9.2,-2.7) {(M,\,H) New regulatory report integrated in $\leq 10$ person-days, touching $\leq 2$ modules};
|
||||
\draw[arr] (util) -- (cons);
|
||||
\draw[arr] (util) -- (avail);
|
||||
\draw[arr] (util) -- (perf);
|
||||
\draw[arr] (util) -- (mod);
|
||||
\draw[arr] (cons) -- (l1);
|
||||
\draw[arr] (avail) -- (l2);
|
||||
\draw[arr] (perf) -- (l3);
|
||||
\draw[arr] (mod) -- (l4);
|
||||
\end{tikzpicture}%
|
||||
}
|
||||
\end{center}
|
||||
|
||||
\centering\small The \textcolor{bankred}{\textbf{(H,\,H) leaves}} -- important \emph{and} hard -- are the architecturally critical points.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{From leaves to weights}
|
||||
\small The utility tree is the \textbf{methodical derivation of the weights}:
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{keypoint}
|
||||
\small Dimension $D_i$ receives $w_i(a) = \textbf{High}$ exactly when the class's characteristic utility tree has \textbf{(H,\,H) leaves} under the corresponding attribute. Medium and Low follow from the remaining leaf ratings.
|
||||
\end{keypoint}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\footnotesize What a weight \emph{asserts}:
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item \textbf{High} is not enthusiasm -- it is a claim with teeth: binding scenarios exist whose failure is \emph{existential}. High weights carry \textbf{veto power} in the match (week 3).
|
||||
\item Every High must survive the question: \emph{``show me the (H,\,H) leaf.''}
|
||||
\item \textbf{Low} is equally deliberate: not ``we do not care'' but \emph{``we will not pay structure for this''}
|
||||
\item \textbf{Medium} is the tradeable middle.
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{What High and Low look like (selection)}
|
||||
\scriptsize
|
||||
\begin{center}
|
||||
\begin{tabular}{@{}p{2.6cm}p{5.3cm}p{5.2cm}@{}}
|
||||
\toprule
|
||||
\textbf{Dimension} & \textbf{High: example} & \textbf{Low: example} \\
|
||||
\midrule
|
||||
D1 Read scalability & a public social/content feed: thousands of reads per write & an ERP used by clerks: load bounded by headcount \\
|
||||
D2 Write scal.\ \& elasticity & Black Friday checkout: $10$--$50\times$ seasonal write peaks & a BI warehouse loaded once, nightly \\
|
||||
D4 Consistency & a payments ledger: one double booking is existential & a social feed: a stale like-count harms nobody \\
|
||||
D8 Simplicity \& TTM & an internal back-office tool: its value is shipping this quarter & a core ledger: care beats speed \\
|
||||
D11 Team scaling & a platform built by thirty teams & a two-person project: nothing to mirror \\
|
||||
D12 AI integrability & the AI-native advisory platform: hosting fallible components \emph{is} the product & a classical accounting module \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\footnotesize Note the \textbf{D4 row}: ledger and feed are near-perfect \emph{mirror images} -- a structure optimised for one is close to pessimal for the other. Part III uses exactly this pair as its anchor.
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% SHAPE, CONSTRAINTS, R(a) ASSEMBLED
|
||||
% ============================================
|
||||
\section{Workload Shape, Constraints, and $R(a)$}
|
||||
|
||||
\begin{frame}{The last two components: shape and constraints}
|
||||
\footnotesize
|
||||
\textbf{Workload shape $S(a)$} -- how load arrives:
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item \emph{interactive} $\cdot$ \emph{continuous stream} $\cdot$ \emph{scheduled batch} $\cdot$ explicitly \emph{hybrid} -- with its signature: read/write ratio, load pattern, latency budget, data volume, change rate
|
||||
\item \textbf{measured, not guessed}: ratios from access logs, patterns from telemetry
|
||||
\item patterns have native shapes too -- the match enforces this as a \emph{gate}: a batch pipeline cannot carry an interactive core
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\textbf{Hard constraints $K(a)$} -- an explicit inventory:
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item regulatory obligations (BCBS 239, PCI DSS, EU AI Act), team size and skills, budget, mandated platforms
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{hinweisbox}
|
||||
\textbf{Constraints are knock-out filters, never weights.} A violating pattern is excluded \emph{before} any scoring -- never averaged away: an architecture that cannot produce the legally required audit trail is \textbf{not a candidate}.
|
||||
\end{hinweisbox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Worked construction: $R(\text{C10})$ -- the advisory platform (your project!)}
|
||||
\footnotesize
|
||||
\begin{center}
|
||||
\footnotesize
|
||||
\begin{tabular}{@{}lp{9.6cm}@{}}
|
||||
\toprule
|
||||
\textbf{High} & D6 auditability (provenance) $\cdot$ D7 evolvability (model/prompt churn) $\cdot$ D9 testability (evals) $\cdot$ D10 cost \emph{per request} $\cdot$ D12 AI \\
|
||||
\textbf{Medium} & D1, D3, D4, D5, D8 \\
|
||||
\textbf{Low} & D2, D11 \\
|
||||
\textbf{Shape} & \emph{hybrid}: interactive advisory dialogue $+$ batch pipelines (indexing, eval runs) \\
|
||||
\textbf{Constraints} & EU AI Act (logging, documentation, human oversight); GDPR \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.2cm}
|
||||
Two Mediums surprise students:
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item \textbf{D3}: users accept seconds for an advisory answer -- the concern is \emph{cost per request}, not speed
|
||||
\item \textbf{D4}: a hybrid -- knowledge index eventually consistent, transaction and audit path strictly ACID
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.1cm}
|
||||
Every High traces to (H,\,H) scenarios; the constraints are knock-out conditions for the match.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{This week's exercise: your QAW}
|
||||
\begin{projektbox}
|
||||
\footnotesize Run a \textbf{compressed QAW} in stakeholder roles (retail customer, compliance officer, operations engineer, product owner):
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item brainstorm, consolidate, prioritise scenarios; refine the top candidates into the \textbf{six-part form} -- each with a \emph{numeric} response measure
|
||||
\item assemble a \textbf{utility tree}; identify the \textbf{(H,\,H) leaves}
|
||||
\end{itemize}
|
||||
\textbf{Deliverable:} $\geq 8$ scenarios, $\geq 3$ addressing the AI components (answer correctness, token cost per request, provider migration).
|
||||
\end{projektbox}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{hinweisbox}
|
||||
\small Not a warm-up: the (H,\,H) leaves become the \textbf{weights of your requirements profile} (A1, next week) -- matched in your week-6 ADR, defended in week 14.
|
||||
\end{hinweisbox}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% SUMMARY
|
||||
% ============================================
|
||||
\section{Summary}
|
||||
|
||||
\begin{frame}{Summary}
|
||||
\footnotesize
|
||||
\begin{enumerate}\setlength\itemsep{2pt}
|
||||
\item Twelve dimensions in five groups -- each a recurring question, \textbf{named and instrumented}: \emph{no instrument, no dimension}
|
||||
\item ISO/IEC 25010:2023 supplies the names -- and since 2023 covers AI systems without private extensions
|
||||
\item ASRs are vague and implicit $\to$ \textbf{elicited} in a QAW; they discriminate only as \textbf{six-part scenarios} -- the response measure (number $+$ unit) is non-negotiable
|
||||
\item The \textbf{utility tree} derives the weights: (H,\,H) leaves $\to$ High; \textbf{High $=$ veto claim}
|
||||
\item $R(a) = (w_1, \dots, w_{12};\, S(a);\, K(a))$ -- weights, measured shape, knock-out constraints
|
||||
\end{enumerate}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{keypoint}
|
||||
\textbf{Maxim 6.} An architecture decision without a response measure is an \emph{opinion}; with a response measure and a fitness function it is a \emph{testable hypothesis}.
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Next week}
|
||||
\begin{columns}[T]
|
||||
\begin{column}{0.55\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Lecture 3 -- the supply side and the match}}
|
||||
\begin{itemize}
|
||||
\item the seven candidate patterns, previewed
|
||||
\item capability profiles $C(p)$ via \textbf{tactics}
|
||||
\item the three-stage, non-compensatory \textbf{fit} procedure
|
||||
\item worked mini-match: the advisory platform (C10!) against three candidates
|
||||
\item recording decisions: \textbf{ADR / MADR}
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\begin{column}{0.42\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Reading}}
|
||||
\begin{itemize}
|
||||
\item this week: script Part I, Sections 2--3
|
||||
\item ahead: Part I, Sections 4--6
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.3cm}
|
||||
\textcolor{bankblue}{\textbf{Exercise}}
|
||||
\begin{itemize}
|
||||
\item Requirements workshop I: QAW $+$ utility tree
|
||||
\item \textbf{A1 due end of week 3}
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% END
|
||||
% ============================================
|
||||
\FHGRClosingPage[][{\color{white}\parbox{0.9\paperwidth}{\centering Thank you!\\[3ex]
|
||||
{\normalsize\mdseries Dr.\ Florian Herzog\\[0.9ex]
|
||||
Fachhochschule Graub\"unden, Chur\\[2.4ex]
|
||||
{\small AISE502 -- AI in Software Engineering II}}}}]
|
||||
|
||||
\end{document}
|
||||
BIN
Folien/AISE502_Vorlesung_3_Folien.pdf
Normal file
660
Folien/AISE502_Vorlesung_3_Folien.tex
Normal file
@ -0,0 +1,660 @@
|
||||
% !TEX encoding = UTF-8 Unicode
|
||||
% ============================================================================
|
||||
% AISE502 -- AI in Software Engineering II
|
||||
% Lecture 3 slides, typeset with the official FHGR beamer theme
|
||||
% (beamerthemeFHGR.sty, University of Applied Sciences of the Grisons).
|
||||
% Slide content is unchanged; only the presentation layer is the FHGR template.
|
||||
% ============================================================================
|
||||
\documentclass[aspectratio=169]{beamer}
|
||||
|
||||
\usetheme[showsection, titlebg=pics/theme_pics/titlepage.png]{FHGR}
|
||||
|
||||
% ============================================
|
||||
% PACKAGES
|
||||
% The theme already loads tikz, graphicx, xcolor, tabularx, colortbl,
|
||||
% listings, hyperref, environ and xparse -- only the extras are needed here.
|
||||
% ============================================
|
||||
\usepackage[british]{babel}
|
||||
\usepackage{booktabs}
|
||||
\usepackage{amsmath}
|
||||
\usepackage{amssymb}
|
||||
\usepackage{tcolorbox}
|
||||
\usetikzlibrary{shapes.geometric, arrows.meta, positioning, fit, backgrounds, calc}
|
||||
|
||||
% ============================================
|
||||
% SEMANTIC COLOURS, MAPPED ONTO THE FHGR PALETTE
|
||||
% The names used throughout the slides are kept, so no slide text changes;
|
||||
% they now resolve to the FHGR brand colours defined by the theme.
|
||||
% ============================================
|
||||
\colorlet{bankblue}{blue} % FHGR blue (4B92A4)
|
||||
\colorlet{bankgreen}{green} % FHGR green (817E65)
|
||||
\colorlet{bankred}{red} % FHGR red (C60219)
|
||||
\colorlet{codegray}{gray} % FHGR gray (595959)
|
||||
\colorlet{backcolour}{linen} % FHGR linen (E1D3B5)
|
||||
\definecolor{aiviolet}{HTML}{6B4E71} % muted plum, kept distinct for the AI lens
|
||||
|
||||
% Attribution labels in English (theme default is German)
|
||||
\renewcommand{\source}[1]{\par\hfill {\tiny\color{FHGRDeco} Source:\,\itshape #1}}
|
||||
\renewcommand{\imagesource}[1]{\par\hfill {\tiny\color{FHGRDeco} Image source:\,\itshape #1}}
|
||||
|
||||
% ============================================
|
||||
% CUSTOM TCOLORBOXES (same semantics as the script, FHGR colours)
|
||||
% ============================================
|
||||
\newtcolorbox{keypoint}{
|
||||
colback=bankblue!7!white,
|
||||
colframe=bankblue,
|
||||
title=Key Concept,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{examplebox}[1][]{
|
||||
colback=bankgreen!10!white,
|
||||
colframe=bankgreen,
|
||||
title={Example: #1},
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{definitionbox}[1][]{
|
||||
colback=linen!40!white,
|
||||
colframe=camel!85!black,
|
||||
title={Definition: #1},
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{thinkbox}{
|
||||
colback=lightGray!35!white,
|
||||
colframe=darkGray,
|
||||
title=Discussion,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{hinweisbox}{
|
||||
colback=bankred!5!white,
|
||||
colframe=bankred,
|
||||
title=Important Note,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{ailinse}[1][]{
|
||||
colback=aiviolet!7!white,
|
||||
colframe=aiviolet,
|
||||
title={AI Lens: #1},
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{projektbox}{
|
||||
colback=bankblue!4!white,
|
||||
colframe=bankblue!70!black,
|
||||
title=Project Link: Portfolio Intelligence Platform,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
% ============================================
|
||||
% TITLE METADATA
|
||||
% ============================================
|
||||
\title[AI in Software Engineering II]{AISE502: AI in Software Engineering II}
|
||||
\subtitle{Lecture 3: The Supply Side, the Match, and the Decision Record\\[0.4ex]{\small Script: Part I, Sections 4--6}}
|
||||
\author{Dr.\ Florian Herzog}
|
||||
\shortname{AISE502}
|
||||
\fullname{Fachhochschule Graub\"unden, Chur -- Autumn Semester 2026}
|
||||
|
||||
\begin{document}
|
||||
|
||||
% ============================================
|
||||
% TITLE SLIDE
|
||||
% ============================================
|
||||
\FHGRTitlePage
|
||||
|
||||
% ============================================
|
||||
% AGENDA
|
||||
% ============================================
|
||||
\begin{frame}{Agenda}
|
||||
\small
|
||||
\begin{enumerate}\setlength\itemsep{1pt}
|
||||
\item Recap: the demand side is built
|
||||
\item The seven candidates: a first look
|
||||
\item Tactics: the causal mechanism from structure to quality
|
||||
\item Deriving a capability rating $c_i(p)$
|
||||
\item The match: what the construction dictates
|
||||
\item The three-stage fit procedure
|
||||
\item The mechanics on a real case: matching the advisory platform (C10)
|
||||
\item Why the weighted sum fails
|
||||
\item Recording the decision: ADR and MADR
|
||||
\item The measurement contract
|
||||
\end{enumerate}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% RECAP
|
||||
% ============================================
|
||||
\section{Recap}
|
||||
|
||||
\begin{frame}{Recap: where we are}
|
||||
\footnotesize
|
||||
\begin{center}
|
||||
\small demand $\;\to\;$ \textbf{supply} $\;\to\;$ \textbf{match} $\;\to\;$ \textbf{record} $\;\to\;$ test
|
||||
\end{center}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\textbf{Done} (weeks 1--2): twelve dimensions; scenarios with response measures; utility tree; weights, shape, constraints -- $R(a)$, worked for C10 and the back-office tool.
|
||||
|
||||
\vspace{0.15cm}
|
||||
\textbf{Today} -- the remaining three framework elements:
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item the \textbf{supply side} $C(p)$: seven candidate patterns, rated \emph{by derivation}, not by taste
|
||||
\item the \textbf{match} $\mathrm{fit}(a,p)$: three stages, non-compensatory -- run live on your project class C10
|
||||
\item the \textbf{record}: ADR/MADR and the measurement contract
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{hinweisbox}
|
||||
\footnotesize \textbf{A1 (requirements dossier) is due this week} -- scenarios, utility tree, $R(\text{platform})$ with weights, shape, and constraints.
|
||||
\end{hinweisbox}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% SEVEN CANDIDATES
|
||||
% ============================================
|
||||
\section{The Seven Candidates}
|
||||
|
||||
\begin{frame}{The seven candidates (1/2)}
|
||||
\footnotesize
|
||||
The set $P$ of the framework -- each in one sentence, with its signature strength and cost:
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{center}
|
||||
\scriptsize
|
||||
\begin{tabular}{@{}p{2.5cm}p{5.0cm}p{2.6cm}p{2.8cm}@{}}
|
||||
\toprule
|
||||
\textbf{Pattern (code)} & \textbf{Structure in one sentence} & \textbf{Signature strength} & \textbf{Signature cost} \\
|
||||
\midrule
|
||||
Layered / 3-tier (L) & one deployable, cut into horizontal \emph{technical} layers & simple and cheap: one build, one database & a typical feature cuts across all layers \\
|
||||
Modular monolith (MM) & one deployable, cut into \emph{domain} modules with machine-enforced boundaries & monolith economics with modular evolvability & boundaries erode without governance \\
|
||||
Hexagonal (HX) & a domain core behind technology-neutral ports with swappable adapters & hermetic testability; swappable technology & indirection that pays off only under change \\
|
||||
Microservices (MS) & many independently deployable services, database per service & team scaling; independent deployment & no ACID across services; highest operating cost \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\scriptsize\textcolor{codegray}{You have met four in production dress: Stack Overflow ran L-style, Monzo runs MS, Prime Video's failed design was SL, Segment's rollback was an MS cut.}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{The seven candidates (2/2)}
|
||||
\footnotesize
|
||||
\begin{center}
|
||||
\scriptsize
|
||||
\begin{tabular}{@{}p{2.5cm}p{5.0cm}p{2.6cm}p{2.8cm}@{}}
|
||||
\toprule
|
||||
\textbf{Pattern (code)} & \textbf{Structure in one sentence} & \textbf{Signature strength} & \textbf{Signature cost} \\
|
||||
\midrule
|
||||
Event-driven (EDA) & components communicate through asynchronous events via a broker & decoupling, elasticity, fault isolation & eventual consistency; end-to-end testing hard \\
|
||||
Pipes-and-filters (PF) & data flows through a chain or DAG of processing steps & throughput and reproducibility for batch work & not built for interactive latency \\
|
||||
Serverless / FaaS (SL) & functions on managed infrastructure: scale-to-zero, per-execution billing & elasticity; zero idle cost & cold starts; cost inverts under sustained load \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{hinweisbox}
|
||||
\footnotesize \textbf{HX is not a competitor in the same race.} It organises dependencies \emph{inside} whichever host it is applied to and \textbf{composes} with the other six -- a hexagonal modular monolith is \emph{one} coherent design, not two rival ones.
|
||||
\end{hinweisbox}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% TACTICS
|
||||
% ============================================
|
||||
\section{Tactics}
|
||||
|
||||
\begin{frame}{Three levels of design vocabulary}
|
||||
\begin{definitionbox}[Architectural pattern (style)]
|
||||
\small A named, documented \textbf{macro-structure}: a topology of elements, permitted relations between them, and known consequences.
|
||||
\end{definitionbox}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{definitionbox}[Architectural tactic]
|
||||
\small An \textbf{elementary design decision} that directly influences the response of \emph{one} quality attribute -- the atomic unit of architectural design. Examples: \emph{heartbeat}, \emph{redundancy} (availability); \emph{use an intermediary}, \emph{defer binding} (modifiability); \emph{introduce concurrency}, \emph{maintain multiple copies} (performance).
|
||||
\end{definitionbox}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\small Students routinely conflate the levels -- the framework keeps them apart, because its \textbf{explanatory mechanism lives exactly in the gap} between them.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Patterns are bundles of tactics}
|
||||
\begin{keypoint}
|
||||
\footnotesize A pattern structurally \textbf{privileges} some tactics while \textbf{impeding} others -- so every pattern helps some quality attributes and hurts others \emph{by construction}, not by accident. The causal chain \textbf{topology $\to$ tactics $\to$ quality attribute responses} makes every $++$ and every $--$ explainable and testable.
|
||||
\end{keypoint}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{examplebox}[EDA as a tactics bundle]
|
||||
\footnotesize An event-driven architecture structurally packages \emph{use an intermediary} (modifiability) and \emph{introduce concurrency} (performance) -- while structurally \emph{impeding} \emph{transactions} (consistency). It helps D7 and hurts D4 by construction.
|
||||
\end{examplebox}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\footnotesize
|
||||
And one demarcation for everything that follows: patterns are evaluated \textbf{per subsystem}, not per company logo -- hybrids are the normal case.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Deriving a rating $c_i(p)$: three sources, applied in order}
|
||||
\footnotesize
|
||||
A rating $c_i(p) \in \{++, +, \circ, -, --\}$ is an \emph{ordinal} claim: how well does the topology structurally support dimension $D_i$?
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{enumerate}\setlength\itemsep{3pt}
|
||||
\item \textbf{Tactics analysis} -- which tactics does the topology make cheap, which does it impede? The causal core: a $--$ that cannot be traced to a structural impediment is an \emph{assertion}, not a rating.
|
||||
\item \textbf{Published ratings} -- Richards \& Ford's star ratings calibrate ours, five-step to five-step ($5\star \to ++$, \dots, $1\star \to --$); \textbf{every deviation is footnoted}. Where no stars exist (HX, SL): primary sources, flagged.
|
||||
\item \textbf{Documented production systems} -- calibration points: a rating that contradicts a documented production result must either explain the context difference or \textbf{yield}.
|
||||
\end{enumerate}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize A capability rating is a \textbf{testable prediction}, not a preference. Supply is constructed with the same rigour as demand.
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Micro-derivation 1: why EDA rates $++$ on D7 (evolvability)}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{3pt}
|
||||
\item \textbf{Tactics analysis:} the broker topology \emph{is} the tactic ``use an intermediary'', built into the macro-structure. A new consumer -- a recommendation engine, an audit feed -- attaches to the event stream \textbf{without touching a single producer}. D7's response measure, \emph{change dispersion}, is structurally minimised: adding functionality is additive, not invasive.
|
||||
\item \textbf{Published rating:} Richards \& Ford rate the style's evolvability at five stars $\to$ $++$, no deviation to footnote.
|
||||
\item \textbf{Production evidence:} LinkedIn's Kafka ecosystem grew for a decade by attaching new consumers to the same durable log.
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{hinweisbox}
|
||||
\footnotesize The rating is a \textbf{trade}, exactly as A2 predicts: the same intermediary that decouples producers from consumers also \emph{impedes transactions and hides the workflow} -- the costs land on D4 and D9.
|
||||
\end{hinweisbox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Micro-derivation 2: why microservices rate $--$ on D4 (consistency)}
|
||||
\small
|
||||
\begin{itemize}\setlength\itemsep{3pt}
|
||||
\item \textbf{Tactics analysis:} the weakness is \emph{structural}. Database-per-service is constitutive of the pattern -- so \textbf{no ACID transaction spans a service boundary}. An invariant crossing services (order $\to$ stock $\to$ ledger) must be maintained by a \textbf{saga}: a sequence of local transactions with \emph{compensating actions}. Intermediate states are visible; compensation is \emph{not} rollback.
|
||||
\item Against D4's response measures (invariant violations: target 0 for ledgers), the topology impedes the transaction tactic \textbf{by construction}. Hence $--$.
|
||||
\item \textbf{Production evidence:} a documented mitigation exists but is conditional -- Monzo makes sagas work under \emph{extreme technological homogeneity}.
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\small The matching procedure handles exactly this case: a \textbf{veto} on a High-weight dimension that only a \emph{documented} mitigation can lift.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{What $++$ and $--$ look like (selection)}
|
||||
\scriptsize
|
||||
\begin{center}
|
||||
\begin{tabular}{@{}p{2.4cm}p{5.4cm}p{5.3cm}@{}}
|
||||
\toprule
|
||||
\textbf{Dimension} & \textbf{What $++$ looks like structurally} & \textbf{What $--$ (or the weak end) looks like} \\
|
||||
\midrule
|
||||
D2 Write scalability & partitioned ingest with elastic consumers (EDA, SL) & one relational database receiving every write (L) \\
|
||||
D4 Consistency & one ACID transaction boundary around all state (L, MM) & sagas across service databases (MS); eventual consistency through a broker (EDA) \\
|
||||
D5 Availability & bulkheaded services: blast radius one service (MS, EDA) & one process: blast radius $100\,\%$ by construction (L, MM: $-$) \\
|
||||
D8 Simplicity \& TTM & one repository, one pipeline, shipping this week (L, PF) & platform engineering before the first feature (MS, EDA) \\
|
||||
D9 Testability & hermetic domain tests behind ports (HX) & verification only against an integrated environment (L: $-$); event flows resisting end-to-end tests (EDA: $-$) \\
|
||||
D12 AI integrability & a natural queue, port, and measurement point (EDA, HX, PF) & an honest middle: platform timeouts vs.\ minutes-long AI runs (SL: $\circ$) \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\footnotesize Note the refused $--$ entries (D6, D12 in the full table): where a weakness is genuinely two-faced or workload-dependent, the honest rating is a \textbf{middle} one -- the supply-side counterpart of A4's ban on vague requirements.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Native workload shape -- and $C(p)$ assembled}
|
||||
\small
|
||||
Every pattern has a \textbf{native workload shape} $S(p)$ -- a \emph{type}, not a rating:
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{center}
|
||||
\footnotesize
|
||||
\begin{tabular}{@{}ll@{}}
|
||||
\toprule
|
||||
L, MM, MS & interactive request/response \\
|
||||
EDA & streams and asynchronous flows \\
|
||||
PF & scheduled batch \\
|
||||
SL & event-triggered, short-lived work \\
|
||||
HX & inherits its host's shape (composition pattern) \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{definitionbox}[Capability profile $C(p)$]
|
||||
\small $C(p) = \bigl(c_1(p), \dots, c_{12}(p);\; S(p)\bigr)$, $c_i(p) \in \{++, +, \circ, -, --\}$: ordinal ratings of structural support for each dimension, justified through \textbf{tactics}, anchored in published star ratings, deviations footnoted -- plus the native shape, which feeds the workload-shape \textbf{gate} of the match.
|
||||
\end{definitionbox}
|
||||
|
||||
\vspace{0.15cm}
|
||||
Part II derives all seven profiles in full -- starting next week.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{AI Lens: an LLM component stresses D3, D10, and D12}
|
||||
\begin{ailinse}[Axis B preview]
|
||||
\small Suppose one component is an LLM call. Nothing new is needed -- the coordinate system already carries it:
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item \textbf{D3}: LLM calls cost \emph{seconds} where classical calls cost milliseconds -- time behaviour becomes a \emph{structural} concern (queues, asynchronous integration, caching)
|
||||
\item \textbf{D10}: per-token pricing makes operating cost a \emph{per-request} attribute -- a bad prompt chain is a cost regression the way an $n{+}1$ query is a latency regression
|
||||
\item \textbf{D12}: the pattern either provides the \emph{queue, port, and measurement point} -- or it does not; the seven patterns differ sharply on exactly that
|
||||
\end{itemize}
|
||||
\end{ailinse}
|
||||
|
||||
\vspace{0.25cm}
|
||||
\small The supply side absorbs AI as \textbf{ratings on existing dimensions} -- assumption A6 at work.
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% THE MATCH
|
||||
% ============================================
|
||||
\section{The Match}
|
||||
|
||||
\begin{frame}{What the construction dictates}
|
||||
\footnotesize
|
||||
Three properties of the profiles are \emph{results of their construction} -- and each imposes a requirement on any admissible aggregation:
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{enumerate}\setlength\itemsep{3pt}
|
||||
\item \textbf{Constraints are knock-outs.} A violated obligation cannot be traded against merit $\to$ eliminate \emph{before} any scoring. The \textbf{workload shape} belongs to the same family: a pattern whose native $S(p)$ contradicts the dominant $S(a)$ cannot carry the class's core.
|
||||
\item \textbf{High weights carry vetoes.} A High weight \emph{was defined} as the presence of (H,\,H) leaves -- scenarios whose failure is existential. A pattern structurally weak exactly there fails those scenarios; excellence elsewhere does not un-fail them $\to$ \textbf{non-compensatory} on High-weight dimensions.
|
||||
\item \textbf{Everything is ordinal.} Ordinal inputs license ordinal outputs -- \emph{rankings and exclusions, never percentages} -- and every result must be checked for stability under plausible re-weighting.
|
||||
\end{enumerate}
|
||||
|
||||
\vspace{0.15cm}
|
||||
These three requirements admit \textbf{essentially one procedure} \dots
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{The three-stage fit procedure}
|
||||
\begin{definitionbox}[Architecture--application fit $\mathrm{fit}(a,p)$]
|
||||
\footnotesize An ordinal aggregate on the scale $\{++, +, \circ, -, --\}$, determined by a deliberately \textbf{non-compensatory, three-stage procedure}:
|
||||
\begin{enumerate}\setlength\itemsep{2pt}
|
||||
\item \textbf{Knock-out screening.} Hard constraints $K(a)$ eliminate patterns before any scoring. The \emph{workload-shape gate}: if $S(p)$ does not match the dominant $S(a)$, the cell is capped at $\circ$ (subsystem role) -- $+$ only for a \emph{constitutive} subsystem of a shape-hybrid class; $-$/$--$ where it would harm binding scenarios.
|
||||
\item \textbf{Veto rule on High-weight dimensions.} $c_i(p) = --$ on a High dimension caps the fit at $-$; $c_i(p) = -$ caps it at $\circ$ -- \emph{unless a documented mitigation exists} (a tactic or hybrid with production evidence), in which case the cell says so and the cap is lifted.
|
||||
\item \textbf{Holistic ordinal reading with mandatory sensitivity analysis.} Survivors are ranked by support of the High set; clustering Medium conflicts can downgrade one step. Result: a \emph{ranking with exclusions}. If it flips under plausible re-weighting, that instability is a genuine \textbf{trade-off point} -- escalate to scenario-based analysis (ATAM).
|
||||
\end{enumerate}
|
||||
\end{definitionbox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Why non-compensatory -- and why the veto can be lifted}
|
||||
\footnotesize
|
||||
\textbf{Non-compensatory mirrors how architectural failure actually works:} Prime Video's serverless design was \emph{excellent} on elasticity and deployability -- none of that compensated for the cost structure its workload shape imposed.
|
||||
|
||||
\vspace{0.15cm}
|
||||
\textbf{The mitigation clause keeps the rule honest:}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item a veto can be lifted -- but only by a \emph{documented} tactic or hybrid with production evidence
|
||||
\item ``pod-sharded replication of the monolith'' (Shopify) or ``event-driven edges around an ACID core'' -- \textbf{never by optimism}
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{examplebox}[Same class -- opposite structures: LMAX and Monzo]
|
||||
\footnotesize LMAX runs core trading on \emph{one} deterministic, event-sourced JVM thread ($6$M orders/s); Monzo runs banking on $\sim 2{,}800$ microservices. \textbf{Both} satisfy the class's binding scenarios. Lesson: $R(a)$ alone defines a \emph{feasible set}; the constraints and context in $K(a)$ decide \emph{within} it. A theory pretending to compute a single winner would be falsified by this pair.
|
||||
\end{examplebox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{The mini-match: $R(\text{C10})$ against L, MM, MS -- stage 1}
|
||||
\small
|
||||
\textbf{The demand side} (from week 2): High on $\{$D6, D7, D9, D10, D12$\}$; shape \emph{hybrid}; EU AI Act and GDPR in $K$.
|
||||
|
||||
\vspace{0.25cm}
|
||||
\textbf{Stage 1 -- knock-out and shape gate:}
|
||||
\begin{itemize}\setlength\itemsep{3pt}
|
||||
\item $S(\text{C10})$ is hybrid: an interactive advisory dialogue at the core, batch/asynchronous pipelines (indexing, evaluation) beside it
|
||||
\item all three candidates are natively \emph{interactive} $\to$ all pass the gate \textbf{for the core} -- the pipelines will be carried by PF- and EDA-shaped \emph{subsystems} in any design
|
||||
\item no hard constraint eliminates a candidate outright -- but note for stage 3: the AI Act's logging and oversight duties \emph{favour} structures where every model call flows through \textbf{one auditable path}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{The mini-match -- stage 2: vetoes on the High dimensions}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{4pt}
|
||||
\item \textbf{L (layered):} rates $-$ on High-weighted \textbf{D7} $\to$ cap $\circ$ unless mitigated -- and at C10's extreme change rate of models, prompts, and frameworks \emph{there is none}: technical layers give the non-deterministic component no boundary, no queue, no measurement point. \textbf{D9} is a second $-$ on a High dimension; D12 offers only $\circ$. Two unmitigated vetoes that \emph{cluster} push the stage-3 reading one step below the cap: $\mathbf{-}$.
|
||||
\item \textbf{MS (microservices):} rates $--$ on High-weighted \textbf{D10} $\to$ would cap at $-$ -- but here the \emph{mitigation clause earns its keep}: C10's cost concern is \textbf{per-request AI cost} (tokens, GPU), governed at a \emph{gateway} -- orthogonal to distribution. The platform-cost veto relaxes to $\circ$. What stops MS from rising further: synchronous service chains \emph{multiply} seconds-scale LLM latency and failure rates, and the pattern's signature payoff (team scaling) sits on \textbf{Low-weighted} D11 -- for a student-sized team the microservice premium buys nothing.
|
||||
\item \textbf{MM (modular monolith):} \textbf{no veto fires at all} -- $+$ or better on every High dimension; its one structural $-$ (D5, blast radius) is Medium-weighted and mitigated by replicated instances.
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{The mini-match -- stage 3 and the verdict}
|
||||
\footnotesize
|
||||
MM leads the High set outright; \textbf{HX inside} raises D9/D12 to $++$ -- the LLM becomes a mockable, swappable adapter on a port.
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{center}
|
||||
\scriptsize
|
||||
\begin{tabular}{@{}p{3.4cm}ccc@{}}
|
||||
\toprule
|
||||
\textbf{High dimension of C10} & \textbf{L} & \textbf{MM ($+$ HX inside)} & \textbf{MS} \\
|
||||
\midrule
|
||||
D6 Security \& auditability & $+$ & $+$ & $\circ$ \\
|
||||
D7 Evolvability & $-$ \emph{(veto)} & $+$ & $++$ \\
|
||||
D9 Testability \& deployability & $-$ \emph{(veto)} & $+$ ($++$ with HX) & $+$ \\
|
||||
D10 Operating cost & $++$ & $++$ & $--$ \emph{(veto, relaxed)} \\
|
||||
D12 AI integrability & $\circ$ & $+$ ($++$ with HX) & $\circ$ \\
|
||||
\midrule
|
||||
\textbf{Verdict $\mathrm{fit}(\text{C10},p)$} & $\mathbf{-}$ & $\mathbf{++}$ & $\mathbf{\circ}$ \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize The \textbf{hexagonal modular monolith} is the primary recommendation -- and it is exactly the architecture of your course project. One profile, three candidates, three stages: a \emph{ranking with exclusions}.
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Discussion}
|
||||
\begin{thinkbox}
|
||||
\small Run the same three candidates against $R(\text{back-office})$ from week 2 -- High on D4, D6, D7, D8, D10. Which veto fires first, and does the verdict change?
|
||||
|
||||
\vspace{0.2cm}
|
||||
Check yourselves: MS now hits \textbf{two unmitigated $--$ vetoes at once} (D8 and D10, both High for this class); L's strengths sit exactly on the class's High set (D4, D8, D10), and only D7 caps it -- liftable by scoping to a small, stable domain. The verdicts become \textbf{L $+$, MM $++$, MS $--$}: the same winner, but a radically re-ordered field.
|
||||
\end{thinkbox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Why the obvious alternative fails}
|
||||
\small
|
||||
Why not score $1$--$5$, multiply by weights, add up ($V = \sum_i w_i \cdot v_i$)? The additive form is licensed only under three conditions -- \textbf{all three fail here}:
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{enumerate}\setlength\itemsep{2pt}
|
||||
\item \textbf{Cardinal (interval) scales} -- but the ratings are ordinal by construction: what would ``microservices score $4.3$ on consistency'' \emph{mean}?
|
||||
\item \textbf{Preferential independence} -- violated \emph{by definition}: A2 says the value of ``scalability $= ++$'' depends on what happens to consistency; trade-offs \emph{are} preferential dependence
|
||||
\item \textbf{Weights as trade-off rates} -- nobody can state, or defend to an auditor, the rate at which audit-trail quality is exchangeable for deployment frequency
|
||||
\end{enumerate}
|
||||
|
||||
\vspace{0.2cm}
|
||||
The AHP repair inherits documented defects: adding an alternative (even a \emph{copy}) can \textbf{reverse the ranking}; Dyer's verdict: ``flawed as a procedure for ranking alternatives''.
|
||||
|
||||
\vspace{0.15cm}
|
||||
\textbf{Kept} from multi-criteria analysis: the \emph{explication discipline} -- criteria on the table, weights argued, options compared. \textbf{Dropped}: the arithmetic pretensions.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Beware pseudo-precision}
|
||||
\begin{hinweisbox}
|
||||
\small A weighted-sum matrix over ordinal ratings produces numbers -- ``pattern A: $3.87$; pattern B: $3.79$'' -- whose significant digits are \textbf{artefacts of the procedure}, not measurements of anything. Such numbers end discussions that should be had (the $0.08$ gap will not survive any plausible re-weighting) and lend false authority to buried assumptions.
|
||||
\end{hinweisbox}
|
||||
|
||||
\vspace{0.3cm}
|
||||
\small The professional habit this module trains is the opposite:
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item report \textbf{rankings with exclusions}, and state the \textbf{veto} behind each exclusion
|
||||
\item run the \textbf{sensitivity analysis}
|
||||
\item if the recommendation flips under plausible weights, you have found a genuine \textbf{trade-off point} -- a \emph{finding} to escalate to stakeholders, not an error to hide with more decimals
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{The status of the matrix}
|
||||
\small
|
||||
Applying the procedure to all pairs yields the $7 \times 10$ matrix of Part IV. One point governs how every cell is read:
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize The matrix is an \textbf{explication and communication instrument} -- a compressed, teachable heuristic that forces criteria, weights, and assumptions into the open -- \emph{not} a computation that determines decisions. The rigorous method behind every contested cell is the \textbf{ATAM}: scenario walk-throughs, sensitivity points, trade-off points, risks.
|
||||
\end{keypoint}
|
||||
|
||||
\vspace{0.2cm}
|
||||
Three honest limits, holding throughout:
|
||||
\begin{enumerate}\setlength\itemsep{2pt}
|
||||
\item the scales are \textbf{ordinal} -- no percentages, ever
|
||||
\item the ratings are \textbf{context-dependent} -- the serverless cost rating literally \emph{inverts} with load shape
|
||||
\item \textbf{hybrids are the normal case} -- the matrix is read \emph{per subsystem}
|
||||
\end{enumerate}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% RECORDING THE DECISION
|
||||
% ============================================
|
||||
\section{Recording the Decision}
|
||||
|
||||
\begin{frame}{The decision is the primary artefact}
|
||||
\small
|
||||
A1 says: what we choose is a \textbf{decision} with high reversal cost -- and undocumented decisions \emph{evaporate}:
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item the code shows \emph{what} was built, never \emph{why}
|
||||
\item within a few staff rotations the rationale is gone; later changes violate constraints nobody remembers -- which is what teams experience as \textbf{``legacy''}
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.15cm}
|
||||
ISO/IEC/IEEE 42010:2022 draws the normative conclusion: a conformant architecture description \textbf{must} record architecture decisions \emph{and their rationale} (Clause 6.10).
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{definitionbox}[Architecture Decision Record (ADR)]
|
||||
\footnotesize A short text document -- one to two pages, \textbf{versioned in the code repository}, one decision per file -- with Nygard's structure: \textbf{Title} $\cdot$ \textbf{Status} (proposed / accepted / deprecated / superseded) $\cdot$ \textbf{Context} (the forces at play, value-neutral) $\cdot$ \textbf{Decision} (active voice: ``We will \dots'') $\cdot$ \textbf{Consequences} (positive \emph{and} negative).
|
||||
\end{definitionbox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Three design choices make the format work -- and MADR extends it}
|
||||
\footnotesize
|
||||
\begin{enumerate}\setlength\itemsep{2pt}
|
||||
\item \textbf{Co-location} -- ADRs live in the repository, next to the code they govern, not in a wiki that dies with the project office
|
||||
\item \textbf{Brevity} -- one decision, one page: a format cheap enough to be used beats a comprehensive one that is not
|
||||
\item \textbf{Immutability} -- a superseded ADR is never edited or deleted; a new ADR supersedes it. The record of \emph{why we changed our minds} is often more valuable than the current answer.
|
||||
\end{enumerate}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\textbf{MADR} adds explicit \textbf{decision drivers} and \textbf{considered options} (each with pros and cons), plus an optional \textbf{confirmation} section.
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize MADR is this module's format for a structural reason: \emph{decision drivers $+$ considered options} is exactly \textbf{one row of the matching matrix in narrative long form} -- a completed matrix is the tabular compression of many MADRs.
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{ADR-011: the LLM gateway decision (your project, week 6)}
|
||||
\begin{tcolorbox}[colback=gray!4!white, colframe=gray!55!black, boxrule=0.6pt, arc=2pt, top=3pt, bottom=3pt, left=6pt, right=6pt]
|
||||
\scriptsize\ttfamily
|
||||
\textbf{ADR-011: Route all LLM calls through one gateway port}\\[2pt]
|
||||
Status: accepted | supersedes ADR-004\\[4pt]
|
||||
\textbf{Context:} providers deprecate models on 6--12-month cycles; token costs must be attributable per request; domain logic must stay testable without paid, non-deterministic API calls.\\[4pt]
|
||||
\textbf{Drivers:} D7 evolvability -- provider change stays cheap $\cdot$ D9 testability -- hermetic tests $\cdot$ D12 -- per-request cost observability\\[4pt]
|
||||
\textbf{Options:} (1) direct provider-SDK calls from domain services $\cdot$ \textbf{(2) one gateway behind a domain-owned port} $\leftarrow$ chosen $\cdot$ (3) per-feature adapters without a shared gateway\\[4pt]
|
||||
\textbf{Consequences:} $+$ provider migration is an adapter task; domain tests run against fakes. $-$ one more runtime component; $\sim$20--50\,ms latency; the gateway needs its own SLO.
|
||||
\end{tcolorbox}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\footnotesize
|
||||
\textbf{Confirmation (measurement contract, in embryonic form):}
|
||||
\begin{itemize}\setlength\itemsep{0pt}
|
||||
\item static rule: no domain module imports the provider SDK (ArchUnit, CI gate, 0 violations)
|
||||
\item eval-harness pass rate $\geq 95\,\%$ on every model/prompt change
|
||||
\item token cost per request $\leq$ budget (p95), monitored continually
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Diagrams and the measurement contract}
|
||||
\small
|
||||
\textbf{C4 -- diagrams for decisions, sparingly:} four zoom levels (system context, container, component, code). For this module, \textbf{container level dominates}: a modular monolith is \emph{one} container with enforced internal boundaries, a microservice system is \emph{many}, an event-driven system inserts a \emph{broker} container between them.
|
||||
|
||||
\vspace{0.25cm}
|
||||
\textbf{The measurement contract} -- the fifth framework element:
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item every ADR ends with the \textbf{fitness functions and thresholds that would tell us the decision has failed}
|
||||
\item static rules as CI gates $\cdot$ scenario response measures as automated tests $\cdot$ cost and latency budgets as telemetry alarms
|
||||
\item in operation, the four \textbf{DORA metrics} test whether the delivery-relevant promises hold
|
||||
\item on breach: a documented evolution path (Strangler Fig) recorded as a \emph{superseding ADR} -- never a silent rewrite
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{AI Lens: an agent drafts the ADR -- a human owns the decision}
|
||||
\begin{ailinse}[Axis A]
|
||||
\small ADRs are an ideal task for AI assistance and a \textbf{hard boundary for AI authority}. An agent with access to the repository, the utility tree, and the matrix can \emph{draft} a competent MADR in minutes: enumerate options, fill pros and cons from the capability profiles, propose fitness functions. Use that. But the decision itself is an \textbf{act of accountability}: a nameable person weighs the drivers, accepts the negative consequences, and answers for them later.
|
||||
\end{ailinse}
|
||||
|
||||
\vspace{0.25cm}
|
||||
\small Second-order effect: agents \emph{read} ADRs and convention files on every run -- documentation quality is reproduced \textbf{at machine speed, in whichever direction it points}. A precise ADR corpus is leverage; a stale one is automated misdirection.
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% SUMMARY
|
||||
% ============================================
|
||||
\section{Summary}
|
||||
|
||||
\begin{frame}{Summary: Part I is complete}
|
||||
\footnotesize
|
||||
\begin{enumerate}\setlength\itemsep{2pt}
|
||||
\item \textbf{Supply:} seven candidates; ratings derived from \emph{tactics}, calibrated against published stars, checked against production -- never taste
|
||||
\item \textbf{Match:} knock-outs and shape gate $\to$ vetoes on High dimensions (liftable only by documented mitigations) $\to$ ordinal reading with sensitivity analysis; weighted sums fail three preconditions -- the matrix is an \emph{explication instrument}, not a computation
|
||||
\item Worked end to end: C10 vs.\ L/MM/MS $\to$ \textbf{hexagonal modular monolith} ($++$) -- your project architecture
|
||||
\item \textbf{Record:} MADR -- drivers $+$ options $=$ one matrix row; co-located, brief, immutable
|
||||
\item \textbf{Measure:} every ADR ends in a measurement contract; breach $\to$ superseding ADR
|
||||
\end{enumerate}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize The chain to remember: class $\to$ scenarios $\to$ utility tree $\to$ $R(a)$ $\to$ non-compensatory match against $C(p)$ $\to$ ADR $\to$ measurement contract $\to$ operation -- and, because profiles drift, back around.
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{This week and next week}
|
||||
\begin{columns}[T]
|
||||
\begin{column}{0.55\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Exercise this week}}
|
||||
\begin{itemize}\small
|
||||
\item Requirements workshop II: finalise $R(\text{platform})$ -- weights, workload shape, knock-out constraints
|
||||
\item ontology as a contract
|
||||
\item \textbf{A1 due: requirements dossier} (scenarios $+$ utility tree $+$ $R(a)$)
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\begin{column}{0.42\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Lecture 4}}
|
||||
\begin{itemize}\small
|
||||
\item Part II begins: \textbf{Layered, Modular Monolith, Hexagonal}
|
||||
\item problem $\to$ profile $\to$ engineering $\to$ ``build it and study it''
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\textcolor{bankblue}{\textbf{Reading}}
|
||||
\begin{itemize}\small
|
||||
\item this week: Part I, Sections 4--6
|
||||
\item ahead: Part II, L/MM/HX
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% END
|
||||
% ============================================
|
||||
\FHGRClosingPage[][{\color{white}\parbox{0.9\paperwidth}{\centering Thank you!\\[3ex]
|
||||
{\normalsize\mdseries Dr.\ Florian Herzog\\[0.9ex]
|
||||
Fachhochschule Graub\"unden, Chur\\[2.4ex]
|
||||
{\small AISE502 -- AI in Software Engineering II}}}}]
|
||||
|
||||
\end{document}
|
||||
BIN
Folien/AISE502_Vorlesung_4_Folien.pdf
Normal file
809
Folien/AISE502_Vorlesung_4_Folien.tex
Normal file
@ -0,0 +1,809 @@
|
||||
% !TEX encoding = UTF-8 Unicode
|
||||
% ============================================================================
|
||||
% AISE502 -- AI in Software Engineering II
|
||||
% Lecture 4 slides, typeset with the official FHGR beamer theme
|
||||
% (beamerthemeFHGR.sty, University of Applied Sciences of the Grisons).
|
||||
% Slide content is unchanged; only the presentation layer is the FHGR template.
|
||||
% ============================================================================
|
||||
\documentclass[aspectratio=169]{beamer}
|
||||
|
||||
\usetheme[showsection, titlebg=pics/theme_pics/titlepage.png]{FHGR}
|
||||
|
||||
% ============================================
|
||||
% PACKAGES
|
||||
% The theme already loads tikz, graphicx, xcolor, tabularx, colortbl,
|
||||
% listings, hyperref, environ and xparse -- only the extras are needed here.
|
||||
% ============================================
|
||||
\usepackage[british]{babel}
|
||||
\usepackage{booktabs}
|
||||
\usepackage{amsmath}
|
||||
\usepackage{amssymb}
|
||||
\usepackage{tcolorbox}
|
||||
\usetikzlibrary{shapes.geometric, arrows.meta, positioning, fit, backgrounds, calc}
|
||||
|
||||
% ============================================
|
||||
% SEMANTIC COLOURS, MAPPED ONTO THE FHGR PALETTE
|
||||
% The names used throughout the slides are kept, so no slide text changes;
|
||||
% they now resolve to the FHGR brand colours defined by the theme.
|
||||
% ============================================
|
||||
\colorlet{bankblue}{blue} % FHGR blue (4B92A4)
|
||||
\colorlet{bankgreen}{green} % FHGR green (817E65)
|
||||
\colorlet{bankred}{red} % FHGR red (C60219)
|
||||
\colorlet{codegray}{gray} % FHGR gray (595959)
|
||||
\colorlet{backcolour}{linen} % FHGR linen (E1D3B5)
|
||||
\definecolor{aiviolet}{HTML}{6B4E71} % muted plum, kept distinct for the AI lens
|
||||
|
||||
% Attribution labels in English (theme default is German)
|
||||
\renewcommand{\source}[1]{\par\hfill {\tiny\color{FHGRDeco} Source:\,\itshape #1}}
|
||||
\renewcommand{\imagesource}[1]{\par\hfill {\tiny\color{FHGRDeco} Image source:\,\itshape #1}}
|
||||
|
||||
% ============================================
|
||||
% CUSTOM TCOLORBOXES (same semantics as the script, FHGR colours)
|
||||
% ============================================
|
||||
\newtcolorbox{keypoint}{
|
||||
colback=bankblue!7!white,
|
||||
colframe=bankblue,
|
||||
title=Key Concept,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{examplebox}[1][]{
|
||||
colback=bankgreen!10!white,
|
||||
colframe=bankgreen,
|
||||
title={Example: #1},
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{definitionbox}[1][]{
|
||||
colback=linen!40!white,
|
||||
colframe=camel!85!black,
|
||||
title={Definition: #1},
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{thinkbox}{
|
||||
colback=lightGray!35!white,
|
||||
colframe=darkGray,
|
||||
title=Discussion,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{hinweisbox}{
|
||||
colback=bankred!5!white,
|
||||
colframe=bankred,
|
||||
title=Important Note,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{ailinse}[1][]{
|
||||
colback=aiviolet!7!white,
|
||||
colframe=aiviolet,
|
||||
title={AI Lens: #1},
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{projektbox}{
|
||||
colback=bankblue!4!white,
|
||||
colframe=bankblue!70!black,
|
||||
title=Project Link: Portfolio Intelligence Platform,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
% ============================================
|
||||
% TITLE METADATA
|
||||
% ============================================
|
||||
\title[AI in Software Engineering II]{AISE502: AI in Software Engineering II}
|
||||
\subtitle{Lecture 4: Patterns I -- Layered, Modular Monolith, Hexagonal\\[0.4ex]{\small Script: Part II, Sections L / MM / HX}}
|
||||
\author{Dr.\ Florian Herzog}
|
||||
\shortname{AISE502}
|
||||
\fullname{Fachhochschule Graub\"unden, Chur -- Autumn Semester 2026}
|
||||
|
||||
\begin{document}
|
||||
|
||||
% ============================================
|
||||
% TITLE SLIDE
|
||||
% ============================================
|
||||
\FHGRTitlePage
|
||||
|
||||
% ============================================
|
||||
% AGENDA
|
||||
% ============================================
|
||||
\begin{frame}{Agenda}
|
||||
\small
|
||||
\begin{enumerate}\setlength\itemsep{1pt}
|
||||
\item How Part II works: examples first, generalisation after
|
||||
\item \textbf{L} -- Layered architecture: the simplest structure that does the whole job
|
||||
\item \textbf{MM} -- Modular monolith: hard boundaries inside one deployable
|
||||
\item \textbf{HX} -- Hexagonal architecture: dependency direction as a compiler-checked property
|
||||
\item The three side by side
|
||||
\item This week's exercise: architecture study I
|
||||
\end{enumerate}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% HOW PART II WORKS
|
||||
% ============================================
|
||||
\section{How Part II Works}
|
||||
|
||||
\begin{frame}{How Part II works -- and why in this order}
|
||||
\footnotesize
|
||||
Every pattern section follows the \textbf{same rhythm}:
|
||||
\begin{enumerate}\setlength\itemsep{1pt}
|
||||
\item what the pattern \emph{is} -- definition, topology, variants
|
||||
\item what real-world \textbf{problem} it was invented to solve, with named production systems
|
||||
\item how it behaves on the \textbf{twelve dimensions} -- rating and structural reason, side by side
|
||||
\item what it does to your \textbf{engineering day} -- build, test, CI/CD, operations, teams
|
||||
\item where you can \textbf{build it and study it} -- plus \textbf{anti-patterns} with measurable alarms, and \textbf{selection signals}
|
||||
\end{enumerate}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize The order is the point: software engineering is not mathematics. Its patterns were not derived from axioms -- they were \textbf{abstracted from systems that worked and systems that failed expensively}. Part II follows that order of discovery; the generalisation comes at the \emph{end}, once you have seen the cases.
|
||||
\end{keypoint}
|
||||
|
||||
\vspace{0.1cm}
|
||||
Every rating is \textbf{anchored}, and \textbf{every deviation is footnoted} in the script.
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% L -- LAYERED
|
||||
% ============================================
|
||||
\section{L -- Layered Architecture}
|
||||
|
||||
\begin{frame}{L -- Layered architecture / 3-tier}
|
||||
\emph{\textcolor{bankblue}{Two of you must ship a working product by December: what is the simplest structure that does the whole job?}}
|
||||
|
||||
\vspace{0.25cm}
|
||||
\begin{definitionbox}[Layered architecture (L)]
|
||||
\small A macro-structure that partitions a system into \textbf{horizontal technical layers} -- typically presentation, business logic, persistence, database -- with a directed dependency rule: each layer may use only the layer(s) beneath it. The whole system is deployed, scaled, and fails as \textbf{one unit}: exactly one \emph{architecture quantum}.
|
||||
\end{definitionbox}
|
||||
|
||||
\vspace{0.25cm}
|
||||
\small Two terms to keep in view -- they recur in \emph{every} pattern section:
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item \textbf{technically partitioned}: units cut by technical role, not by business capability
|
||||
\item \textbf{architecture quantum}: one unit of deployment, scaling, and failure
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{L -- topology}
|
||||
\begin{center}
|
||||
\resizebox{!}{0.66\textheight}{%
|
||||
\begin{tikzpicture}[
|
||||
sysbox/.style={rectangle, draw, rounded corners=4pt, minimum width=3.2cm, minimum height=1.2cm, align=center, font=\small\sffamily, line width=0.8pt},
|
||||
layer/.style={sysbox, fill=bankgreen!15, draw=bankgreen, minimum width=7.2cm, minimum height=0.95cm},
|
||||
extern/.style={sysbox, fill=gray!15, draw=gray!60!black, minimum width=7.2cm, minimum height=0.95cm},
|
||||
arr/.style={-{Stealth[length=2.5mm]}, thick, gray!60!black}
|
||||
]
|
||||
\node[layer] (pres) at (0,0) {Presentation layer};
|
||||
\node[layer, below=0.45cm of pres] (biz) {Business layer};
|
||||
\node[layer, below=0.45cm of biz] (pers) {Persistence layer};
|
||||
\node[extern, below=0.45cm of pers] (db) {Database};
|
||||
\draw[arr] (pres) -- (biz);
|
||||
\draw[arr] (biz) -- (pers);
|
||||
\draw[arr] (pers) -- (db);
|
||||
\draw[dashed, gray!60!black, rounded corners=6pt]
|
||||
([xshift=-0.5cm,yshift=0.35cm]pres.north west) rectangle ([xshift=0.5cm,yshift=-0.35cm]db.south east);
|
||||
\node[font=\footnotesize\sffamily, text=gray!60!black, below=0.15cm of db, yshift=-0.35cm, align=center]
|
||||
{one architecture quantum: one unit of deployment, scaling, and failure};
|
||||
\draw[-{Stealth[length=2.5mm]}, thick, bankred, dashed]
|
||||
([xshift=-1.3cm]pres.west) -- ([xshift=-1.3cm]db.west)
|
||||
node[midway, left, font=\footnotesize\sffamily, text=bankred, align=center] {typical\\feature\\change};
|
||||
\end{tikzpicture}%
|
||||
}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\small The dashed red arrow marks the structural weakness: a typical business-facing feature \textbf{cuts across every layer} -- the root cause of the $-$ on evolvability (D7).
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{L -- the problem it solves}
|
||||
\footnotesize
|
||||
As old as commercial computing: a business needs a tool -- capture orders, look up customers, post invoices -- and it needs it \emph{soon}. A small team, one relational database, a deadline in months. What such a project needs first is not elasticity; it is \textbf{a structure a handful of developers can hold in their heads while shipping}.
|
||||
|
||||
\vspace{0.2cm}
|
||||
Layering was the natural first answer because it \textbf{mirrors both the technology and the team}:
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item the stack already separates concerns: something renders screens, something executes rules, something persists rows -- and so do the skills in the room
|
||||
\item one added rule -- \emph{dependencies point downwards only} -- turns the habit into a pattern
|
||||
\item the reward: one build, one artefact, one ACID database, one thing to operate
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.2cm}
|
||||
De-facto standard since the 1990s: Spring MVC, .NET, Rails and Django scaffold it by default; Metabase ships its whole BI tier as a single JAR \emph{deliberately}. What it was never designed to give: independent scaling and change isolation.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{L -- capability profile (column L of the consolidated table)}
|
||||
\scriptsize
|
||||
\renewcommand{\arraystretch}{0.84}%
|
||||
\vspace{-0.1cm}
|
||||
\begin{center}
|
||||
\begin{tabular}{@{}p{2.9cm}cp{7.8cm}@{}}
|
||||
\toprule
|
||||
\textbf{Dimension} & \textbf{Rating} & \textbf{Structural reason} \\
|
||||
\midrule
|
||||
D1 Read scalability & $\circ$ & stateless replication $+$ caching scale reads; the single write path remains \\
|
||||
D2 Write scal.\ \& elasticity & $--$ & every write funnels through one database inside one quantum \\
|
||||
D3 Latency \& predictability & $+$ & in-process calls: no network hop, no tail amplification \\
|
||||
D4 Consistency \& integrity & $++$ & one ACID transaction boundary under one process \\
|
||||
D5 Availability \& isolation & $-$ & one process: blast radius $100\,\%$ by construction \\
|
||||
D6 Security \& auditability & $+$ & one audit log, one small compliance scope \\
|
||||
D7 Evolvability & $-$ & technical partitioning: a feature cuts across every layer \\
|
||||
D8 Simplicity \& TTM & $++$ & one repo, one pipeline -- lowest entry threshold in the catalogue \\
|
||||
D9 Testability \& deployability & $-$ & any change redeploys the whole artefact, full regression scope \\
|
||||
D10 Operating cost & $++$ & one cheap deployable, near-zero platform staff \\
|
||||
D11 Team scaling & $-$ & one quantum, one release train: a single-team pattern \\
|
||||
D12 AI integrability & $\circ$ & an AI call is easy to host -- but gets no boundary, queue, or measurement point \\
|
||||
\midrule
|
||||
Native shape $S(p)$ & \multicolumn{2}{l}{interactive} \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{L -- three cells with a story}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{3pt}
|
||||
\item \textbf{D1 $= \circ$, D2 $= --$: the read/write split.} The one-star scalability rating conflates two dimensions: replication $+$ caching demonstrably scale \emph{reads} (Stack Overflow, Instagram) -- the single write path remains the bottleneck.
|
||||
\item \textbf{D3 $= +$: a footnoted deviation.} In-process calls give low, \emph{predictable} latency; the source's two stars reflect throughput, which D1/D2 capture separately.
|
||||
\item \textbf{D7, D9, D11 $= -$: the negative change axis.} A feature disperses across all layers; any change redeploys everything; one release train $=$ a single-team pattern.
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{examplebox}[Stack Overflow -- a layered monolith at planetary scale]
|
||||
\footnotesize $\sim 1.3$ billion page views/month from $\sim 9$ web servers before a RAM-resident SQL Server cluster plus Redis -- $\sim 12$\,ms renders. A read-heavy, cache-friendly workload is exactly what carries D1: a counter-example to ``scale requires microservices'' \emph{and} evidence for the single-write-path limit (D2 $= --$).
|
||||
\end{examplebox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{L -- software engineering implications}
|
||||
\footnotesize
|
||||
\begin{columns}[T]
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Build and CI/CD}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item one build, one pipeline, one artefact -- CI trivially simple
|
||||
\item but release cadence is bounded by \textbf{full-regression scope}: the pipeline is cheap, its gate is expensive
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\textcolor{bankblue}{\textbf{Test}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item in-process integration tests: fast, no network doubles
|
||||
\item risk: suites coupled to technical layers -- refactoring breaks hundreds of tests that verify \emph{structure}, not behaviour
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Deployment and operations}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item whole-system releases and rollbacks; classical APM suffices, \textbf{no distributed tracing needed} -- an underrated virtue
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\textcolor{bankblue}{\textbf{Maintenance and teams}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item without enforced conformance the pattern \textbf{decays predictably} -- Lehman's second law has no structural counterweight here
|
||||
\item one team; sub-teams by layer reproduce the layers as hand-off friction (textbook Conway)
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{L -- build it and study it}
|
||||
\begin{examplebox}[Build it and study it -- layered]
|
||||
\footnotesize \textbf{Build.} Django (Python, BSD-3, very active) scaffolds the pattern out of the box: model--view--template \emph{is} an enforced persistence/logic/presentation layering. Canonical Java stack: Spring Boot MVC with Controller $\to$ Service $\to$ Repository.
|
||||
|
||||
\textbf{Study.} \texttt{healthchecks/healthchecks} ($\sim$10k stars, BSD-3, active): a production Django monolith -- four apps (\texttt{accounts}, \texttt{api}, \texttt{front}, \texttt{payments}), each cleanly layered. Runs locally on SQLite: \emph{the easiest start in this catalogue}.
|
||||
\end{examplebox}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{hinweisbox}
|
||||
\footnotesize \textbf{A habit to build now:} before adopting \emph{any} system -- check its \textbf{licence} and its \textbf{maintenance status} (last commit, open issues). The boxes in this part deliberately leave findings visible: a no-derivatives licence here, an archived flagship there. Verifying this is part of the engineering, and it takes two minutes.
|
||||
\end{hinweisbox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{L -- anti-patterns, alarms, selection signals}
|
||||
\small
|
||||
\textbf{Anti-patterns with measurable alarms:}
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item \emph{Architecture sinkhole} -- requests pass through layers that add no logic; rule of thumb: $> 80\,\%$ pass-through requests signal structure without function. \textbf{Alarm:} instrument the pass-through share; track change dispersion (D7 measure).
|
||||
\item \emph{Big ball of mud} -- unguarded decay. \textbf{Alarm:} rising cross-layer dependency violations; countermeasure: the dependency-rule-as-CI-gate machinery of the modular monolith.
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{columns}[T]
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankgreen}{\textbf{Choose when}}
|
||||
\begin{itemize}\footnotesize\setlength\itemsep{1pt}
|
||||
\item team $\leq$ roughly ten; budget and schedule tight
|
||||
\item domain not yet understood; CRUD-dominant at modest scale
|
||||
\item one ACID database satisfies consistency
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankred}{\textbf{Avoid when}}
|
||||
\begin{itemize}\footnotesize\setlength\itemsep{1pt}
|
||||
\item subdomains need independent scaling
|
||||
\item high change rate per subdomain; fault isolation required
|
||||
\item several teams must release independently
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{L -- AI lens and key concept}
|
||||
\begin{ailinse}[The layered pattern and AI components]
|
||||
\footnotesize D12 $= \circ$ -- instructive because the problem is not difficulty but \textbf{ease}: nothing stops a developer from calling an LLM synchronously from a business-layer service, \emph{and that is precisely the risk}. No structural boundary, no queue, no measurement point; token costs are invisible to classical APM; non-determinism leaks freely across layers, which encode technology, not trust. \textbf{Hosting an AI call is easy; containing one is unsupported.}
|
||||
\end{ailinse}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize The layered architecture buys the \textbf{lowest entry cost in the catalogue} ($++$ on D8, D10, an honest $++$ on D4) and pays on every axis of change and scale (D2, D5, D7, D9, D11 all negative). Not a defect -- a \emph{specific trade}: maximal day-one simplicity against minimal structural options later. Mis-chosen only when the profile weights the options it sold off.
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% MM -- MODULAR MONOLITH
|
||||
% ============================================
|
||||
\section{MM -- Modular Monolith}
|
||||
|
||||
\begin{frame}{MM -- Modular monolith}
|
||||
\emph{\textcolor{bankblue}{You want monolith economics but fear the big ball of mud: can hard boundaries live inside one deployable?}}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\small Yes -- \textbf{provided the boundaries are checked by a machine, not by good intentions.}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{definitionbox}[Modular monolith (MM)]
|
||||
\small A single deployment artefact (one process, one quantum) whose interior is partitioned \textbf{by domain} into modules with enforced boundaries: each module encapsulates one \emph{bounded context} -- including sovereignty over its own persistent data -- and inter-module communication passes exclusively through published module APIs or in-process events. \textbf{Boundary conformance is verified automatically.}
|
||||
\end{definitionbox}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\small \emph{Bounded context} (domain-driven design): a business subdomain with its own self-consistent vocabulary and model.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{MM -- topology}
|
||||
\begin{center}
|
||||
\resizebox{0.88\textwidth}{!}{%
|
||||
\begin{tikzpicture}[
|
||||
sysbox/.style={rectangle, draw, rounded corners=4pt, align=center, font=\small\sffamily, line width=0.8pt},
|
||||
module/.style={sysbox, fill=bankblue!20, draw=bankblue, minimum width=3.0cm, minimum height=1.1cm, font=\small\sffamily\bfseries},
|
||||
data/.style={sysbox, fill=gray!15, draw=gray!60!black, minimum width=3.0cm, minimum height=0.8cm, font=\footnotesize\sffamily},
|
||||
arr/.style={-{Stealth[length=2.5mm]}, thick, gray!60!black},
|
||||
darr/.style={{Stealth[length=2.5mm]}-{Stealth[length=2.5mm]}, thick, bankgreen}
|
||||
]
|
||||
\node[module] (m1) at (-4.2,0) {Portfolio\\module};
|
||||
\node[module] (m2) at (0,0) {Instrument\\module};
|
||||
\node[module] (m3) at (4.2,0) {Reporting\\module};
|
||||
\node[data, below=0.5cm of m1] (d1) {owned tables};
|
||||
\node[data, below=0.5cm of m2] (d2) {owned tables};
|
||||
\node[data, below=0.5cm of m3] (d3) {owned tables};
|
||||
\draw[arr] (m1) -- (d1);
|
||||
\draw[arr] (m2) -- (d2);
|
||||
\draw[arr] (m3) -- (d3);
|
||||
\draw[darr] (m1) -- node[above, font=\footnotesize\sffamily, text=bankgreen] {public API /} node[below, font=\footnotesize\sffamily, text=bankgreen] {in-process events} (m2);
|
||||
\draw[darr] (m2) -- node[above, font=\footnotesize\sffamily, text=bankgreen] {public API /} node[below, font=\footnotesize\sffamily, text=bankgreen] {in-process events} (m3);
|
||||
\draw[rounded corners=6pt, line width=1pt, gray!60!black]
|
||||
(-6.1,1.1) rectangle (6.1,-2.6);
|
||||
\node[font=\footnotesize\sffamily, text=gray!60!black, align=center] at (0,-3.05)
|
||||
{single deployable: one process, one architecture quantum};
|
||||
\node[font=\footnotesize\sffamily, text=bankred, align=center] at (0,1.55)
|
||||
{boundary conformance verified in CI (ArchUnit, Spring Modulith, Packwerk)};
|
||||
\end{tikzpicture}%
|
||||
}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\small The boundaries are \textbf{not a diagram convention but a CI subject} -- violations fail the build.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{MM -- the problem it solves}
|
||||
\footnotesize
|
||||
The failure mode every successful layered system eventually demonstrates: \textbf{growth without boundaries} -- features smear across the layers, and the system decays into the big ball of mud.
|
||||
|
||||
\vspace{0.1cm}
|
||||
The fashionable 2010s escape was to \emph{distribute}: let the network enforce the boundaries. But \textbf{distribution charges rent} -- platform staffing, eventual consistency, operational complexity -- even when all the organisation needed was the boundaries.
|
||||
|
||||
\vspace{0.1cm}
|
||||
Hence the precise problem: \emph{how does a team keep monolith economics -- one build, one deployable, one ACID database -- and still get hard, change-absorbing domain boundaries?}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{examplebox}[Shopify -- the canonical modular monolith]
|
||||
\footnotesize One of the largest Rails codebases ($> 2.8$M lines of Ruby); decided deliberately \emph{against} microservices. Since 2017: components with enforced boundaries, checked by the purpose-built tool \textbf{Packwerk}. Scaling: \textbf{sharding whole monolith instances into pods} -- carrying BFCM peaks of $\sim 280$M requests/minute. Both halves in one case: microservices-grade modularity (D7) at monolith-grade cost (D10) -- and the mitigation that lifts D2 from $--$ to $-$.
|
||||
\end{examplebox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{MM -- capability profile (column MM)}
|
||||
\scriptsize
|
||||
\renewcommand{\arraystretch}{0.84}%
|
||||
\vspace{-0.1cm}
|
||||
\begin{center}
|
||||
\begin{tabular}{@{}p{2.9cm}cp{7.8cm}@{}}
|
||||
\toprule
|
||||
\textbf{Dimension} & \textbf{Rating} & \textbf{Structural reason} \\
|
||||
\midrule
|
||||
D1 Read scalability & $\circ$ & same single quantum as L: replication and caching scale reads \\
|
||||
D2 Write scal.\ \& elasticity & $-$ & one database inside one quantum; pod/tenant sharding is the documented mitigation (lifts it from $--$) \\
|
||||
D3 Latency \& predictability & $+$ & in-process calls between modules: no network hop between contexts \\
|
||||
D4 Consistency \& integrity & $++$ & one process, one ACID transaction scope across all modules \\
|
||||
D5 Availability \& isolation & $-$ & single process, single blast radius; replication mitigates \\
|
||||
D6 Security \& auditability & $+$ & one audit log, one compliance scope; module boundaries as policy seams \\
|
||||
D7 Evolvability & $+$ & the domain cut absorbs a typical feature \emph{inside one module} \\
|
||||
D8 Simplicity \& TTM & $+$ & monolith-simple minus one step: boundary governance is a permanent line item \\
|
||||
D9 Testability \& deployability & $+$ & module APIs as natural test seams; module-scoped test selection \\
|
||||
D10 Operating cost & $++$ & one artefact, one process, classical monitoring \\
|
||||
D11 Team scaling & $\circ$ & roughly three to five teams can share one release train \\
|
||||
D12 AI integrability & $+$ & a hard, CI-verifiable module boundary contains the AI subsystem at monolith cost \\
|
||||
\midrule
|
||||
Native shape $S(p)$ & \multicolumn{2}{l}{interactive} \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{MM -- read the profile \emph{against} L}
|
||||
\footnotesize
|
||||
The most instructive reading isolates the effect of the \textbf{partitioning axis} at a constant quantum count:
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{center}
|
||||
\scriptsize
|
||||
\begin{tabular}{@{}lccl@{}}
|
||||
\toprule
|
||||
& \textbf{L} & \textbf{MM} & \\
|
||||
\midrule
|
||||
D4 Consistency & $++$ & $++$ & unchanged -- same single quantum \\
|
||||
D10 Operating cost & $++$ & $++$ & unchanged -- same single quantum \\
|
||||
D7 Evolvability & $-$ & $+$ & \textcolor{bankgreen}{\textbf{domain partitioning buys this}} \\
|
||||
D9 Testability & $-$ & $+$ & \textcolor{bankgreen}{\textbf{domain partitioning buys this}} \\
|
||||
D8 Simplicity & $++$ & $+$ & the price: permanent boundary governance \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\textbf{Architecture conformance becomes a CI subject} -- the declared structure is executable, a failing test rather than a slide:
|
||||
|
||||
\vspace{0.05cm}
|
||||
\begin{tcolorbox}[colback=gray!4!white, colframe=gray!55!black, boxrule=0.6pt, arc=2pt, top=2pt, bottom=2pt, left=6pt, right=6pt]
|
||||
\scriptsize\ttfamily
|
||||
rule "module boundaries hold" \{\\
|
||||
\hspace*{1em}classes in module("portfolio") may only be accessed through its published API;\\
|
||||
\hspace*{1em}no cycles between modules(); domain packages must not depend on framework packages;\\
|
||||
\hspace*{1em}no module accesses tables owned by another module;\\
|
||||
\}
|
||||
\end{tcolorbox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{MM -- software engineering implications}
|
||||
\footnotesize
|
||||
\begin{columns}[T]
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Build and CI/CD}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item still one build -- but the domain cut enables \textbf{module-scoped test selection}: a reporting change runs the reporting tests, not the world
|
||||
\item architecture verification runs on every build -- \emph{the first fitness function most teams ever write}
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\textcolor{bankblue}{\textbf{Test}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item module APIs as test seams; hermetic module tests replace whole-system fixtures
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Deployment and operations}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item identical to the monolith, identically cheap
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\textcolor{bankblue}{\textbf{Maintenance and teams}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item failure mode: \textbf{boundary erosion}; countermeasure: automated verification -- Lehman's second law never sleeps, and code review alone demonstrably does not hold the line
|
||||
\item roughly three to five teams with accepted release coordination; beyond that, the single release train binds and D11 is exhausted
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{MM -- build it and study it}
|
||||
\begin{examplebox}[Build it and study it -- modular monolith]
|
||||
\footnotesize \textbf{Build.} Spring Modulith (Java, Apache-2.0, active): module boundaries as first-class artefacts -- verification tests, recorded event publication, generated module documentation inside one Spring Boot deployable. In Python the same discipline is a linter: \texttt{import-linter} (BSD-2, active) declares layer and independence contracts and fails CI on violation -- \emph{remember it, it returns unchanged for the hexagonal pattern}.
|
||||
|
||||
\textbf{Study.} Apache Fineract ($\sim$2.3k stars, Apache-2.0, active): core banking at industrial scale -- \textbf{34 \texttt{fineract-*} Gradle modules} (\texttt{-loan}, \texttt{-accounting}, \texttt{-savings}, \dots) composed into \emph{one} deployable, plus a \texttt{custom/} extension directory. Runs via docker-compose (JVM, heavy: moderate effort). Smaller first contact: \texttt{sivaprasadreddy/spring-modular-monolith} (Apache-2.0).
|
||||
\end{examplebox}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\footnotesize
|
||||
\textbf{Anti-patterns and alarms:} \emph{boundary erosion without automated verification} (alarms: declared-boundary violations $> 0$ in CI; rising share of features touching $> 2$ modules); \emph{shared database tables across module boundaries} (alarms: foreign keys crossing module schemas; migrations that only pass when several modules deploy together).
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{MM -- selection signals, AI lens, key concept}
|
||||
\footnotesize
|
||||
\textbf{Choose when:} domain known or explorable; organisation $<$ roughly fifty developers; time-to-market \emph{and} long-term evolvability both matter (MonolithFirst). \quad \textbf{Avoid when:} modules have fundamentally different scaling or compliance profiles, or independent deployment is business-critical.
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{ailinse}[The modular monolith as an AI host]
|
||||
\footnotesize D12 $= +$: hosts the deterministic majority of an AI-bearing system at monolith cost, and gives the AI subsystem what L cannot: a \textbf{hard, CI-verifiable module boundary}. Your project's determinism boundary -- \emph{no domain module talks to the LLM gateway except through its declared port} -- is exactly one more rule in the boundary fitness function.
|
||||
\end{ailinse}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize MM dominates L on almost every dimension except day-one simplicity, at the price of \textbf{continuous boundary governance}. The default starting point of modern systems: \emph{domain partitioning now, distribution only when a measured requirement demands it}.
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% HX -- HEXAGONAL
|
||||
% ============================================
|
||||
\section{HX -- Hexagonal Architecture}
|
||||
|
||||
\begin{frame}{HX -- Hexagonal architecture / ports and adapters}
|
||||
\emph{\textcolor{bankblue}{How do you make the domain logic testable in milliseconds when the database, the broker, and an LLM provider all sit at the edges?}}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\small By making ``at the edges'' \textbf{a property the compiler can check}.
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{definitionbox}[Hexagonal architecture / ports and adapters (HX)]
|
||||
\footnotesize A pattern of \textbf{dependency organisation}: the application core interacts with the outside exclusively through technology-neutral interfaces (\emph{ports}) that \emph{the core itself defines}; technology-specific \emph{adapters} plug into them. \textbf{All source-code dependencies point inwards} -- adapters depend on ports, never the reverse.
|
||||
\end{definitionbox}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{hinweisbox}
|
||||
\footnotesize \textbf{Not a distribution style.} Orthogonal to the monolith/microservices axis; \emph{composes} with the other six. Its column is a \textbf{delta}: $\diamond$ inherits the host; its own five cells are what the cut \emph{adds}.
|
||||
\end{hinweisbox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{HX -- topology}
|
||||
\begin{center}
|
||||
\resizebox{0.8\textwidth}{!}{%
|
||||
\begin{tikzpicture}[
|
||||
sysbox/.style={rectangle, draw, rounded corners=4pt, align=center, font=\small\sffamily, line width=0.8pt},
|
||||
drivead/.style={sysbox, fill=bankgreen!15, draw=bankgreen, minimum width=2.6cm, minimum height=0.9cm},
|
||||
drivenad/.style={sysbox, fill=gray!15, draw=gray!60!black, minimum width=2.6cm, minimum height=0.9cm},
|
||||
aiad/.style={sysbox, fill=violet!15, draw=aiviolet, minimum width=2.6cm, minimum height=0.9cm},
|
||||
port/.style={rectangle, draw=bankblue, fill=white, minimum size=0.32cm, inner sep=0pt, line width=0.8pt},
|
||||
arr/.style={-{Stealth[length=2.5mm]}, thick, gray!60!black}
|
||||
]
|
||||
\draw[line width=1pt, draw=bankblue, fill=bankblue!15]
|
||||
(30:2.3) -- (90:2.3) -- (150:2.3) -- (210:2.3) -- (270:2.3) -- (330:2.3) -- cycle;
|
||||
\node[font=\small\sffamily\bfseries, text=bankblue, align=center] at (0,0)
|
||||
{Domain core\\ \footnotesize (knows nothing of\\ \footnotesize the outside world)};
|
||||
\node[port] (p1) at (150:2.3) {};
|
||||
\node[port] (p2) at (210:2.3) {};
|
||||
\node[port] (p3) at (30:2.3) {};
|
||||
\node[port] (p4) at (330:2.3) {};
|
||||
\node[font=\scriptsize\sffamily, text=bankblue, above left=0.05cm of p1] {driving ports};
|
||||
\node[font=\scriptsize\sffamily, text=bankblue, above right=0.05cm of p3] {driven ports};
|
||||
\node[drivead] (rest) at (-5.4,1.4) {REST API\\adapter};
|
||||
\node[drivead] (test) at (-5.4,-1.4) {Test harness\\(fake driver)};
|
||||
\draw[arr] (rest) -- (p1);
|
||||
\draw[arr] (test) -- (p2);
|
||||
\node[drivenad] (db) at (5.4,1.8) {Database\\adapter};
|
||||
\node[drivenad] (mq) at (5.4,0) {Message-broker\\adapter};
|
||||
\node[aiad] (llm) at (5.4,-1.8) {LLM-provider\\adapter};
|
||||
\draw[arr] (p3) -- (db);
|
||||
\draw[arr] (p3) -- (mq);
|
||||
\draw[arr] (p4) -- (llm);
|
||||
\node[font=\footnotesize\sffamily, text=gray!60!black, align=center] at (0,-3.3)
|
||||
{runtime calls flow outwards; source-code dependencies point inwards:\\adapters depend on ports, the core depends on nothing outside itself};
|
||||
\end{tikzpicture}%
|
||||
}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.05cm}
|
||||
\small The \textcolor{aiviolet}{\textbf{LLM-provider adapter}} previews the pattern's role as the \emph{anti-corruption layer} for AI components.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{HX -- the problem it solves}
|
||||
\footnotesize
|
||||
\textbf{The pain that produced the pattern is testability.} Cockburn's 2005 diagnosis: business logic ends up \emph{welded} to its surroundings -- rules leak into UI event handlers on one side and into data-access code on the other, until the only way to check a discount computation is to start the whole application, click through screens, and inspect database rows. Such tests are slow, brittle, expensive -- \emph{and the logic most worth testing is precisely the logic hardest to reach}.
|
||||
|
||||
\vspace{0.2cm}
|
||||
The same weld causes a second, slower problem: \textbf{the system cannot follow its technology}. A new UI generation, a database migration, an additional channel -- each \emph{ought} to be peripheral, but while rules are smeared through UI and persistence code, every peripheral change is open-heart surgery.
|
||||
|
||||
\vspace{0.2cm}
|
||||
Cockburn's response \textbf{inverts the dependency}: the core defines technology-neutral interfaces in its own vocabulary, and every technology -- \emph{the test harness included} -- becomes an interchangeable plug. A fake replaces the database in milliseconds.
|
||||
|
||||
\vspace{0.15cm}
|
||||
\textcolor{codegray}{Standard core-isolation discipline of banking backends; house style of domain-driven design.}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{HX -- capability profile (a delta: $\diamond$ inherits the host)}
|
||||
\scriptsize
|
||||
\renewcommand{\arraystretch}{0.84}%
|
||||
\vspace{-0.1cm}
|
||||
\begin{center}
|
||||
\begin{tabular}{@{}p{2.9cm}cp{7.8cm}@{}}
|
||||
\toprule
|
||||
\textbf{Dimension} & \textbf{Rating} & \textbf{Structural reason} \\
|
||||
\midrule
|
||||
D1 Read scalability & $\diamond$ & inherited from the host pattern \\
|
||||
D2 Write scal.\ \& elasticity & $\diamond$ & inherited \\
|
||||
D3 Latency \& predictability & $\diamond$ & inherited \\
|
||||
D4 Consistency \& integrity & $\diamond$ & inherited \\
|
||||
D5 Availability \& isolation & $\diamond$ & inherited \\
|
||||
D6 Security \& auditability & $+$ & ports are natural audit and policy chokepoints \\
|
||||
D7 Evolvability & $++$ & technology migrations become \textbf{localised adapter tasks} \\
|
||||
D8 Simplicity \& TTM & $-$ & indirection that amortises only under change -- ceremony for pure CRUD \\
|
||||
D9 Testability \& deployability & $++$ & \textbf{hermetic domain tests}: fakes replace infrastructure, feedback in milliseconds \\
|
||||
D10 Operating cost & $\diamond$ & inherited \\
|
||||
D11 Team scaling & $\diamond$ & inherited \\
|
||||
D12 AI integrability & $++$ & an \textbf{imposed anti-corruption boundary} that an ML component cannot erode \\
|
||||
\midrule
|
||||
Native shape $S(p)$ & \multicolumn{2}{l}{(host's)} \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{HX -- the delta cells, measured}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item \textbf{D7 $= ++$ and D9 $= ++$ are the pattern's reason for existing} -- and both are directly measurable: the share of \emph{hermetic} tests rises sharply once domain logic sits behind ports; test feedback for that logic falls to milliseconds. Technology migrations -- database, broker, LLM provider -- become \emph{localised adapter tasks}: A1's cost-of-change criterion applied surgically at the anticipated seams.
|
||||
\item \textbf{The honest cost is D8 $= -$}: for pure CRUD pass-through with no domain logic, ports and adapters are ceremony -- waste, in lean terms.
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{examplebox}[Storage migrations behind a seam -- Discord]
|
||||
\footnotesize Discord's message store migrated \textbf{twice at trillion-row scale} -- MongoDB $\to$ Cassandra $\to$ ScyllaDB, hot paths re-implemented as Rust data services -- cutting p99 reads from 40--125\,ms to $\sim 15$\,ms. Survivable \emph{because} data access sat behind stable interfaces: \textbf{the storage technology churned, the callers did not}. The D7/D9 delta observed in production -- and a preview of why the same discipline turns an LLM-provider deprecation from a crisis into an adapter task.
|
||||
\end{examplebox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{HX -- software engineering implications}
|
||||
\small
|
||||
\begin{itemize}\setlength\itemsep{3pt}
|
||||
\item \textbf{Build and CI/CD:} the hexagon is invisible to the pipeline topology, but adds one gate: \emph{the dependency rule itself is a fitness function} -- ``the domain imports no framework, no vendor SDK'' -- enforceable with the same ArchUnit-class tooling as module boundaries
|
||||
\item \textbf{Test:} the pyramid gains a wide, fast base of hermetic domain tests; each port acquires \textbf{contract tests} that every adapter -- \emph{including every fake} -- must pass, so that fakes cannot drift from reality
|
||||
\item \textbf{Maintenance:} the payoff channel -- volatile peripheries (UIs, providers, AI services) churn in adapters while the core stays still
|
||||
\item \textbf{Teams:} neutral -- but the pattern demands \emph{design skill}: ports must be cut in domain vocabulary, which is a modelling task, not a refactoring
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{HX -- build it and study it}
|
||||
\begin{examplebox}[Build it and study it -- hexagonal]
|
||||
\footnotesize \textbf{Build.} The hexagon is a discipline, not a runtime -- its ``framework'' is a rule checker. ArchUnit (Java, Apache-2.0, active): its \texttt{onionArchitecture()} API encodes the inward-pointing arrows directly. Python: \texttt{import-linter} (BSD-2, active) enforces the same contracts between packages.
|
||||
|
||||
\textbf{Study.} \texttt{cosmicpython/code} ($\sim$2.7k stars): the example application of \emph{Architecture Patterns with Python} (Percival \& Gregory) -- the book's full text is freely readable online, the ideal companion for this module's Python-first audience. Look at \texttt{src/allocation/}: the split into \texttt{domain/}, \texttt{service\_layer/}, \texttt{adapters/}, \texttt{entrypoints/}, and the repository and unit-of-work \emph{ports} with swappable adapters. Runs via docker-compose $+$ pytest. \textbf{Licence caveat, as promised:} the repository is \textbf{CC-BY-ND} -- free to study, \emph{not} free to reuse in derived work.
|
||||
\end{examplebox}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\footnotesize \textbf{Selection signals} -- \textcolor{bankgreen}{\textbf{choose when}} long-lived domain logic meets volatile peripheries (many UIs, exchangeable providers, AI services) and testability is High; \textcolor{bankred}{\textbf{avoid when}} the component is pure CRUD pass-through -- then D8 $= -$ buys nothing, and the indirection never amortises.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{HX -- anti-pattern: hexagonal in name only}
|
||||
\small
|
||||
The folder structure says ports and adapters; the dependencies say otherwise. \textbf{Three measurable symptoms:}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{enumerate}\setlength\itemsep{3pt}
|
||||
\item \textbf{Ports leaking vendor types} -- a port signature mentions a provider SDK class. \emph{Alarm:} static rule ``no vendor or framework types in port signatures'', target zero violations.
|
||||
\item \textbf{Adapters containing business logic} -- decisions made where they cannot be hermetically tested. \emph{Alarm:} the share of hermetic tests \emph{stagnates} after the supposed hexagonal refactoring (if the cut were real, it would rise).
|
||||
\item \textbf{The anaemic domain behind perfect ports} -- all logic in application services, the core reduced to data bags. \emph{Alarm:} core modules with high afferent coupling but near-zero cyclomatic complexity (almost no decision logic inside).
|
||||
\end{enumerate}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{HX -- AI lens and key concept}
|
||||
\begin{ailinse}[The anti-corruption layer for AI components]
|
||||
\footnotesize D12 $= ++$ -- \textbf{the strongest cell in the D12 row}. ML components resist modularisation: ``changing anything changes everything'' (CACE), and they \emph{erode} abstraction boundaries unless a boundary is \textbf{imposed} on them. The port is that imposed boundary -- an \emph{anti-corruption layer} in the DDD sense. An LLM behind a port is \textbf{swappable} when the provider deprecates the model, \textbf{mockable} in every test, and \textbf{replaceable by a deterministic fake} -- so the deterministic $95\,\%$ of the system can be tested deterministically.
|
||||
\end{ailinse}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize HX is not a competitor of the other six patterns but a \textbf{discipline inside them}. Its profile is a delta: $++$ on evolvability, testability, and AI integrability, bought with $-$ on day-one simplicity. It purchases \textbf{options on change} -- and, like all options, it is worth exactly nothing where change never comes.
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% CLOSING
|
||||
% ============================================
|
||||
\section{The Three Side by Side}
|
||||
|
||||
\begin{frame}{The three side by side}
|
||||
\footnotesize
|
||||
\begin{center}
|
||||
\footnotesize
|
||||
\begin{tabular}{@{}lccc@{}}
|
||||
\toprule
|
||||
& \textbf{L} & \textbf{MM} & \textbf{HX (delta)} \\
|
||||
\midrule
|
||||
D4 Consistency & $++$ & $++$ & $\diamond$ \\
|
||||
D7 Evolvability & $-$ & $+$ & $++$ \\
|
||||
D8 Simplicity \& TTM & $++$ & $+$ & $-$ \\
|
||||
D9 Testability & $-$ & $+$ & $++$ \\
|
||||
D10 Operating cost & $++$ & $++$ & $\diamond$ \\
|
||||
D12 AI integrability & $\circ$ & $+$ & $++$ \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.25cm}
|
||||
Three readings:
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item L $\to$ MM isolates the \textbf{partitioning axis}: same quantum, same cost -- evolvability and testability bought by the \emph{domain cut}, not by distribution
|
||||
\item HX \textbf{composes}: a hexagonal modular monolith takes MM's column and lifts D7/D9/D12 towards $++$
|
||||
\item exactly this composition won the mini-match for C10 last week -- \textbf{your project architecture}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{This week's exercise: architecture study I}
|
||||
\begin{projektbox}
|
||||
\small
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item \textbf{Inspect} Apache Fineract (34 modules, one deployable) and \texttt{cosmicpython/code} (\texttt{domain/}, \texttt{service\_layer/}, \texttt{adapters/}, \texttt{entrypoints/}) -- find the boundaries, find the ports
|
||||
\item \textbf{Shortlist candidates for the platform core}: which of L / MM / MM$+$HX carries your requirements profile from A1?
|
||||
\item \textbf{Draw the C4 context and container diagrams} of your platform draft
|
||||
\end{itemize}
|
||||
\end{projektbox}
|
||||
|
||||
\vspace{0.3cm}
|
||||
\small While you study the repositories, apply the two-minute habit: \textbf{licence and maintenance status first} -- one of this week's study objects carries a no-derivatives licence, and finding that yourself is part of the exercise.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Summary}
|
||||
\small
|
||||
\begin{enumerate}\setlength\itemsep{2pt}
|
||||
\item Part II works \textbf{inductively}: problem $\to$ topology $\to$ twelve-dimension profile $\to$ engineering consequences $\to$ inspectable open source
|
||||
\item \textbf{L}: lowest entry cost in the catalogue ($++$ D4/D8/D10) -- pays on every axis of change and scale; a specific trade, not a defect
|
||||
\item \textbf{MM}: domain partitioning at constant quantum count -- D7/D9 rise from $-$ to $+$ while D4/D10 stay $++$; boundary conformance is a \textbf{CI subject}
|
||||
\item \textbf{HX}: a delta pattern -- $++$ on D7/D9/D12 for any host, at $-$ on D8; the \textbf{anti-corruption layer} for AI components
|
||||
\item Together: the \textbf{hexagonal modular monolith} -- the composition that won the C10 mini-match, and your project's architecture
|
||||
\end{enumerate}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Next week}
|
||||
\begin{columns}[T]
|
||||
\begin{column}{0.55\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Lecture 5 -- Patterns II}}
|
||||
\begin{itemize}\small
|
||||
\item \textbf{Microservices}: quanta, sagas vs.\ ACID, the operating premium
|
||||
\item \textbf{Event-driven architecture}: brokers, resilience patterns, eventual consistency
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\begin{column}{0.42\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Reading}}
|
||||
\begin{itemize}\small
|
||||
\item this week: Part II, sections L / MM / HX
|
||||
\item ahead: Part II, sections MS / EDA
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\textcolor{bankblue}{\textbf{Exercise}}
|
||||
\begin{itemize}\small
|
||||
\item architecture study I; C4 drafts
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% END
|
||||
% ============================================
|
||||
\FHGRClosingPage[][{\color{white}\parbox{0.9\paperwidth}{\centering Thank you!\\[3ex]
|
||||
{\normalsize\mdseries Dr.\ Florian Herzog\\[0.9ex]
|
||||
Fachhochschule Graub\"unden, Chur\\[2.4ex]
|
||||
{\small AISE502 -- AI in Software Engineering II}}}}]
|
||||
|
||||
\end{document}
|
||||
BIN
Folien/AISE502_Vorlesung_5_Folien.pdf
Normal file
650
Folien/AISE502_Vorlesung_5_Folien.tex
Normal file
@ -0,0 +1,650 @@
|
||||
% !TEX encoding = UTF-8 Unicode
|
||||
% ============================================================================
|
||||
% AISE502 -- AI in Software Engineering II
|
||||
% Lecture 5 slides, typeset with the official FHGR beamer theme
|
||||
% (beamerthemeFHGR.sty, University of Applied Sciences of the Grisons).
|
||||
% Slide content is unchanged; only the presentation layer is the FHGR template.
|
||||
% ============================================================================
|
||||
\documentclass[aspectratio=169]{beamer}
|
||||
|
||||
\usetheme[showsection, titlebg=pics/theme_pics/titlepage.png]{FHGR}
|
||||
|
||||
% ============================================
|
||||
% PACKAGES
|
||||
% The theme already loads tikz, graphicx, xcolor, tabularx, colortbl,
|
||||
% listings, hyperref, environ and xparse -- only the extras are needed here.
|
||||
% ============================================
|
||||
\usepackage[british]{babel}
|
||||
\usepackage{booktabs}
|
||||
\usepackage{amsmath}
|
||||
\usepackage{amssymb}
|
||||
\usepackage{tcolorbox}
|
||||
\usetikzlibrary{shapes.geometric, arrows.meta, positioning, fit, backgrounds, calc}
|
||||
|
||||
% ============================================
|
||||
% SEMANTIC COLOURS, MAPPED ONTO THE FHGR PALETTE
|
||||
% The names used throughout the slides are kept, so no slide text changes;
|
||||
% they now resolve to the FHGR brand colours defined by the theme.
|
||||
% ============================================
|
||||
\colorlet{bankblue}{blue} % FHGR blue (4B92A4)
|
||||
\colorlet{bankgreen}{green} % FHGR green (817E65)
|
||||
\colorlet{bankred}{red} % FHGR red (C60219)
|
||||
\colorlet{codegray}{gray} % FHGR gray (595959)
|
||||
\colorlet{backcolour}{linen} % FHGR linen (E1D3B5)
|
||||
\definecolor{aiviolet}{HTML}{6B4E71} % muted plum, kept distinct for the AI lens
|
||||
|
||||
% Attribution labels in English (theme default is German)
|
||||
\renewcommand{\source}[1]{\par\hfill {\tiny\color{FHGRDeco} Source:\,\itshape #1}}
|
||||
\renewcommand{\imagesource}[1]{\par\hfill {\tiny\color{FHGRDeco} Image source:\,\itshape #1}}
|
||||
|
||||
% ============================================
|
||||
% CUSTOM TCOLORBOXES (same semantics as the script, FHGR colours)
|
||||
% ============================================
|
||||
\newtcolorbox{keypoint}{
|
||||
colback=bankblue!7!white,
|
||||
colframe=bankblue,
|
||||
title=Key Concept,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{examplebox}[1][]{
|
||||
colback=bankgreen!10!white,
|
||||
colframe=bankgreen,
|
||||
title={Example: #1},
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{definitionbox}[1][]{
|
||||
colback=linen!40!white,
|
||||
colframe=camel!85!black,
|
||||
title={Definition: #1},
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{thinkbox}{
|
||||
colback=lightGray!35!white,
|
||||
colframe=darkGray,
|
||||
title=Discussion,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{hinweisbox}{
|
||||
colback=bankred!5!white,
|
||||
colframe=bankred,
|
||||
title=Important Note,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{ailinse}[1][]{
|
||||
colback=aiviolet!7!white,
|
||||
colframe=aiviolet,
|
||||
title={AI Lens: #1},
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{projektbox}{
|
||||
colback=bankblue!4!white,
|
||||
colframe=bankblue!70!black,
|
||||
title=Project Link: Portfolio Intelligence Platform,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
% ============================================
|
||||
% TITLE METADATA
|
||||
% ============================================
|
||||
\title[AI in Software Engineering II]{AISE502: AI in Software Engineering II}
|
||||
\subtitle{Lecture 5: Patterns II -- Microservices and Event-Driven Architecture\\[0.4ex]{\small Script: Part II, Sections MS / EDA}}
|
||||
\author{Dr.\ Florian Herzog}
|
||||
\shortname{AISE502}
|
||||
\fullname{Fachhochschule Graub\"unden, Chur -- Autumn Semester 2026}
|
||||
|
||||
\begin{document}
|
||||
|
||||
% ============================================
|
||||
% TITLE SLIDE
|
||||
% ============================================
|
||||
\FHGRTitlePage
|
||||
|
||||
% ============================================
|
||||
% AGENDA
|
||||
% ============================================
|
||||
\begin{frame}{Agenda}
|
||||
\small
|
||||
\begin{enumerate}\setlength\itemsep{1pt}
|
||||
\item Recap: one quantum, three cuts -- today: many quanta
|
||||
\item \textbf{MS} -- Microservices: what buys team independence, and what it costs
|
||||
\item Sagas vs.\ ACID: why compensation is not rollback
|
||||
\item \textbf{EDA} -- Event-driven architecture: what an intermediary gives and takes
|
||||
\item Resilience primitives for distributed edges
|
||||
\item This week's exercise: architecture study II
|
||||
\end{enumerate}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% RECAP
|
||||
% ============================================
|
||||
\section{Recap}
|
||||
|
||||
\begin{frame}{Recap: where we are in the catalogue}
|
||||
\footnotesize
|
||||
Last week -- three patterns, all \textbf{single-quantum}:
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item \textbf{L}: technical layers -- cheapest entry, pays on every change axis
|
||||
\item \textbf{MM}: the \emph{domain} cut at constant quantum count -- D7/D9 rise from $-$ to $+$
|
||||
\item \textbf{HX}: a delta discipline -- $++$ on D7/D9/D12 for any host
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\textbf{Today: the distributed half of the catalogue.} Both patterns multiply quanta, both buy their strengths with the same currency -- and both carry $--$ on D8:
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item \textbf{MS} distributes \emph{by domain}: one quantum per business capability
|
||||
\item \textbf{EDA} decouples \emph{in time}: an intermediary between producers and consumers
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize Keep last week's lens: every $++$ and $--$ below traces to a \textbf{tactic} the topology bundles or impedes -- and to the \textbf{quantum boundaries} in the figures.
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% MS -- MICROSERVICES
|
||||
% ============================================
|
||||
\section{MS -- Microservices}
|
||||
|
||||
\begin{frame}{MS -- Microservices}
|
||||
\emph{\textcolor{bankblue}{Thirty teams share one release train and step on each other with every deployment: what buys their independence -- and what does it cost?}}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\small This section derives both halves of the answer -- \textbf{and the cost half is the longer one.}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{definitionbox}[Microservices (MS)]
|
||||
\footnotesize A macro-structure of \textbf{independently deployable services}, each modelled around one business capability, each owning its persistent data exclusively (\emph{database per service}), communicating via lightweight protocols. \textbf{Every service is its own architecture quantum}: its own unit of deployment, scaling, and failure.
|
||||
\end{definitionbox}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\footnotesize In the taxonomy: \textbf{domain partitioning, many quanta} -- the highest aggregate star score of all styles, and one star on overall cost and simplicity. Newman's one-sentence definition names the two load-bearing properties: \emph{``independently deployable services modelled around a business domain.''}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{MS -- topology}
|
||||
\begin{center}
|
||||
\resizebox{0.82\textwidth}{!}{%
|
||||
\begin{tikzpicture}[
|
||||
sysbox/.style={rectangle, draw, rounded corners=4pt, align=center, font=\small\sffamily, line width=0.8pt},
|
||||
gateway/.style={sysbox, fill=bankblue!20, draw=bankblue, minimum width=4.6cm, minimum height=0.95cm, font=\small\sffamily\bfseries},
|
||||
svc/.style={sysbox, fill=bankgreen!15, draw=bankgreen, minimum width=2.9cm, minimum height=1.0cm},
|
||||
data/.style={sysbox, fill=gray!15, draw=gray!60!black, minimum width=2.9cm, minimum height=0.75cm, font=\footnotesize\sffamily},
|
||||
arr/.style={-{Stealth[length=2.5mm]}, thick, gray!60!black},
|
||||
saga/.style={-{Stealth[length=2.5mm]}, thick, bankred, dashed}
|
||||
]
|
||||
\node[gateway] (gw) at (0,2.6) {API gateway};
|
||||
\node[svc] (s1) at (-4.2,0.6) {Catalogue\\service};
|
||||
\node[svc] (s2) at (0,0.6) {Order\\service};
|
||||
\node[svc] (s3) at (4.2,0.6) {Payment\\service};
|
||||
\node[data, below=0.45cm of s1] (db1) {own database};
|
||||
\node[data, below=0.45cm of s2] (db2) {own database};
|
||||
\node[data, below=0.45cm of s3] (db3) {own database};
|
||||
\draw[arr] (gw) -- (s1);
|
||||
\draw[arr] (gw) -- (s2);
|
||||
\draw[arr] (gw) -- (s3);
|
||||
\draw[arr] (s1) -- (db1);
|
||||
\draw[arr] (s2) -- (db2);
|
||||
\draw[arr] (s3) -- (db3);
|
||||
\draw[saga] (s2) -- node[above, font=\footnotesize\sffamily, text=bankred] {saga, no ACID} (s3);
|
||||
\draw[dashed, gray!60!black, rounded corners=5pt] (-5.85,1.25) rectangle (-2.55,-1.75);
|
||||
\draw[dashed, gray!60!black, rounded corners=5pt] (-1.65,1.25) rectangle (1.65,-1.75);
|
||||
\draw[dashed, gray!60!black, rounded corners=5pt] (2.55,1.25) rectangle (5.85,-1.75);
|
||||
\node[font=\footnotesize\sffamily, text=gray!60!black, align=center] at (0,-2.3)
|
||||
{one quantum per service: own pipeline, own release, own blast radius, own database};
|
||||
\end{tikzpicture}%
|
||||
}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\small Cross-service consistency is bought with \textcolor{bankred}{\textbf{sagas instead of ACID transactions}} -- the structural reason for D4 $= --$.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{MS -- the problem it solves}
|
||||
\footnotesize
|
||||
\textbf{Organisational before technical.} By the mid-2000s, Amazon and Netflix had hundreds of teams contributing to shared deployables -- and a shared deployable means a shared \textbf{release train}: every team's change waits on every other team's; integration scope grows with the \emph{organisation}, not the change; one team's defect rolls back everyone's release. Past a certain size, \emph{the queue for the release train} -- not compute, not traffic -- binds how fast the company ships.
|
||||
|
||||
\vspace{0.1cm}
|
||||
The answer: \textbf{make the team's unit of ownership the system's unit of deployment.} Cut along business capabilities, give each service exclusive data ownership and its own pipeline -- ``you build it, you run it.''
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item strongest empirical support is organisational: in high performers, \textbf{deployment frequency scales linearly with team count} instead of collapsing under coordination (DORA)
|
||||
\item the documented \emph{upper} bound: Uber, at $\sim 2{,}200$ critical services, re-introduced a second structuring level -- $\sim 70$ domains with gateways (DOMA) -- a convergence back towards macro-modules
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{MS -- capability profile (column MS)}
|
||||
\scriptsize
|
||||
\renewcommand{\arraystretch}{0.84}%
|
||||
\vspace{-0.1cm}
|
||||
\begin{center}
|
||||
\begin{tabular}{@{}p{2.9cm}cp{7.8cm}@{}}
|
||||
\toprule
|
||||
\textbf{Dimension} & \textbf{Rating} & \textbf{Structural reason} \\
|
||||
\midrule
|
||||
D1 Read scalability & $++$ & independently replicated, cacheable read paths per service \\
|
||||
D2 Write scal.\ \& elasticity & $++$ & per-service horizontal scaling; fine-grained provisioning \\
|
||||
D3 Latency \& predictability & $-$ & network hops, serialisation, tail amplification along synchronous chains \\
|
||||
D4 Consistency \& integrity & $--$ & database-per-service: no ACID across a boundary \\
|
||||
D5 Availability \& isolation & $++$ & bulkheads: one failing service is not a failing product \\
|
||||
D6 Security \& auditability & $\circ$ & expanded attack surface, scattered audit trails vs.\ isolation \\
|
||||
D7 Evolvability & $++$ & domain partitioning: a change lands inside one deployable service \\
|
||||
D8 Simplicity \& TTM & $--$ & platform engineering before the first feature -- the premium \\
|
||||
D9 Testability \& deployability & $+$ & per-service excellent; system-level verification shifts towards production \\
|
||||
D10 Operating cost & $--$ & the premium is paid mostly as platform staffing \\
|
||||
D11 Team scaling & $++$ & independent deployability: teams release without queueing \\
|
||||
D12 AI integrability & $\circ$ & isolation helps, but synchronous chains multiply LLM latency and failure probability \\
|
||||
\midrule
|
||||
Native shape $S(p)$ & \multicolumn{2}{l}{interactive} \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{MS -- the catalogue's steepest trade, cell by cell}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{3pt}
|
||||
\item \textbf{D11 $= ++$ is the real payoff.} Deployments per developer per day scale \emph{linearly} with team count in high-performing organisations -- teams stop queueing. \textbf{This, not raw traffic, is the requirement that legitimately forces the pattern.}
|
||||
\item \textbf{D4 $= --$ is structural} (the method's negative example from week 3). A cross-service invariant (order $\to$ stock $\to$ ledger) becomes a saga -- and \emph{compensation is not rollback}: a rollback erases an intermediate state as if it never existed; a compensating action cannot, because \textbf{other services have already seen and acted on that state}. Every ``undo'' is a new business operation (cancel, restock, refund) with its own logic, tests, and failure modes. No implementation skill removes this cell -- it can only be \emph{relocated} by cutting boundaries so invariants live inside one service.
|
||||
\item \textbf{D8/D10 $= --$: the premium is staffing.} Self-managed Kubernetes TCO runs roughly $3\times$ managed offerings, dominated by personnel.
|
||||
\item \textbf{D9 $= +$ averages a genuine split}: per-service testing is excellent; \emph{system-level} verification shifts towards production -- consumer-driven contracts, canary releases, progressive delivery.
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{MS -- software engineering implications}
|
||||
\footnotesize
|
||||
Omitting these does not produce a leaner variant of the pattern -- it produces a \textbf{broken} one:
|
||||
|
||||
\vspace{0.05cm}
|
||||
\begin{columns}[T]
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Build, test, deploy}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item one pipeline and one contract-test suite \emph{per service}; \textbf{consumer-driven contracts}; canaries, \textbf{feature flags}, progressive delivery
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Operations, maintenance, teams}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item distributed tracing, per-service SLOs, \textbf{circuit breakers}, \textbf{bulkheads}
|
||||
\item \textbf{cross-cutting change multiplies by service count} -- the Segment mechanism
|
||||
\item stream-aligned teams $+$ a platform team: a \emph{precondition}
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{hinweisbox}
|
||||
\footnotesize \textbf{The distributed monolith} -- services that only build, test, and release together -- combines the costs of both worlds without the payoff. Measurable: \emph{lockstep release ratio}, cross-service change dispersion, synchronised version bumps.
|
||||
\end{hinweisbox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{MS -- Monzo and Segment: the homogeneity condition}
|
||||
\begin{examplebox}[two documented cases bracket the viability conditions]
|
||||
\footnotesize \textbf{Monzo} operates a licensed retail bank on $\sim 2{,}800$ microservices -- viable because the company enforces \textbf{extreme technological homogeneity}: one language (Go), one monorepo, shared infrastructure libraries, central migration automation that upgrades hundreds of services mechanically.
|
||||
|
||||
\vspace{0.1cm}
|
||||
\textbf{Segment} cut its pipeline into $> 140$ services -- one per analytics destination, i.e.\ along \emph{instances of configuration} rather than domain seams -- and publicly reversed course in 2018: one shared-library change required over a hundred deployments; test and operations load crushed a small team.
|
||||
\end{examplebox}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize Read jointly: viability at scale depends on \textbf{where the boundaries run} (Maxim 4) and on paying the platform premium \emph{centrally} -- not on service count.
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{MS -- build it and study it, signals, anti-patterns}
|
||||
\begin{examplebox}[Build it and study it -- microservices]
|
||||
\footnotesize \textbf{Build.} FastAPI (Python, MIT): one small HTTP service with a generated OpenAPI contract per capability; Kubernetes underneath. Java: Spring Cloud (Apache-2.0).
|
||||
|
||||
\textbf{Study.} Google's Online Boutique ($\sim$20.6k stars, Apache-2.0): twelve polyglot services under \texttt{src/}, gRPC contracts in \texttt{protos/}, one deployment per service. Runs on kind/minikube via \texttt{skaffold run}: moderate to hard -- \emph{instructively} so, because the platform effort you feel \textbf{is} D8 $= --$. Alternative: \texttt{dotnet/eShop}. (Sock Shop, cited by older literature, was archived in 2023 -- the maintenance check in action.)
|
||||
\end{examplebox}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\footnotesize
|
||||
\textbf{Anti-patterns:} \emph{entity services} (cut around nouns -- alarm: fan-out per business transaction); \emph{grains of sand} (too small to own an invariant -- alarm: service count outgrowing team count).
|
||||
|
||||
\vspace{0.1cm}
|
||||
\textcolor{bankgreen}{\textbf{Choose when}} many teams must deliver in parallel (D11 \emph{measurably} binding); subdomains have independent scaling/failure/compliance profiles; the organisation can staff a platform. \textcolor{bankred}{\textbf{Avoid when}} the premium exceeds the system's complexity; the domain is not yet stable enough to cut boundaries; or the motivation is fashion.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{MS -- AI lens and key concept}
|
||||
\begin{ailinse}[Microservices and AI: the synchronous-chain trap]
|
||||
\footnotesize D12 $= \circ$, and the ambivalence is precise. Per-service isolation is welcome for a fallible component -- an AI capability can be its own service with its own SLO. But an LLM call inside a \emph{synchronous} service chain multiplies seconds-scale latency and per-hop failure probability -- without constitutive stability patterns this is a \textbf{cascade design}. And token cost per request is a \emph{gateway} concern orthogonal to distribution: splitting a system into services does nothing to measure or cap it.
|
||||
\end{ailinse}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize Microservices are the \textbf{only pattern rated $++$ on team scaling (D11)} -- and everything else in the column is the bill: $--$ on consistency, simplicity, and cost are structural properties of many quanta, not implementation accidents. Adopt for \emph{measured organisational scale}, never for traffic alone -- traffic has cheaper answers.
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% EDA -- EVENT-DRIVEN
|
||||
% ============================================
|
||||
\section{EDA -- Event-Driven Architecture}
|
||||
|
||||
\begin{frame}{EDA -- Event-driven architecture}
|
||||
\emph{\textcolor{bankblue}{Tomorrow a new consumer needs every order event: can you attach it without touching the producer?}}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\small If the answer must be yes, an \textbf{intermediary} has to stand between the two -- and everything in this section follows from what that intermediary gives and takes.
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{definitionbox}[Event-driven architecture (EDA)]
|
||||
\footnotesize A macro-structure of \textbf{asynchronously decoupled} event producers and consumers connected through a messaging substrate. Processing is a reaction to \emph{events} -- immutable records of facts -- rather than a response to synchronous calls; producers and consumers share knowledge of \textbf{event schemas, never of each other}.
|
||||
\end{definitionbox}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\footnotesize Two topologies, and the distinction is load-bearing: the \textbf{broker topology} (decentralised event chains -- maximal scaling, no central workflow control, hard error recovery) and the \textbf{mediator topology} (central orchestrator dispatching via queues -- workflow visibility and recoverability, at the price of coupling and a potential bottleneck).
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{EDA -- the two topologies}
|
||||
\begin{center}
|
||||
\resizebox{0.86\textwidth}{!}{%
|
||||
\begin{tikzpicture}[
|
||||
sysbox/.style={rectangle, draw, rounded corners=4pt, align=center, font=\footnotesize\sffamily, line width=0.8pt},
|
||||
proc/.style={sysbox, fill=bankgreen!15, draw=bankgreen, minimum width=2.0cm, minimum height=0.8cm},
|
||||
med/.style={sysbox, fill=bankblue!20, draw=bankblue, minimum width=2.2cm, minimum height=0.9cm, font=\footnotesize\sffamily\bfseries},
|
||||
broker/.style={sysbox, fill=gray!15, draw=gray!60!black, minimum width=5.6cm, minimum height=0.7cm},
|
||||
queue/.style={sysbox, fill=gray!15, draw=gray!60!black, minimum width=1.7cm, minimum height=0.55cm, font=\scriptsize\sffamily},
|
||||
arr/.style={-{Stealth[length=2.5mm]}, thick, gray!60!black}
|
||||
]
|
||||
\node[proc] (prod) at (-4.2,2.2) {Producer};
|
||||
\node[broker] (bk) at (-4.2,0.7) {event broker (topics)};
|
||||
\node[proc] (c1) at (-5.9,-0.9) {Processor A};
|
||||
\node[proc] (c2) at (-2.5,-0.9) {Processor B};
|
||||
\node[proc] (c3) at (-4.2,-2.4) {Processor C};
|
||||
\draw[arr] (prod) -- node[right, font=\scriptsize\sffamily] {event} (bk);
|
||||
\draw[arr] (bk.south west)+(0.6,0) -- (c1.north);
|
||||
\draw[arr] (bk.south east)+(-0.6,0) -- (c2.north);
|
||||
\draw[arr] (c1.east) -- node[above, font=\scriptsize\sffamily] {derived event} (c3.west |- c1.east) -- (c3.north west);
|
||||
\draw[arr] (c2.south) -- (c3.north east);
|
||||
\node[font=\footnotesize\sffamily\bfseries, text=gray!60!black] at (-4.2,-3.3) {(a) broker topology};
|
||||
\node[proc] (src) at (4.2,2.2) {Initiating event};
|
||||
\node[med] (md) at (4.2,0.7) {Mediator};
|
||||
\node[queue] (q1) at (2.6,-0.7) {queue};
|
||||
\node[queue] (q2) at (5.8,-0.7) {queue};
|
||||
\node[proc] (w1) at (2.6,-2.0) {Processor A};
|
||||
\node[proc] (w2) at (5.8,-2.0) {Processor B};
|
||||
\draw[arr] (src) -- (md);
|
||||
\draw[arr] (md) -- (q1);
|
||||
\draw[arr] (md) -- (q2);
|
||||
\draw[arr] (q1) -- (w1);
|
||||
\draw[arr] (q2) -- (w2);
|
||||
\draw[arr, dashed] (w1.east) to[bend right=25] node[right, font=\scriptsize\sffamily] {status} (md.south);
|
||||
\node[font=\footnotesize\sffamily\bfseries, text=gray!60!black] at (4.2,-3.3) {(b) mediator topology};
|
||||
\end{tikzpicture}%
|
||||
}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.05cm}
|
||||
\footnotesize Four things commonly conflated under ``event-driven'' (Fowler): \textbf{event notification} $\cdot$ \textbf{event-carried state transfer} $\cdot$ \textbf{event sourcing} (the log \emph{is} the system of record -- LMAX: $6$M orders/s on one event-sourced JVM thread) $\cdot$ \textbf{CQRS} (separate write and read models).
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{EDA -- the problem it solves}
|
||||
\footnotesize
|
||||
\textbf{Integration at scale.} Around 2010, LinkedIn's activity data -- page views, profile edits, connections -- was wanted by an ever-growing set of consumers: search indexes, recommenders, metrics warehouses, security monitoring. Point-to-point wiring grows roughly \textbf{quadratically} with the number of systems and breaks with every schema change.
|
||||
|
||||
\vspace{0.1cm}
|
||||
LinkedIn's answer: put \textbf{one durable, partitioned, replayable log} in the middle and let every consumer read at its own pace -- the system that became \textbf{Apache Kafka}.
|
||||
|
||||
\vspace{0.1cm}
|
||||
The general form recurs wherever the consumer set is \emph{open-ended}: the producer of a fact -- an order placed, a sensor fired, a light switched on -- \textbf{cannot know today who will need that fact tomorrow}. Home Assistant faces the domestic version: thousands of device integrations, none depending on any other, coordinated by one event bus.
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{examplebox}[Kafka at LinkedIn; the Uber real-time stack]
|
||||
\footnotesize By 2019, LinkedIn's Kafka carried $> 7$ \emph{trillion} messages per day -- the existence proof for D1/D2 $= ++$. Uber composes Kafka $+$ Flink $+$ Pinot into an end-to-end event-driven stack -- the canonical EDA-plus-pipeline hybrid for the IoT class (C8).
|
||||
\end{examplebox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{EDA -- capability profile (column EDA)}
|
||||
\scriptsize
|
||||
\renewcommand{\arraystretch}{0.84}%
|
||||
\vspace{-0.1cm}
|
||||
\begin{center}
|
||||
\begin{tabular}{@{}p{2.9cm}cp{7.8cm}@{}}
|
||||
\toprule
|
||||
\textbf{Dimension} & \textbf{Rating} & \textbf{Structural reason} \\
|
||||
\midrule
|
||||
D1 Read scalability & $++$ & consumers replicate and cache independently behind the broker \\
|
||||
D2 Write scal.\ \& elasticity & $++$ & partitioned ingest with elastic, decoupled consumers \\
|
||||
D3 Latency \& predictability & $+$ & async throughput excellent; request/response through events is not the mode \\
|
||||
D4 Consistency \& integrity & $--$ & eventual consistency moves correctness into the design \\
|
||||
D5 Availability \& isolation & $++$ & a slow or dead consumer does not stall producers \\
|
||||
D6 Security \& auditability & $\circ$ & durable log supports audit; causal trails need correlation IDs \\
|
||||
D7 Evolvability & $++$ & new consumers attach without touching producers \\
|
||||
D8 Simplicity \& TTM & $--$ & eventuality and broker operations designed and staffed first \\
|
||||
D9 Testability \& deployability & $-$ & non-deterministic event flows resist end-to-end testing \\
|
||||
D10 Operating cost & $\circ$ & few quanta, no premium -- but the broker is a standing cost \\
|
||||
D11 Team scaling & $+$ & teams per processor decouple well; the broker needs an owner \\
|
||||
D12 AI integrability & $++$ & queues absorb LLM latency, limits, outages; log $=$ audit journal \\
|
||||
\midrule
|
||||
Native shape $S(p)$ & \multicolumn{2}{l}{stream / async} \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{EDA -- the same coin, two sides}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{3pt}
|
||||
\item \textbf{D7 $= ++$: the decoupling is threefold.} In \emph{topology} (producers know the event schema, never the audience), in \emph{time} (a consumer may be down, slow, or not yet written when the event is published), and in \emph{organisation} (the team attaching a fraud detector needs no meeting with the team owning the order flow).
|
||||
\item \textbf{D4 $= --$ is the same coin, seen from the other side.} Eventual consistency moves correctness \emph{out of the database and into the design}: read-your-writes anomalies, ordering across partitions, duplicate delivery are all \textbf{design obligations} -- and their testing bill is what keeps D8 at $--$ and D9 at $-$.
|
||||
\item \textbf{D3 $= +$ refines the five stars}: throughput and responsiveness are excellent, but synchronous round trips \emph{through} asynchronous flows are not the pattern's mode.
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize EDA packages ``use an intermediary'' and ``introduce concurrency'' by construction -- and \emph{impedes} ``transactions'' by the same construction. \textbf{No broker product removes the trade.}
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{EDA -- software engineering implications}
|
||||
\footnotesize
|
||||
\begin{columns}[T]
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Build and test}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item the hard artefact is the \textbf{event schema}: schema registry $+$ compatibility rules (backward/forward/full) as pipeline gates; AsyncAPI in OpenAPI's role
|
||||
\item contract tests per event type; consumer replays against recorded streams
|
||||
\item \textbf{idempotency tests}: processing an event twice must equal processing it once -- under deliberate duplicate delivery
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Operations and maintenance}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item the RED metrics of this world: \textbf{consumer lag}, \textbf{dead-letter queues}, duplicate rates
|
||||
\item debugging $=$ \textbf{correlation-ID tracing} across hops -- a core competency, not an advanced topic
|
||||
\item additive evolution is the glory (attach a consumer); \emph{changing} an established schema is the most expensive operation
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{EDA -- build it and study it, anti-patterns}
|
||||
\begin{examplebox}[Build it and study it -- event-driven]
|
||||
\footnotesize \textbf{Build.} Apache Kafka (durable, partitioned, replayable log); RabbitMQ (classic AMQP routing). Python-first layer: FastStream (Apache-2.0) -- FastAPI-style producers/consumers with the broker behind a decorator.
|
||||
|
||||
\textbf{Study.} Home Assistant (\texttt{home-assistant/core}, $\sim$89k stars, Apache-2.0): genuinely event-driven Python -- \texttt{homeassistant/core.py} defines \texttt{Event} and \texttt{EventBus} with \texttt{async\_fire}, and \emph{every} state change flows through that one bus. Runs via \texttt{pip install homeassistant}; the codebase is huge, so \textbf{read exactly that one file} -- the whole pattern is in it.
|
||||
\end{examplebox}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\footnotesize
|
||||
\textbf{Anti-patterns with alarms:} \emph{event soup} (no workflow visibility -- alarm: share of events without correlation IDs; time to reconstruct one causal trail); \emph{events as disguised RPCs} (a producer blocking for a reply event -- synchronous coupling with extra steps); \emph{missing idempotency} (at-least-once $+$ non-idempotent consumers $=$ silent corruption); \emph{event sourcing as default} (the burden of proof lies with the auditability requirement).
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Discussion}
|
||||
\begin{thinkbox}
|
||||
\small D4 $= --$, and yet Part IV will rate EDA the \emph{primary} pattern for three application classes.
|
||||
|
||||
\vspace{0.15cm}
|
||||
Which classes can afford to make correctness \emph{eventual} -- and what, precisely, is the \textbf{response measure} that would tell you your class cannot?
|
||||
|
||||
\vspace{0.15cm}
|
||||
Formulate it as a six-part quality attribute scenario before looking at Part III.
|
||||
\end{thinkbox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{EDA -- AI lens and key concept}
|
||||
\begin{ailinse}[Queues absorb what LLMs are worst at]
|
||||
\footnotesize D12 $= ++$. The three operational pathologies of LLM components -- seconds-scale latency, rate limits, provider outages -- are \textbf{exactly what a queue absorbs}; asynchronous integration is the default for non-interactive AI work. Queues also create natural \emph{batching points}: batch APIs price roughly $50\,\%$ below synchronous calls. And the durable event log \textbf{doubles as the audit journal} that logging obligations for AI systems demand -- every prompt, every response, every agent step, replayable. The one thing EDA does not give: a synchronous answer -- where the user is waiting, the latency budget must be engineered explicitly.
|
||||
\end{ailinse}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize For your project this cell is load-bearing: the \textbf{event-driven edges} around the hexagonal modular monolith carry the AI job spine -- analysis requests queue asynchronously, and the event journal is the audit trail.
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% RESILIENCE PRIMITIVES
|
||||
% ============================================
|
||||
\section{Resilience Primitives}
|
||||
|
||||
\begin{frame}{Resilience primitives for distributed edges}
|
||||
\footnotesize
|
||||
Distribution and asynchrony are bought with \textbf{explicit failure engineering} -- constitutive for MS, standard for EDA edges, and the toolkit of this week's exercise:
|
||||
|
||||
\vspace{0.05cm}
|
||||
\begin{center}
|
||||
\scriptsize
|
||||
\renewcommand{\arraystretch}{0.95}%
|
||||
\begin{tabular}{@{}p{2.6cm}p{5.6cm}p{4.6cm}@{}}
|
||||
\toprule
|
||||
\textbf{Primitive} & \textbf{What it does} & \textbf{Measured by} \\
|
||||
\midrule
|
||||
Timeout & bounds how long a caller waits -- no call may wait forever & timeout rate per dependency \\
|
||||
Retry with backoff & re-attempts transient failures with growing pauses -- safe only on \emph{idempotent} operations & retry rate; success-after-retry \\
|
||||
Circuit breaker & callers stop calling a dependency that keeps failing; probes recovery & breaker state transitions; open time \\
|
||||
Bulkhead & partitions resources so one failing component cannot drain the rest & saturation per pool \\
|
||||
Fallback / degradation & a defined degraded answer beats no answer & share of degraded responses \\
|
||||
Dead-letter queue & parks messages that repeatedly fail processing for inspection & DLQ depth and age \\
|
||||
Idempotent consumer & processing twice $=$ processing once -- makes retries safe & duplicate rate under replay \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.05cm}
|
||||
Each is a \textbf{tactic} in the week-3 sense -- and each becomes a \emph{fitness function} in your measurement contract.
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% CLOSING
|
||||
% ============================================
|
||||
\section{Closing}
|
||||
|
||||
\begin{frame}{MS and EDA side by side}
|
||||
\footnotesize
|
||||
\begin{center}
|
||||
\footnotesize
|
||||
\begin{tabular}{@{}lccl@{}}
|
||||
\toprule
|
||||
& \textbf{MS} & \textbf{EDA} & \\
|
||||
\midrule
|
||||
D4 Consistency & $--$ & $--$ & both trade ACID away -- differently: sagas vs.\ eventuality \\
|
||||
D5 Availability & $++$ & $++$ & bulkheads vs.\ temporal decoupling \\
|
||||
D7 Evolvability & $++$ & $++$ & domain cut vs.\ attach-a-consumer \\
|
||||
D8 Simplicity & $--$ & $--$ & platform premium vs.\ asynchrony bill \\
|
||||
D11 Team scaling & $++$ & $+$ & the release train vs.\ the broker owner \\
|
||||
D12 AI integrability & $\circ$ & $++$ & synchronous chains vs.\ absorbing queues \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item \textbf{MS distributes by domain}; \textbf{EDA decouples in time} -- and they compose: event-driven communication \emph{between} services is the standard hybrid
|
||||
\item both demand the resilience primitives -- and both pay D8 $= --$ \emph{before the first feature ships}
|
||||
\item for your project: neither carries the \emph{core} (the mini-match verdict stands) -- but \textbf{EDA carries the edges}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{This week's exercise: architecture study II}
|
||||
\begin{projektbox}
|
||||
\small
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item \textbf{Design the edges} of your platform: the ingestion queue for analysis requests, and \textbf{resilience against external-API failure} -- timeouts, retries with backoff, circuit breaker, fallback, DLQ on every external call
|
||||
\item \textbf{Sketch the service contracts}: which events exist, which schemas, who produces, who consumes
|
||||
\item \textbf{Matrix pre-filter}: hold your A1 requirements profile against all candidate patterns seen so far -- which survive stage 1 (shape gate) and stage 2 (vetoes)?
|
||||
\end{itemize}
|
||||
\end{projektbox}
|
||||
|
||||
\vspace{0.25cm}
|
||||
\small Next week you will run the \textbf{full three-stage match} and take the architecture decision -- the pre-filter is its preparation.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Summary}
|
||||
\footnotesize
|
||||
\begin{enumerate}\setlength\itemsep{2pt}
|
||||
\item \textbf{MS}: the only $++$ on team scaling -- adopt for \emph{measured organisational scale}, never for traffic; D4 $= --$ is structural (compensation $\neq$ rollback), D8/D10 $= --$ is staffing
|
||||
\item The \textbf{distributed monolith} is the most common failure outcome -- and it is measurable (lockstep release ratio)
|
||||
\item Monzo and Segment bracket the viability conditions: \emph{where the boundaries run} and \emph{central} platform investment -- not service count
|
||||
\item \textbf{EDA}: threefold decoupling (topology, time, organisation) -- and D4/D8/D9 are the same coin's other side; no broker removes the trade
|
||||
\item \textbf{Resilience primitives} (timeout, retry, circuit breaker, bulkhead, fallback, DLQ, idempotency) are constitutive, not hardening -- each one a fitness function
|
||||
\item For the project: MM$+$HX core unchanged; \textbf{EDA takes the edges} -- queues absorb what LLMs are worst at
|
||||
\end{enumerate}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Next week}
|
||||
\begin{columns}[T]
|
||||
\begin{column}{0.55\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Lecture 6 -- Patterns III and your class}}
|
||||
\begin{itemize}\small
|
||||
\item \textbf{Pipes-and-filters} and \textbf{Serverless}
|
||||
\item Stepping back: the quantum, partitioning beats distribution, the consolidated table
|
||||
\item Part III: \textbf{C10 in depth} $+$ the C1/C2 mirror pair
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\begin{column}{0.42\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Reading}}
|
||||
\begin{itemize}\small
|
||||
\item this week: Part II, MS / EDA
|
||||
\item ahead: Part II, PF / SL $+$ closing; Part III, C10
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\textcolor{bankblue}{\textbf{Exercise}}
|
||||
\begin{itemize}\small
|
||||
\item edges, resilience, contracts; matrix pre-filter
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% END
|
||||
% ============================================
|
||||
\FHGRClosingPage[][{\color{white}\parbox{0.9\paperwidth}{\centering Thank you!\\[3ex]
|
||||
{\normalsize\mdseries Dr.\ Florian Herzog\\[0.9ex]
|
||||
Fachhochschule Graub\"unden, Chur\\[2.4ex]
|
||||
{\small AISE502 -- AI in Software Engineering II}}}}]
|
||||
|
||||
\end{document}
|
||||
BIN
Folien/AISE502_Vorlesung_6_Folien.pdf
Normal file
708
Folien/AISE502_Vorlesung_6_Folien.tex
Normal file
@ -0,0 +1,708 @@
|
||||
% !TEX encoding = UTF-8 Unicode
|
||||
% ============================================================================
|
||||
% AISE502 -- AI in Software Engineering II
|
||||
% Lecture 6 slides, typeset with the official FHGR beamer theme
|
||||
% (beamerthemeFHGR.sty, University of Applied Sciences of the Grisons).
|
||||
% Slide content is unchanged; only the presentation layer is the FHGR template.
|
||||
% ============================================================================
|
||||
\documentclass[aspectratio=169]{beamer}
|
||||
|
||||
\usetheme[showsection, titlebg=pics/theme_pics/titlepage.png]{FHGR}
|
||||
|
||||
% ============================================
|
||||
% PACKAGES
|
||||
% The theme already loads tikz, graphicx, xcolor, tabularx, colortbl,
|
||||
% listings, hyperref, environ and xparse -- only the extras are needed here.
|
||||
% ============================================
|
||||
\usepackage[british]{babel}
|
||||
\usepackage{booktabs}
|
||||
\usepackage{amsmath}
|
||||
\usepackage{amssymb}
|
||||
\usepackage{tcolorbox}
|
||||
\usetikzlibrary{shapes.geometric, arrows.meta, positioning, fit, backgrounds, calc}
|
||||
|
||||
% ============================================
|
||||
% SEMANTIC COLOURS, MAPPED ONTO THE FHGR PALETTE
|
||||
% The names used throughout the slides are kept, so no slide text changes;
|
||||
% they now resolve to the FHGR brand colours defined by the theme.
|
||||
% ============================================
|
||||
\colorlet{bankblue}{blue} % FHGR blue (4B92A4)
|
||||
\colorlet{bankgreen}{green} % FHGR green (817E65)
|
||||
\colorlet{bankred}{red} % FHGR red (C60219)
|
||||
\colorlet{codegray}{gray} % FHGR gray (595959)
|
||||
\colorlet{backcolour}{linen} % FHGR linen (E1D3B5)
|
||||
\definecolor{aiviolet}{HTML}{6B4E71} % muted plum, kept distinct for the AI lens
|
||||
|
||||
% Attribution labels in English (theme default is German)
|
||||
\renewcommand{\source}[1]{\par\hfill {\tiny\color{FHGRDeco} Source:\,\itshape #1}}
|
||||
\renewcommand{\imagesource}[1]{\par\hfill {\tiny\color{FHGRDeco} Image source:\,\itshape #1}}
|
||||
|
||||
% ============================================
|
||||
% CUSTOM TCOLORBOXES (same semantics as the script, FHGR colours)
|
||||
% ============================================
|
||||
\newtcolorbox{keypoint}{
|
||||
colback=bankblue!7!white,
|
||||
colframe=bankblue,
|
||||
title=Key Concept,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{examplebox}[1][]{
|
||||
colback=bankgreen!10!white,
|
||||
colframe=bankgreen,
|
||||
title={Example: #1},
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{definitionbox}[1][]{
|
||||
colback=linen!40!white,
|
||||
colframe=camel!85!black,
|
||||
title={Definition: #1},
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{thinkbox}{
|
||||
colback=lightGray!35!white,
|
||||
colframe=darkGray,
|
||||
title=Discussion,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{hinweisbox}{
|
||||
colback=bankred!5!white,
|
||||
colframe=bankred,
|
||||
title=Important Note,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{ailinse}[1][]{
|
||||
colback=aiviolet!7!white,
|
||||
colframe=aiviolet,
|
||||
title={AI Lens: #1},
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{projektbox}{
|
||||
colback=bankblue!4!white,
|
||||
colframe=bankblue!70!black,
|
||||
title=Project Link: Portfolio Intelligence Platform,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
% ============================================
|
||||
% TITLE METADATA
|
||||
% ============================================
|
||||
\title[AI in Software Engineering II]{AISE502: AI in Software Engineering II}
|
||||
\subtitle{Lecture 6: Pipelines, Serverless, the View Across -- and Your Class (C10)\\[0.4ex]{\small Script: Part II, Sections PF / SL $+$ closing; Part III, Section C10}}
|
||||
\author{Dr.\ Florian Herzog}
|
||||
\shortname{AISE502}
|
||||
\fullname{Fachhochschule Graub\"unden, Chur -- Autumn Semester 2026}
|
||||
|
||||
\begin{document}
|
||||
|
||||
% ============================================
|
||||
% TITLE SLIDE
|
||||
% ============================================
|
||||
\FHGRTitlePage
|
||||
|
||||
% ============================================
|
||||
% AGENDA
|
||||
% ============================================
|
||||
\begin{frame}{Agenda}
|
||||
\small
|
||||
\begin{enumerate}\setlength\itemsep{1pt}
|
||||
\item \textbf{PF} -- Pipes-and-filters: the throughput pattern
|
||||
\item \textbf{SL} -- Serverless: pay per execution, own no capacity
|
||||
\item Stepping back: the quantum, partitioning beats distribution
|
||||
\item The consolidated capability table -- all seven, side by side
|
||||
\item Outlook: agent orchestration as a composition pattern
|
||||
\item Part III opens: \textbf{C10 in depth} -- the class of your project
|
||||
\item The C1/C2 mirror pair
|
||||
\item This week's exercise: \textbf{the match}
|
||||
\end{enumerate}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% PF
|
||||
% ============================================
|
||||
\section{PF -- Pipes-and-Filters}
|
||||
|
||||
\begin{frame}{PF -- Pipes-and-filters / batch pipeline}
|
||||
\emph{\textcolor{bankblue}{The nightly risk run must process millions of rows, reproducibly, by 06:00: what structure is born for exactly that?}}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\small This one -- the \textbf{oldest pattern in the catalogue}, and the one most precisely matched to its workload shape.
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{definitionbox}[Pipes-and-filters / batch pipeline (PF)]
|
||||
\footnotesize A macro-structure of independent, composable transformation steps (\emph{filters}) connected by unidirectional data conduits (\emph{pipes}) into a chain or directed acyclic graph (DAG). Each filter is self-contained -- ideally \textbf{stateless and idempotent} -- and knows only its own data contracts, never its neighbours; the composition logic is explicit and \emph{external} to the filters.
|
||||
\end{definitionbox}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\footnotesize Historical root: the Unix pipe. Modern incarnations dominate the data world: ETL/ELT, DAG orchestration (Airflow), data-parallel engines (Spark), HPC job chains (Slurm), streaming pipelines (Flink -- the bridge to EDA), and \textbf{ML and retrieval pipelines} -- the current incarnation.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{PF -- topology and the problem it solves}
|
||||
\begin{center}
|
||||
\resizebox{0.8\textwidth}{!}{%
|
||||
\begin{tikzpicture}[
|
||||
sysbox/.style={rectangle, draw, rounded corners=4pt, align=center, font=\footnotesize\sffamily, line width=0.8pt},
|
||||
filter/.style={sysbox, fill=bankgreen!15, draw=bankgreen, minimum width=2.0cm, minimum height=0.9cm},
|
||||
extern/.style={sysbox, fill=gray!15, draw=gray!60!black, minimum width=2.0cm, minimum height=0.9cm},
|
||||
arr/.style={-{Stealth[length=2.5mm]}, thick, gray!60!black}
|
||||
]
|
||||
\node[extern] (src) at (-5.6,0) {Source\\(producer)};
|
||||
\node[filter] (f1) at (-2.9,0) {Filter 1\\(transform)};
|
||||
\node[filter] (f2a) at (0,1.1) {Filter 2a\\(transform)};
|
||||
\node[filter] (f2b) at (0,-1.1) {Filter 2b\\(transform)};
|
||||
\node[filter] (f3) at (2.9,0) {Filter 3\\(merge/test)};
|
||||
\node[extern] (sink) at (5.7,0) {Output store\\(consumer)};
|
||||
\draw[arr] (src) -- node[above, font=\scriptsize\sffamily] {pipe} (f1);
|
||||
\draw[arr] (f1) -- (f2a);
|
||||
\draw[arr] (f1) -- (f2b);
|
||||
\draw[arr] (f2a) -- (f3);
|
||||
\draw[arr] (f2b) -- (f3);
|
||||
\draw[arr] (f3) -- node[above, font=\scriptsize\sffamily] {pipe} (sink);
|
||||
\node[font=\footnotesize\sffamily, text=gray!60!black, align=center] at (0,-2.3)
|
||||
{every pipe is a versioned data contract; every filter is stateless, idempotent,\\and independently testable against golden datasets};
|
||||
\end{tikzpicture}%
|
||||
}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.05cm}
|
||||
\footnotesize \textbf{The problem is the oldest workload in commercial computing:} when the business day closes, the day's records must be collected, validated, transformed, aggregated -- reliably, repeatably, \emph{before the next day begins}. Payroll, end-of-day processing, warehouse loads, overnight risk runs: a finite body of data flows through fixed transformations, and nobody waits interactively. What matters: the run finishes \textbf{inside its window}, and the same inputs \textbf{provably produce the same outputs}.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{PF -- capability profile (column PF)}
|
||||
\scriptsize
|
||||
\renewcommand{\arraystretch}{0.8}%
|
||||
\vspace{-0.35cm}
|
||||
\begin{center}
|
||||
\begin{tabular}{@{}p{2.9cm}cp{7.8cm}@{}}
|
||||
\toprule
|
||||
\textbf{Dimension} & \textbf{Rating} & \textbf{Structural reason} \\
|
||||
\midrule
|
||||
D1 Read scalability & $\circ$ & the pipeline does not serve reads; precomputation \emph{delegates} to the output store \\
|
||||
D2 Write scal.\ \& elasticity & $+$ & data-parallel frameworks are the standard operating mode \\
|
||||
D3 Latency \& predictability & $--$ & answers arrive in makespans, not milliseconds -- by design \\
|
||||
D4 Consistency \& integrity & $+$ & immutable inputs $+$ idempotent stages: \emph{reproducibility}, ``as of last run'' \\
|
||||
D5 Availability \& isolation & $-$ & a failed stage stalls the run; recovery is re-execution \\
|
||||
D6 Security \& auditability & $+$ & versioned inputs, deterministic reruns: audit trail on demand \\
|
||||
D7 Evolvability & $+$ & filters individually replaceable behind explicit data contracts \\
|
||||
D8 Simplicity \& TTM & $++$ & explicit composition over self-contained filters -- shipping this week \\
|
||||
D9 Testability \& deployability & $+$ & golden datasets per filter; bit-level assertions \\
|
||||
D10 Operating cost & $++$ & compute in schedulable bursts, near-zero platform staff \\
|
||||
D11 Team scaling & $\circ$ & DAG/filter ownership parallelises data teams moderately \\
|
||||
D12 AI integrability & $++$ & ingestion, training, evals \emph{are} pipes-and-filters; non-determinism localised \\
|
||||
\midrule
|
||||
Native shape $S(p)$ & \multicolumn{2}{l}{scheduled batch} \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{PF -- the cells with a story}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item \textbf{D3 $= --$ is not a defect but the definition}: the pattern optimises \emph{makespan} (first filter starts $\to$ last finishes) and batch-window adherence, and delegates interactive serving to the stores it fills. The streaming incarnation escapes the cell.
|
||||
\item \textbf{D4 $= +$ is the subtlest cell in the table}: not ACID -- immutable inputs plus deterministic, \emph{idempotent} stages give \textbf{reproducibility}, a \emph{third} consistency semantics beside ACID and eventual (``as of last run''). For scientific and regulatory workloads, the one that matters.
|
||||
\item \textbf{The most deterministically testable pattern in the catalogue} -- as long as no AI filter sits inside.
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{examplebox}[a Monte-Carlo risk run -- reproducibility by construction]
|
||||
\footnotesize Immutable market-data snapshots and versioned parameters enter; embarrassingly parallel simulation stages fan out; deterministic aggregation produces versioned risk figures. Fixed seeds $+$ versioned inputs make the run \textbf{bit-level reproducible} -- not a nicety but a regulatory duty for risk models: ``the same inputs produce the same books, provably, on demand.''
|
||||
\end{examplebox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{PF -- engineering, build it and study it}
|
||||
\footnotesize
|
||||
\textbf{Engineering:} the pipeline versions \emph{three} things -- code, data, schemas; \textbf{backfills} (re-running history through changed logic) are their own deployment class with their own runbook. Test with \textbf{golden datasets} per filter. The on-call page: ``the 02:00 run missed its window'' -- standing measures: makespan trend, window adherence. Coupling risk hides in the \emph{pipes} (implicit schemas).
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{examplebox}[Build it and study it -- pipes-and-filters]
|
||||
\footnotesize \textbf{Build.} Apache Airflow (DAG-as-code; read its shipped example DAGs first). dbt Core: each filter as one SQL model. Dagster as an active alternative.
|
||||
|
||||
\textbf{Study.} \texttt{dbt-labs/jaffle\_shop\_duckdb} (Apache-2.0): every \texttt{.sql} model under \texttt{models/} is a filter, \texttt{ref()} wires the pipes, \texttt{dbt build} materialises the DAG. Runs fully locally on DuckDB: \emph{very easy}. (Status check again: the classic \texttt{jaffle\_shop} was archived in 2024; its successor ships \emph{no licence file} -- use the DuckDB variant.)
|
||||
\end{examplebox}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\textbf{Anti-patterns:} \emph{stateful filters with side effects} (alarm: non-zero \textbf{rerun-diff rate}); \emph{pipeline sprawl} (DAGs without owners or version control); \emph{implicit schema coupling} (alarm: downstream breakage per upstream schema change).
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{PF -- AI lens and key concept}
|
||||
\begin{ailinse}[Pipelines are where AI work naturally lives]
|
||||
\footnotesize D12 $= ++$. The AI-adjacent workloads are pipes-and-filters \emph{by construction}: retrieval ingestion (documents $\to$ chunking $\to$ embedding $\to$ index), model training and batch inference, and \textbf{the eval harness itself} -- a versioned pipeline from golden set to statistical verdict. One precise change when an AI filter enters a deterministic chain: \emph{that stage's} test regime switches from golden-dataset equality to \textbf{statistical acceptance thresholds} (pass rates, score distributions) -- the rest keeps its deterministic tests. \textbf{Few structures contain AI more cheaply.}
|
||||
\end{ailinse}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize PF is the most deterministically testable pattern in the catalogue and the natural home of batch, data, and ML workloads. Its $--$ latency cell is its \emph{definition}: makespan and reproducibility, with interactive serving delegated to the stores it fills.
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% SL
|
||||
% ============================================
|
||||
\section{SL -- Serverless / FaaS}
|
||||
|
||||
\begin{frame}{SL -- Serverless / Function-as-a-Service}
|
||||
\emph{\textcolor{bankblue}{Your load is zero at night and spikes at noon: why pay for idle servers at 03:00?}}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\small The serverless answer is radical -- \textbf{pay per execution, own no capacity} -- and the whole profile is the fine print of that offer.
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{definitionbox}[Serverless / FaaS (SL)]
|
||||
\footnotesize A macro-structure of \textbf{event-triggered, short-lived, stateless functions} on a managed platform that provides provisioning, elastic scaling \emph{from zero} to massive parallelism, and per-execution billing. State lives outside the functions, in managed backing services; \textbf{the function is simultaneously the unit of code, of deployment, of scaling, and of cost}.
|
||||
\end{definitionbox}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\footnotesize The scientific reference point is the Berkeley view: it predicted the dominance of simplified cloud programming \emph{while cataloguing the structural limits with unusual precision} -- cold starts, enforced statelessness, communication through storage, vendor lock-in. FaaS (your code, event-triggered) vs.\ BaaS (API-consumed third-party services).
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{SL -- topology}
|
||||
\begin{center}
|
||||
\resizebox{0.8\textwidth}{!}{%
|
||||
\begin{tikzpicture}[
|
||||
sysbox/.style={rectangle, draw, rounded corners=4pt, align=center, font=\footnotesize\sffamily, line width=0.8pt},
|
||||
evt/.style={sysbox, fill=bankgreen!15, draw=bankgreen, minimum width=2.2cm, minimum height=0.8cm},
|
||||
fn/.style={sysbox, fill=bankblue!20, draw=bankblue, minimum width=2.6cm, minimum height=0.85cm},
|
||||
mgd/.style={sysbox, fill=gray!15, draw=gray!60!black, minimum width=2.4cm, minimum height=0.8cm},
|
||||
arr/.style={-{Stealth[length=2.5mm]}, thick, gray!60!black}
|
||||
]
|
||||
\node[evt] (http) at (-5.6,1.6) {HTTP request};
|
||||
\node[evt] (q) at (-5.6,0) {queue event};
|
||||
\node[evt] (sched) at (-5.6,-1.6) {schedule};
|
||||
\draw[dashed, gray!60!black, rounded corners=6pt] (-2.6,2.6) rectangle (2.6,-2.6);
|
||||
\node[font=\footnotesize\sffamily, text=gray!60!black] at (0,2.25) {managed FaaS platform};
|
||||
\node[fn] (f1) at (0,1.2) {Function A\\ \scriptsize $0 \dots n$ instances};
|
||||
\node[fn] (f2) at (0,-0.3) {Function B\\ \scriptsize $0 \dots n$ instances};
|
||||
\node[font=\scriptsize\sffamily, text=bankred, align=center] at (0,-1.75)
|
||||
{scale-to-zero $\leftrightarrow$ burst parallelism\\per-invocation billing; cold starts};
|
||||
\node[mgd] (obj) at (5.4,1.6) {object storage};
|
||||
\node[mgd] (db) at (5.4,0) {managed database};
|
||||
\node[mgd] (api) at (5.4,-1.6) {third-party API\\(BaaS)};
|
||||
\draw[arr] (http) -- (f1.west);
|
||||
\draw[arr] (q) -- (f2.west);
|
||||
\draw[arr] (sched) -- ([yshift=-0.25cm]f2.west);
|
||||
\draw[arr] (f1.east) -- (obj.west);
|
||||
\draw[arr] (f1.east) -- (db.west);
|
||||
\draw[arr] (f2.east) -- (db.west);
|
||||
\draw[arr] (f2.east) -- (api.west);
|
||||
\end{tikzpicture}%
|
||||
}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.05cm}
|
||||
\footnotesize Functions are stateless: all state lives outside, and \textbf{inter-function communication runs through storage} -- the documented cost trap. The problem it solves: \textbf{idle capacity} -- much real work is spiky or rare (thumbnails, webhooks, reports), and provisioned machines force a bad choice between sizing for the peak and failing at it.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{SL -- capability profile (no star anchor: Berkeley/CNCF-derived)}
|
||||
\scriptsize
|
||||
\renewcommand{\arraystretch}{0.8}%
|
||||
\vspace{-0.35cm}
|
||||
\begin{center}
|
||||
\begin{tabular}{@{}p{2.9cm}cp{7.8cm}@{}}
|
||||
\toprule
|
||||
\textbf{Dimension} & \textbf{Rating} & \textbf{Structural reason} \\
|
||||
\midrule
|
||||
D1 Read scalability & $+$ & wide parallelism, tempered by concurrency limits and the DB-connection bottleneck \\
|
||||
D2 Write scal.\ \& elasticity & $++$ & scale-to-zero to mass parallelism, no capacity planning \\
|
||||
D3 Latency \& predictability & $-$ & cold starts make tail latency structurally unpredictable \\
|
||||
D4 Consistency \& integrity & $-$ & stateless functions push all state through external storage \\
|
||||
D5 Availability \& isolation & $+$ & platform-managed redundancy; small blast radius per function \\
|
||||
D6 Security \& auditability & $\circ$ & platform identity per function vs.\ a fragmented audit trail \\
|
||||
D7 Evolvability & $\circ$ & fine-grained deployability vs.\ vendor lock-in and sprawl \\
|
||||
D8 Simplicity \& TTM & $\circ$ & no server management vs.\ a large configuration surface \\
|
||||
D9 Testability \& deployability & $\circ$ & trivial unit tests vs.\ cloud wiring no laptop reproduces \\
|
||||
D10 Operating cost & $++$/$--$ & \textbf{split by load shape}: zero idle cost vs.\ billing $+$ storage round trips \\
|
||||
D11 Team scaling & $+$ & the smallest teams in the catalogue ship to production \\
|
||||
D12 AI integrability & $\circ$ & fine event glue; platform timeouts collide with minutes-long runs \\
|
||||
\midrule
|
||||
Native shape $S(p)$ & \multicolumn{2}{l}{event-triggered, short-lived} \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{SL -- the split cell, observed in production}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item \textbf{D10 $= ++/--$ is the most workload-sensitive cell in the table}: $++$ for spiky load (zero idle cost); $--$ for sustained, data-intensive load. \emph{It does not average to $\circ$ -- averaging would erase precisely the information an architect needs.}
|
||||
\item \textbf{D3 $= -$ has a mitigation with a sting}: provisioned concurrency removes cold starts -- at the price of exactly the idle cost the pattern exists to avoid.
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.05cm}
|
||||
\begin{examplebox}[Amazon Prime Video -- a measured cost inversion]
|
||||
\footnotesize The video-monitoring service: Step Functions coordinating Lambdas, S3 buffering frames between stages. A hard scaling limit at $\sim 5\,\%$ of expected load, and consolidation into one ECS process cut infrastructure cost by $> 90\,\%$. \textbf{The correct reading}: \emph{one} service with a data-intensive, tightly coupled flow -- PF pushed across expensive distributed boundaries -- not a verdict on serverless. \emph{(Widely reported as ``Amazon abandons microservices'' -- which measurement, taken before the first release, would have predicted the inversion?)}
|
||||
\end{examplebox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{SL -- engineering, build it and study it}
|
||||
\footnotesize
|
||||
\textbf{Engineering:} infrastructure-as-code becomes \emph{part of the test subject}; integration tests run against emulators or ephemeral environments. Above all: \textbf{cost monitoring becomes an engineering discipline (FinOps)} -- cost per request belongs on the same dashboards as latency.
|
||||
|
||||
\vspace{0.05cm}
|
||||
\begin{examplebox}[Build it and study it -- serverless]
|
||||
\footnotesize \textbf{Build.} Knative (Go, Apache-2.0): clean, self-hostable FaaS on Kubernetes, runs on a local kind cluster. Moto (Python, Apache-2.0) mocks AWS APIs in local tests. Deliberately \emph{off} this list: LocalStack (archived into a closed model, 2026) and Serverless Framework v4 (proprietary) -- \textbf{the licence check, twice over}.
|
||||
|
||||
\textbf{Study.} The Knative Bookstore sample: independent Knative Services wired by Brokers and Triggers in YAML -- the most involved setup of the seven boxes, but self-hostable end to end.
|
||||
\end{examplebox}
|
||||
|
||||
\vspace{0.05cm}
|
||||
\textbf{Anti-patterns:} \emph{Lambda pinball} (alarm: function hops per request); \emph{cost inversion under load growth} (alarm: cost-per-request trend vs.\ load trend, break-even utilisation as a standing fitness function); \emph{cold-start denial} (alarm: cold-start rate on p99 routes).
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{SL -- AI lens and key concept}
|
||||
\begin{ailinse}[Serverless and AI: excellent glue -- conditional runtime]
|
||||
\footnotesize D12 $= \circ$, and the split mirrors the D10 cell. Event glue around \emph{batch} AI APIs fits beautifully: a function that submits, polls, and stores an asynchronous AI job is serverless at its best. But \textbf{platform timeout ceilings collide with minutes-long LLM and solver runs} -- a hard constraint, not a tuning issue -- and per-call cost stacking across functions \emph{plus} tokens is opaque without a single gateway measurement point. \textbf{A fine chauffeur for AI jobs, and a poor place for them to live.}
|
||||
\end{ailinse}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize The serverless profile is dominated by one variable more than any other pattern's: \textbf{load shape}. Unmatched elasticity and scale-to-zero economics for spiky workloads -- inverting into the catalogue's worst cost cell under sustained, data-intensive load. The split D10 rating is the table being honest where an average would lie.
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% STEPPING BACK
|
||||
% ============================================
|
||||
\section{Stepping Back}
|
||||
|
||||
\begin{frame}{Stepping back: the architecture quantum}
|
||||
\small
|
||||
Seven times the same movement: problem $\to$ topology $\to$ profile $\to$ engineering $\to$ runnable code. What no single section could deliver is the view \emph{across} -- and it starts with the unit you met in every topology figure: \textbf{the dashed boundary}.
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{definitionbox}[Architecture quantum]
|
||||
\footnotesize An \emph{independently deployable} unit that can be deployed, scaled, and can fail independently of the rest -- the joint unit of deployment, scaling, and failure. L, MM, and PF form exactly \textbf{one} quantum; EDA one or more; MS \textbf{many}; SL many small, short-lived ones.
|
||||
\end{definitionbox}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize \textbf{Maxim 3.} One quantum $\to$ cheap, simple, consistent, rigid. Many quanta $\to$ expensive, complex, eventually consistent, elastic. \emph{The quantum count explains most of the capability table.}
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Partitioning beats distribution}
|
||||
\footnotesize
|
||||
The second axis is orthogonal: \emph{how} the units are cut. \textbf{Technical partitioning} groups by technical role (layers, filter stages); \textbf{domain partitioning} by business capability (modules, services). Change requests arrive in the \emph{domain's} vocabulary -- so a feature cuts across every technical unit, but lands \emph{inside one} domain unit. \textcolor{codegray}{(Parnas's criterion, six decades on.)}
|
||||
|
||||
\vspace{0.1cm}
|
||||
You watched the axis operate \textbf{in isolation}:
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item \textbf{L $\to$ MM}: quantum count constant, only the cut flips -- D7/D9 rise from $-$ to $+$
|
||||
\item \textbf{MM $\to$ MS}: domain cut constant, quanta multiply -- evolvability stays, the bill arrives on D8/D10
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize \textbf{Maxim 4.} The partitioning axis beats the distribution axis: \emph{domain-oriented partitioning, not the number of deployment units, is the strongest single predictor of evolvability.}
|
||||
\end{keypoint}
|
||||
|
||||
\vspace{0.05cm}
|
||||
The $2 \times 2$ logic: L, PF $=$ technical/single quantum $\cdot$ MM $=$ domain/single $\cdot$ MS $=$ domain/many $\cdot$ EDA, SL multiply quanta along technical seams $\cdot$ HX orthogonal to both.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{The evidence base -- and its honest gaps}
|
||||
\footnotesize
|
||||
The most systematic public rating: the star scheme of Richards \& Ford -- eleven characteristics, one to five stars, calibrated here via the fixed mapping ($5\star \to ++$ \dots\ $1\star \to --$). Its own headline result proves a matching problem exists: \textbf{no style dominates} -- microservices lead the aggregate yet one star on cost and simplicity; layered is the exact mirror.
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{hinweisbox}
|
||||
\footnotesize Four caveats before comparative use: (i) star ratings are structured \textbf{expert judgement}, not measurements -- transcribed from the first edition, to be reconciled against the second before print; (ii) \textbf{HX carries no star profile at all} -- correctly, as a dependency-organisation pattern; its column is a flagged delta; (iii) \textbf{SL} likewise -- its column derives from Berkeley $+$ CNCF; (iv) \textbf{MM} is a rated style only since the second edition. Compensation: \emph{triangulation} -- expert ratings $\times$ documented production cases $\times$ defined response measures -- plus the measurement contract, which converts every adopted claim into a testable one.
|
||||
\end{hinweisbox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{The consolidated capability table}
|
||||
\scriptsize
|
||||
\renewcommand{\arraystretch}{0.85}%
|
||||
\begin{center}
|
||||
\begin{tabular}{@{}p{3.6cm}ccccccc@{}}
|
||||
\toprule
|
||||
\textbf{Dimension} & \textbf{L} & \textbf{MM} & \textbf{HX} & \textbf{MS} & \textbf{EDA} & \textbf{PF} & \textbf{SL} \\
|
||||
\midrule
|
||||
D1 Read scalability & $\circ$ & $\circ$ & $\diamond$ & $++$ & $++$ & $\circ$ & $+$ \\
|
||||
D2 Write scalability \& elasticity & $--$ & $-$ & $\diamond$ & $++$ & $++$ & $+$ & $++$ \\
|
||||
D3 Latency \& predictability & $+$ & $+$ & $\diamond$ & $-$ & $+$ & $--$ & $-$ \\
|
||||
D4 Consistency \& integrity & $++$ & $++$ & $\diamond$ & $--$ & $--$ & $+$ & $-$ \\
|
||||
D5 Availability \& fault isolation & $-$ & $-$ & $\diamond$ & $++$ & $++$ & $-$ & $+$ \\
|
||||
D6 Security \& auditability & $+$ & $+$ & $+$ & $\circ$ & $\circ$ & $+$ & $\circ$ \\
|
||||
D7 Evolvability \& maintainability & $-$ & $+$ & $++$ & $++$ & $++$ & $+$ & $\circ$ \\
|
||||
D8 Simplicity \& time-to-market & $++$ & $+$ & $-$ & $--$ & $--$ & $++$ & $\circ$ \\
|
||||
D9 Testability \& deployability & $-$ & $+$ & $++$ & $+$ & $-$ & $+$ & $\circ$ \\
|
||||
D10 Operating cost efficiency & $++$ & $++$ & $\diamond$ & $--$ & $\circ$ & $++$ & $++$/$--$ \\
|
||||
D11 Team scaling (Conway) & $-$ & $\circ$ & $\diamond$ & $++$ & $+$ & $\circ$ & $+$ \\
|
||||
D12 AI integrability & $\circ$ & $+$ & $++$ & $\circ$ & $++$ & $++$ & $\circ$ \\
|
||||
\midrule
|
||||
Native shape $S(p)$ & interact. & interact. & (host's) & interact. & stream & batch & event-trig. \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.05cm}
|
||||
\footnotesize The 21 table notes (every deviation, with evidence) are in the script.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Four reading rules -- and the table's status}
|
||||
\small
|
||||
\begin{enumerate}\setlength\itemsep{2pt}
|
||||
\item \textbf{HX is a delta pattern}: $\diamond$ inherits the host; its own cells are what the cut adds
|
||||
\item \textbf{Every deviation is footnoted} -- an unexplained deviation would violate the theory's own rigour standard
|
||||
\item \textbf{One cell is split}: SL's D10 genuinely inverts with load shape -- a standing sensitivity point, not a $\circ$
|
||||
\item \textbf{The last row feeds the shape gate}: $S(p)$ vs.\ $S(a)$ in stage-1 knock-out screening
|
||||
\end{enumerate}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize \emph{Ordinal} reading only: rankings and exclusions, never weighted sums. Every cell is a \textbf{default hypothesis} -- replaced by measurement once the system exists. Two cells documented to invert with context: SL cost (Prime Video), L read scalability (Stack Overflow). \emph{The matrix predicts the default, not the exception.}
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Reading the catalogue as a whole}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item \textbf{No column dominates -- so a matching problem exists.} A2 made visible in data; two variables -- quantum count (Maxim 3) and partitioning axis (Maxim 4) -- explain most of 84 cells.
|
||||
\item \textbf{The cost curves cross.} Single quanta: low fixed cost, superlinear maintenance growth unless governance holds. Many quanta: high fixed cost (platform staffing) or load-proportional cost. The five case studies are where fit and misfit were \emph{measured in money}.
|
||||
\item \textbf{Conway is a decision filter, not a footnote.} Every column presupposes a team topology: L one team $\cdot$ MM 3--5 coordinated $\cdot$ MS stream-aligned $+$ platform. Loosely coupled architectures \emph{and teams} predict continuous delivery.
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.05cm}
|
||||
\begin{thinkbox}
|
||||
\footnotesize Stack Overflow: $\sim 1.3$bn page views/month from \emph{one} quantum. Monzo: a licensed bank on $\sim 2{,}800$. What exactly does this pair falsify about ``microservices scale better than monoliths'' -- and what does it \emph{not} falsify?
|
||||
\end{thinkbox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Outlook: agent orchestration -- an emergent composition pattern}
|
||||
\footnotesize
|
||||
One candidate for an ``eighth pattern'', filed correctly: agent orchestration is \textbf{not a new style} -- it is a \emph{composition pattern} for non-deterministic components that \textbf{reuses this catalogue's topologies}:
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{center}
|
||||
\scriptsize
|
||||
\begin{tabular}{@{}ll@{}}
|
||||
\toprule
|
||||
\textbf{Agent construct} & \textbf{Classical topology} \\
|
||||
\midrule
|
||||
prompt chaining & pipes-and-filters \\
|
||||
routing & dispatch layer \\
|
||||
parallelisation with voting & broker-style fan-out \\
|
||||
orchestrator--workers & mediator EDA \\
|
||||
evaluator--optimizer loop & feedback control loop \\
|
||||
multi-agent systems & broker fan-out of autonomous quanta \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.1cm}
|
||||
Load-bearing distinction: \textbf{workflows} (predefined code paths) vs.\ \textbf{agents} (the model steers its own process). The rigour case for restraint is quantified: a multi-agent research system beat a single agent by $90.2\,\%$ -- at roughly \textbf{fifteen times} the token consumption, with token use alone explaining $80\,\%$ of the variance. The module's default rule: \emph{workflows before agents}; every escalation is an ADR with a measurement contract.
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% PART III: C10
|
||||
% ============================================
|
||||
\section{C10 -- Your Class}
|
||||
|
||||
\begin{frame}{Part III opens: C10 -- AI-native advisory platforms}
|
||||
\emph{\textcolor{bankblue}{The component your product is built around is non-deterministic, priced per call, and deprecated within months: what structure contains it?}}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\small The youngest class in the catalogue, \textbf{the profile of the course project}, and the reason this course exists in its present form. The architecture must \emph{contain} the AI component: deterministic services for everything deterministic, LLM calls only where determinism cannot reach, every generated statement grounded in retrievable sources.
|
||||
|
||||
\vspace{0.15cm}
|
||||
\footnotesize \textbf{Three challenges define the class:}
|
||||
\begin{enumerate}\setlength\itemsep{1pt}
|
||||
\item \textbf{Accountability for probabilistic output} -- provenance per claim, a log per agent step: observability is \emph{domain functionality}, with EU AI Act force behind it (potentially high-risk classification)
|
||||
\item \textbf{A genuinely new cost model} -- requests rare but heavy: cost \emph{per request} (tokens, GPU), not per user; batch APIs $\sim 50\,\%$ cheaper; model cascades up to $98\,\%$ cost reduction; learned routers halve cost
|
||||
\item \textbf{Churn at the core's edge} -- models, prompts, frameworks turn over in months: the most extreme change rate in the catalogue, and the strongest argument for ports and adapters
|
||||
\end{enumerate}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{C10 -- the binding scenarios}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{3pt}
|
||||
\item \textbf{S1 (grounded answer).} A client asks for a recommendation; \textbf{every factual claim carries a resolvable provenance reference}, failing answers are blocked and escalated -- \textbf{detection rate $\geq 99\,\%$ at $< 2$\,s added latency}. \textcolor{codegray}{(The D6 scenario.)}
|
||||
\item \textbf{S2 (cost per request).} A session triggers a multi-step agent workflow; it completes \textbf{within a per-request token-cost budget (e.g.\ CHF~0.40 at p95) and a p95 latency budget (e.g.\ 20\,s)} -- both CI-gated fitness functions. \textcolor{codegray}{(The D10 scenario.)}
|
||||
\item \textbf{S3 (model migration).} The provider deprecates the production model; the platform migrates with \textbf{eval-harness pass rate $\geq$ threshold on the golden set before rollout, rollback available}. \textcolor{codegray}{(The D7/D9 scenario.)}
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\textbf{Knock-out reading of $K$:} an architecture in which agent steps are not loggable, tool privileges not boundable, or provenance not reconstructable is \textbf{excluded before scoring} -- C1's ACID veto logic, transposed to accountability. Prompt injection cannot be fully solved in the model $\to$ system-level defence in depth is \emph{constitutive}.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{C10 -- requirements profile (the only column with an H on D12)}
|
||||
\scriptsize
|
||||
\renewcommand{\arraystretch}{0.8}%
|
||||
\vspace{-0.35cm}
|
||||
\begin{center}
|
||||
\begin{tabular}{@{}p{3.0cm}cp{7.7cm}@{}}
|
||||
\toprule
|
||||
\textbf{Dimension} & \textbf{Weight} & \textbf{Why} \\
|
||||
\midrule
|
||||
D1 Read scalability & M & retrieval reads; user concurrency modest \\
|
||||
D2 Write scal.\ \& elasticity & L & requests rare; batch pipelines scheduled, not elastic \\
|
||||
D3 Latency & M & users accept seconds-to-minutes for advisory answers \\
|
||||
D4 Consistency \& integrity & M & hybrid: knowledge index eventual, audit path ACID \\
|
||||
D5 Availability \& isolation & M & degraded answers beat no answers \\
|
||||
D6 Security \& auditability & \textbf{H} & provenance per claim, a log per agent step -- AI Act force (S1) \\
|
||||
D7 Evolvability & \textbf{H} & models, prompts, frameworks turn over in months (S3) \\
|
||||
D8 Simplicity \& TTM & M & start simplest -- but never simpler than the audit path \\
|
||||
D9 Testability \& deployability & \textbf{H} & \textbf{evals are the operative meaning of testability} (S3) \\
|
||||
D10 Operating cost & \textbf{H} & cost per \emph{request} -- a run-cost class no classical profile contains (S2) \\
|
||||
D11 Team scaling & L & small product teams; the platform premium is unaffordable \\
|
||||
D12 AI integrability & \textbf{H} & definitional: the class exists to contain the probabilistic component \\
|
||||
\midrule
|
||||
Shape $S(a)$ & \multicolumn{2}{l}{hybrid: interactive $+$ batch/async} \\
|
||||
Constraints $K(a)$ & \multicolumn{2}{l}{EU AI Act 2024/1689 (logging, oversight; potentially high-risk); GDPR} \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{C10 -- what real systems chose, and why}
|
||||
\footnotesize
|
||||
Three documented building blocks define the reference shape:
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item \textbf{Retrieval-augmented generation}: ingestion $\to$ vector index $\to$ retrieval $\to$ context $\to$ generation with citations -- structurally a \textbf{PF pipeline plus a serving layer}
|
||||
\item \textbf{Agent orchestration}: \emph{workflows before agents} -- the restraint case is quantified ($90.2\,\%$ better at $15\times$ the tokens)
|
||||
\item \textbf{Compound AI systems}: results come from systems of retrievers, models, tools, verifiers -- \emph{the system architecture becomes the differentiator}
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.05cm}
|
||||
The capability tables explain the host choice:
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item \textbf{MM} hosts the deterministic majority in one ACID quantum \emph{and} gives the AI subsystem a hard, CI-verifiable boundary
|
||||
\item \textbf{HX} answers the two hardest Highs: the LLM as a swappable adapter behind a port (D7); the port is where the \textbf{eval harness and cost gateway dock} (D9, D10)
|
||||
\item where A2 bites: synchronous chains multiply LLM latency -- what keeps \textbf{MS at $\circ$}; the monolith's weak cells are mitigated by \textbf{asynchronous edges}
|
||||
\end{itemize}
|
||||
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{The C1/C2 mirror pair -- weights, not dimensions, define a class}
|
||||
\footnotesize
|
||||
\begin{columns}[T]
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankblue}{\textbf{C1 core banking}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item a lost or double-posted booking \emph{creates or destroys money}: D4/D5/D6/D7/D9 High
|
||||
\item verdict: \textbf{MM$+$HX core}, EDA edges, PF batch runs; MS only at the Monzo condition (D11 forced High)
|
||||
\item LMAX vs.\ Monzo: \emph{same profile, opposite structures} -- $R(a)$ defines the feasible set, $K(a)$ decides within it
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankblue}{\textbf{C2 social/content platforms}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item $\sim 50{:}1$ read/write ratio; a \emph{stale} feed is invisible, an \emph{unavailable} feed is the defect: D1/D3/D5/D7/D9/D11 High, \textbf{D4 Low}
|
||||
\item verdict: \textbf{EDA$+$MS hybrid} at organisational scale; MM secondary until that scale is \emph{measured} (Instagram: a Django monolith at 100 deployments/day)
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize C1 and C2 are \textbf{mirror images} across the consistency/availability trade: same twelve dimensions, inverted weights on D1 and D4. \emph{Weights, not dimensions, define a class.}
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{C10 -- your project as an inheritance diagram}
|
||||
\begin{projektbox}
|
||||
\footnotesize The Portfolio Intelligence Platform \emph{is} a C10 instance. \textbf{Inherited:} ingestion and eval pipelines are C6 (reproducible batch); analytics are C7 (refresh contracts, lineage); the deterministic services are C3 (ACID, boring on purpose). \textbf{New:} the cost model -- \emph{expensive per request}: a token-cost budget, enforced in CI. \textbf{Also new:} D12 $=$ H, and D9 $=$ H in its eval reading -- a versioned golden set gates every prompt change and model migration. \emph{Spend your design budget on the new elements -- the inherited disciplines are solved problems.}
|
||||
\end{projektbox}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize C10 \textbf{stress-tests} the method rather than overthrowing it: one new High dimension, one new cost semantics, one new test-artefact class -- otherwise \emph{inherited} (A6 made concrete). In one sentence: a \emph{hexagonal modular monolith} -- AI adapters at ports, an LLM gateway as the single measurement point -- plus PF for ingestion and evals, EDA for the job and audit spine.
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% CLOSING
|
||||
% ============================================
|
||||
\section{Closing}
|
||||
|
||||
\begin{frame}{This week's exercise: the match}
|
||||
\begin{projektbox}
|
||||
\footnotesize Run the \textbf{full three-stage procedure} for your platform, against your A1 requirements profile:
|
||||
\begin{enumerate}\setlength\itemsep{1pt}
|
||||
\item \textbf{Knock-out}: constraints and the workload-shape gate -- which candidates cannot carry the core?
|
||||
\item \textbf{Veto}: hold every High weight against the capability columns -- which vetoes fire, which have \emph{documented} mitigations?
|
||||
\item \textbf{Ordinal reading}: rank the survivors on the High set; run the sensitivity check
|
||||
\end{enumerate}
|
||||
\textbf{Take the decision -- and begin the ADR} (MADR: drivers, options, consequences, confirmation).
|
||||
\end{projektbox}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\small Next week's lecture shows the same procedure formally -- you will recognise every step.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Summary}
|
||||
\footnotesize
|
||||
\begin{enumerate}\setlength\itemsep{2pt}
|
||||
\item \textbf{PF}: makespan and reproducibility -- a \emph{third} consistency semantics (``as of last run''); the most deterministically testable pattern; the natural home of ingestion, training, and evals
|
||||
\item \textbf{SL}: the profile is dominated by load shape; the split D10 cell is the table being honest -- Prime Video is note 18 observed in production, with a price tag
|
||||
\item \textbf{Maxims 3 and 4}: quantum count and partitioning axis explain most of the 84 cells
|
||||
\item The \textbf{consolidated table} supports ordinal reading only -- every cell a default hypothesis, two cells documented to invert with context
|
||||
\item \textbf{Agent orchestration} reuses this catalogue's topologies -- workflows before agents ($15\times$ token finding)
|
||||
\item \textbf{C10}: Highs on D6/D7/D9/D10/D12 -- accountability, churn, evals, cost per request, containment; inherits C6/C7/C3, adds the eval harness and the token budget
|
||||
\item \textbf{C1/C2}: mirror images across the consistency/availability axis -- weights, not dimensions, define a class
|
||||
\end{enumerate}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Next week}
|
||||
\begin{columns}[T]
|
||||
\begin{column}{0.55\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Lecture 7 -- Part IV: the match, formally}}
|
||||
\begin{itemize}\small
|
||||
\item three cases, three stages
|
||||
\item the procedure in general; reading the $7 \times 10$ matrix
|
||||
\item the measurement contract, introduced
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\begin{column}{0.42\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Reading}}
|
||||
\begin{itemize}\small
|
||||
\item this week: Part II close; Part III, C10
|
||||
\item ahead: Part IV, sections 1--3
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\textcolor{bankblue}{\textbf{Exercise / deliverable}}
|
||||
\begin{itemize}\small
|
||||
\item the match; decision; ADR begun
|
||||
\item \textbf{A2 $+$ design gate: next week}
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% END
|
||||
% ============================================
|
||||
\FHGRClosingPage[][{\color{white}\parbox{0.9\paperwidth}{\centering Thank you!\\[3ex]
|
||||
{\normalsize\mdseries Dr.\ Florian Herzog\\[0.9ex]
|
||||
Fachhochschule Graub\"unden, Chur\\[2.4ex]
|
||||
{\small AISE502 -- AI in Software Engineering II}}}}]
|
||||
|
||||
\end{document}
|
||||
1083
Folien/CDS305_Vorlesung_1_Folien.tex
Normal file
BIN
Folien/FHGR_Logo_Large.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
Folien/FHGR_Logo_small.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
829
Folien/beamerthemeFHGR.sty
Normal file
@ -0,0 +1,829 @@
|
||||
% beamerthemeFHGR.sty
|
||||
% A modernized, configurable Beamer FHGR theme.
|
||||
% Author: Daniel Zünd
|
||||
% Date: 2025-10-16
|
||||
%
|
||||
% Quick start
|
||||
% \documentclass{beamer}
|
||||
% \usetheme[dark,noprog]{FHGR} % all keys: see "Options" below / README.md
|
||||
% \title{Deck title}\subtitle{Subtitle}\author{Jane Doe}
|
||||
% \fullname{Prof. Dr. Jane Doe} % optional, title page only
|
||||
% \shortname{CDS042} % optional, footline + title page
|
||||
% \begin{document}
|
||||
% \FHGRTitlePage % title slide
|
||||
% \FHGRToC{Agenda} % ToC slide, image on the left half
|
||||
% \begin{frame}{A slide} ... \end{frame}
|
||||
% \FHGRClosingPage[][Thank you!]% closing slide
|
||||
% \end{document}
|
||||
%
|
||||
% Every image is looked up with \IfFileExists, so a missing logo or background
|
||||
% is skipped silently instead of aborting the build. The defaults expect the
|
||||
% theme images under pics/theme_pics/.
|
||||
%
|
||||
% Commands defined here: \FHGRTitlePage, \FHGRToC, \FHGRClosingPage,
|
||||
% \FHGRTable (env), \fullname, \shortname, \credit, \imagesource, \source.
|
||||
|
||||
% =============================
|
||||
% Package metadata & engine setup
|
||||
% =============================
|
||||
\NeedsTeXFormat{LaTeX2e}
|
||||
\ProvidesPackage{beamerthemeFHGR}[2025/10/16 v1.0 FHGR Beamer Theme]
|
||||
|
||||
% Covered overlay material (\pause, \onslide, [<+->]) is hidden completely.
|
||||
% Put \setbeamercovered{transparent} in your preamble to grey it out instead.
|
||||
\mode<presentation>{
|
||||
\setbeamercovered{invisible}
|
||||
}
|
||||
|
||||
% Ensure xcolor gets the `table` option (for \rowcolor/\rowcolors) BEFORE any
|
||||
% package (e.g. tikz) loads xcolor without it.
|
||||
\PassOptionsToPackage{table}{xcolor}
|
||||
|
||||
% Core deps (why each one is needed)
|
||||
\RequirePackage{etoolbox} % \patchcmd, \pretocmd, \ifdefempty
|
||||
\RequirePackage{iftex} % \ifPDFTeX engine test below
|
||||
\RequirePackage{tikz} % title page, ToC panel, progress bar
|
||||
\RequirePackage{calc} % infix length arithmetic
|
||||
\RequirePackage{graphicx} % logos and background images
|
||||
\RequirePackage{pgfkeys} % the /fhgr option keys
|
||||
\RequirePackage{hyperref} % links + PDF bookmarks (see "Appendix")
|
||||
\RequirePackage{listings} % code slides, see "Listings style"
|
||||
\RequirePackage{appendixnumberbeamer}% \appendix restarts frame numbering
|
||||
\RequirePackage{xparse} % \NewDocumentCommand: \FHGRToC, \FHGRClosingPage
|
||||
|
||||
|
||||
% Font setup (pdfLaTeX vs Xe/Lua): pdfLaTeX gets a scaled Helvetica clone,
|
||||
% Xe/LuaLaTeX needs Roboto installed system-wide.
|
||||
\ifPDFTeX
|
||||
\RequirePackage[scaled=0.92]{helvet}
|
||||
\RequirePackage[T1]{fontenc}
|
||||
\RequirePackage{textcomp}
|
||||
\renewcommand\familydefault{\sfdefault}
|
||||
\else
|
||||
\RequirePackage{fontspec}
|
||||
% You can change these to your corporate fonts
|
||||
\setmainfont{Roboto}[Scale=0.92]
|
||||
\setsansfont{Roboto}
|
||||
\fi
|
||||
|
||||
% =============================
|
||||
% Options via pgfkeys (usable with \usetheme[<keys>]{FHGR})
|
||||
% =============================
|
||||
% One switch per boolean key; the pgfkeys `.is if' handlers below flip them.
|
||||
% Query them in your own templates with \ifFHGR@dark ... \else ... \fi.
|
||||
\newif\ifFHGR@dark
|
||||
\newif\ifFHGR@progressbar
|
||||
\newif\ifFHGR@shownav
|
||||
\newif\ifFHGR@shownumber
|
||||
\newif\ifFHGR@showsection
|
||||
\newif\ifFHGR@compactlists
|
||||
\newif\ifFHGR@titlegradient
|
||||
\newif\ifFHGR@titlefillimage
|
||||
|
||||
\pgfkeys{/fhgr/.is family, /fhgr,
|
||||
% File paths (safe defaults) -- each is stored in the \FHGR@... macro named
|
||||
% after it and read at typeset time, so a wrong path fails silently.
|
||||
logo/.store in=\FHGR@logo, % footline logo, light mode
|
||||
logo={pics/theme_pics/logo_green_small.png},
|
||||
logowhite/.store in=\FHGR@logowhite, % footline logo, dark mode
|
||||
logowhite={pics/theme_pics/logo_green_small.png},% same file as `logo' by default
|
||||
biglogoblack/.store in=\FHGR@biglogoblack, % title page logo, light mode
|
||||
biglogoblack={pics/theme_pics/logo_green.png},
|
||||
biglogowhite/.store in=\FHGR@biglogowhite, % title page logo, dark mode
|
||||
biglogowhite={pics/theme_pics/logo_green.png},
|
||||
grlogo/.store in=\FHGR@grlogo, % stored only -- no template uses
|
||||
grlogo={pics/theme_pics/graubuenden.png}, % it; free for your own slides
|
||||
titlebg/.store in=\FHGR@titlebg, % background of title/ToC/closing
|
||||
titlebg={pics/theme_pics/titlepage.png},
|
||||
% Toggles -- `\usetheme[key]{FHGR}' / `\usetheme[nokey]{FHGR}', see below
|
||||
dark/.is if=FHGR@dark, % dark background, light text
|
||||
dark=false,
|
||||
progressbar/.is if=FHGR@progressbar, % thin bar along the bottom edge
|
||||
progressbar=true,
|
||||
nav/.is if=FHGR@shownav, % beamer's navigation symbols
|
||||
nav=false,
|
||||
framenumber/.is if=FHGR@shownumber, % "n / total" in the footline
|
||||
framenumber=true,
|
||||
showsection/.is if=FHGR@showsection, % current section in the headline
|
||||
showsection=false,
|
||||
compactlists/.is if=FHGR@compactlists, % tighter list spacing
|
||||
compactlists=true,
|
||||
titlegradient/.is if=FHGR@titlegradient, % fade PNG over background images
|
||||
titlegradient=true,
|
||||
titlefillimage/.is if=FHGR@titlefillimage, % true: stretch background to the
|
||||
titlefillimage=true, % slide; false: keep aspect ratio
|
||||
% Branding colors: 6-digit HTML values without `#'. They become the named
|
||||
% colours in the "Colors" section below (\color{camel}, ...).
|
||||
color/green/.store in=\FHGR@green,
|
||||
color/green=817E65,
|
||||
color/red/.store in=\FHGR@red,
|
||||
color/red=C60219,
|
||||
color/gray/.store in=\FHGR@gray,
|
||||
color/gray=595959,
|
||||
color/lightgray/.store in=\FHGR@lightgray,
|
||||
color/lightgray=CCCCCC,
|
||||
color/darkgray/.store in=\FHGR@darkgray,
|
||||
color/darkgray=3F3F3F,
|
||||
color/camel/.store in=\FHGR@camel,
|
||||
color/camel=B39048,
|
||||
color/linen/.store in=\FHGR@linen,
|
||||
color/linen=e1d3b5,
|
||||
color/black/.store in=\FHGR@black,
|
||||
color/black=1E1E1E,
|
||||
color/blue/.store in=\FHGR@blue,
|
||||
color/blue=4B92A4,
|
||||
color/white/.store in=\FHGR@white,
|
||||
color/white=F8F9FA
|
||||
}
|
||||
|
||||
% \beamerthemeFHGRoptions{<keys>} -- set /fhgr keys with their full names, e.g.
|
||||
% \beamerthemeFHGRoptions{logo=pics/mylogo.png,titlegradient=false}
|
||||
% It can only run after \usetheme, i.e. after the colours below were already
|
||||
% \definecolor'd, so color/* keys have no effect here -- recolour with
|
||||
% \definecolor + \colorlet instead (see "Colors").
|
||||
\def\beamerthemeFHGRoptions#1{\pgfkeys{/fhgr,#1}}
|
||||
% Aliases accepted by \usetheme[...]{FHGR}: the value keys logo= and titlebg=,
|
||||
% plus these on/off pairs -- dark/nodark, progressbar/noprog, nav/nonav,
|
||||
% framenumber/noframenumber, showsection/nosection, compactlists/nocompactlists,
|
||||
% titlegradient/notitlegradient, titlefillimage/notitlefillimage.
|
||||
\DeclareOptionBeamer{logo}{\pgfkeys{/fhgr,logo={#1}}}
|
||||
\DeclareOptionBeamer{titlebg}{\pgfkeys{/fhgr,titlebg={#1}}}
|
||||
\DeclareOptionBeamer{dark}{\pgfkeys{/fhgr,dark}}
|
||||
\DeclareOptionBeamer{nodark}{\pgfkeys{/fhgr,dark=false}}
|
||||
\DeclareOptionBeamer{progressbar}{\pgfkeys{/fhgr,progressbar}}
|
||||
\DeclareOptionBeamer{noprog}{\pgfkeys{/fhgr,progressbar=false}}
|
||||
\DeclareOptionBeamer{nav}{\pgfkeys{/fhgr,nav}}
|
||||
\DeclareOptionBeamer{nonav}{\pgfkeys{/fhgr,nav=false}}
|
||||
\DeclareOptionBeamer{framenumber}{\pgfkeys{/fhgr,framenumber}}
|
||||
\DeclareOptionBeamer{noframenumber}{\pgfkeys{/fhgr,framenumber=false}}
|
||||
\DeclareOptionBeamer{showsection}{\pgfkeys{/fhgr,showsection}}
|
||||
\DeclareOptionBeamer{nosection}{\pgfkeys{/fhgr,showsection=false}}
|
||||
\DeclareOptionBeamer{compactlists}{\pgfkeys{/fhgr,compactlists}}
|
||||
\DeclareOptionBeamer{nocompactlists}{\pgfkeys{/fhgr,compactlists=false}}
|
||||
\DeclareOptionBeamer{titlegradient}{\pgfkeys{/fhgr,titlegradient}}
|
||||
\DeclareOptionBeamer{notitlegradient}{\pgfkeys{/fhgr,titlegradient=false}}
|
||||
\DeclareOptionBeamer{titlefillimage}{\pgfkeys{/fhgr,titlefillimage}}
|
||||
\DeclareOptionBeamer{notitlefillimage}{\pgfkeys{/fhgr,titlefillimage=false}}
|
||||
\ProcessOptionsBeamer
|
||||
|
||||
% =============================
|
||||
% Colors
|
||||
% =============================
|
||||
\RequirePackage{xcolor}
|
||||
\RequirePackage{tabularx}
|
||||
\RequirePackage{colortbl}
|
||||
\RequirePackage{environ}% \NewEnviron captures the whole body (needed to wrap tabularx)
|
||||
% The palette. Usable anywhere: \textcolor{camel}{...}, \color{linen},
|
||||
% tikz [fill=green]. Careful -- green/red/gray/black/blue/white deliberately
|
||||
% shadow xcolor's standard names, so \color{red} is FHGR red, not pure red.
|
||||
\definecolor{green}{HTML}{\FHGR@green}
|
||||
\definecolor{red}{HTML}{\FHGR@red}
|
||||
\definecolor{gray}{HTML}{\FHGR@gray}
|
||||
\definecolor{lightGray}{HTML}{\FHGR@lightgray}
|
||||
\definecolor{camel}{HTML}{\FHGR@camel}
|
||||
\definecolor{linen}{HTML}{\FHGR@linen}
|
||||
\definecolor{black}{HTML}{\FHGR@black}
|
||||
\definecolor{blue}{HTML}{\FHGR@blue}
|
||||
\definecolor{darkGray}{HTML}{\FHGR@darkgray}
|
||||
\definecolor{white}{HTML}{\FHGR@white}
|
||||
|
||||
% Dark mode adjustments. These semantic aliases are what the templates use, and
|
||||
% what you should prefer in your own slides -- they follow the `dark' toggle:
|
||||
% FHGRBg page background FHGRTxt body text
|
||||
% FHGRDeco titles, footline, progress bar
|
||||
% FHGRItem list bullets/numbers
|
||||
% FHGRBlockBg / FHGRBlockTitleBg / FHGRBlockTitleFg block colours
|
||||
% \colorlet copies the *value*, not the name, so recolouring after \usetheme
|
||||
% takes two steps: \definecolor{green}{HTML}{00693C}\colorlet{FHGRDeco}{green}
|
||||
\ifFHGR@dark
|
||||
\colorlet{FHGRBg}{black}
|
||||
\colorlet{FHGRTxt}{white}
|
||||
\colorlet{FHGRDeco}{green}
|
||||
\colorlet{FHGRBlockBg}{gray}
|
||||
\colorlet{FHGRBlockTitleBg}{darkGray}
|
||||
\colorlet{FHGRBlockTitleFg}{camel}
|
||||
\colorlet{FHGRItem}{camel}
|
||||
\pagecolor{FHGRBg}
|
||||
\else
|
||||
\colorlet{FHGRBg}{white}
|
||||
\colorlet{FHGRTxt}{black}
|
||||
\colorlet{FHGRDeco}{green}
|
||||
\colorlet{FHGRBlockBg}{lightGray!50}
|
||||
\colorlet{FHGRBlockTitleBg}{lightGray}
|
||||
\colorlet{FHGRBlockTitleFg}{camel}
|
||||
\colorlet{FHGRItem}{camel}
|
||||
\pagecolor{FHGRBg}
|
||||
\fi
|
||||
|
||||
% =============================
|
||||
% Public metadata helpers (optional)
|
||||
% \fullname{Prof. Dr. Jane Doe} -> \insertfullname, title page meta line only
|
||||
% \shortname{CDS042} -> \insertshortname, footline + title page
|
||||
% Use them in the preamble next to \title/\author. Both start out empty; the
|
||||
% footline then falls back to \insertauthor (see \FHGR@footmeta below).
|
||||
% =============================
|
||||
\newcommand*\fullname[1]{\gdef\FHGR@fullname{#1}}
|
||||
\newcommand*\shortname[1]{\gdef\FHGR@shortname{#1}}
|
||||
\def\FHGR@fullname{}
|
||||
\def\FHGR@shortname{}
|
||||
% Retrieval macros, for use inside custom templates.
|
||||
\newcommand*\insertfullname{\FHGR@fullname}
|
||||
\newcommand*\insertshortname{\FHGR@shortname}
|
||||
|
||||
% \FHGR@metajoin{<separator>}{<part>} -- typesets <part> only if it is non-empty,
|
||||
% preceded by <separator> only if an earlier part was already set. Reset the run
|
||||
% with \FHGR@metasepfalse, then call it once per part: no divider can then appear
|
||||
% at the start or the end of the line, whichever parts happen to be empty.
|
||||
% Emptiness is measured in a box rather than tested with \ifdefempty, because
|
||||
% both \insertauthor and \insertshortname have a permanently non-empty
|
||||
% replacement text (beamer runs \author{} itself; \insertshortname wraps
|
||||
% \FHGR@shortname), so no \ifx test on them can ever detect "the user set nothing".
|
||||
\newif\ifFHGR@metasep
|
||||
\newcommand*\FHGR@metajoin[2]{%
|
||||
\setbox\z@\hbox{#2}%
|
||||
\ifdim\wd\z@>\z@
|
||||
\ifFHGR@metasep#1\fi
|
||||
#2\FHGR@metaseptrue
|
||||
\fi
|
||||
}
|
||||
|
||||
% Footline segment: \shortname (or \author as fallback) | short title.
|
||||
\newcommand*\FHGR@footmeta{%
|
||||
\FHGR@metasepfalse
|
||||
\FHGR@metajoin{\,|\,}{\ifx\FHGR@shortname\@empty\insertauthor\else\insertshortname\fi}%
|
||||
\FHGR@metajoin{\,|\,}{\insertshorttitle}%
|
||||
}
|
||||
|
||||
% Title-page meta line: author | \shortname | \fullname.
|
||||
\newcommand*\FHGR@titlemeta{%
|
||||
\FHGR@metasepfalse
|
||||
\FHGR@metajoin{~|~}{\insertauthor}%
|
||||
\FHGR@metajoin{~|~}{\insertshortname}%
|
||||
\FHGR@metajoin{~|~}{\insertfullname}%
|
||||
}
|
||||
|
||||
% =============================
|
||||
% Beamer color setup
|
||||
% Maps the palette onto beamer's colour names. Override single entries after
|
||||
% \usetheme, e.g. \setbeamercolor{block title}{bg=camel,fg=white}.
|
||||
% =============================
|
||||
\setbeamercolor*{normal text}{fg=FHGRTxt,bg=FHGRBg}
|
||||
\setbeamercolor*{alerted text}{fg=red}
|
||||
\setbeamercolor*{example text}{fg=green}
|
||||
\setbeamercolor*{structure}{fg=FHGRTxt}
|
||||
|
||||
\setbeamercolor*{title}{fg=FHGRDeco}
|
||||
\setbeamercolor*{subtitle}{fg=FHGRDeco}
|
||||
\setbeamercolor*{frametitle}{fg=FHGRDeco}
|
||||
\setbeamercolor*{framesubtitle}{fg=FHGRDeco}
|
||||
\setbeamercolor*{section in head/foot}{fg=FHGRDeco}
|
||||
\setbeamercolor*{section in toc}{fg=FHGRTxt}
|
||||
\setbeamercolor*{subsection in toc}{fg=FHGRTxt}
|
||||
|
||||
\setbeamercolor{block title}{bg=FHGRBlockTitleBg,fg=FHGRBlockTitleFg}
|
||||
\setbeamercolor{block title example}{bg=FHGRBlockTitleBg,fg=green}
|
||||
\setbeamercolor{block title alerted}{bg=FHGRBlockTitleBg,fg=red}
|
||||
\setbeamercolor{block body}{bg=FHGRBlockBg,fg=FHGRTxt}
|
||||
\setbeamercolor{block body example}{bg=FHGRBlockBg,fg=FHGRTxt}
|
||||
\setbeamercolor{block body alerted}{bg=FHGRBlockBg,fg=FHGRTxt}
|
||||
|
||||
\setbeamercolor{caption}{fg=FHGRTxt}
|
||||
|
||||
\setbeamercolor{itemize item}{fg=FHGRItem}
|
||||
\setbeamercolor{itemize subitem}{fg=FHGRItem}
|
||||
\setbeamercolor{itemize subsubitem}{fg=FHGRItem}
|
||||
\setbeamercolor{enumerate item}{fg=FHGRItem}
|
||||
\setbeamercolor{enumerate subitem}{fg=FHGRItem}
|
||||
\setbeamercolor{enumerate subsubitem}{fg=FHGRItem}
|
||||
\setbeamercolor{description item}{fg=FHGRItem}
|
||||
\setbeamercolor{description subitem}{fg=FHGRItem}
|
||||
\setbeamercolor{description subsubitem}{fg=FHGRItem}
|
||||
|
||||
\setbeamercolor{note title}{bg=FHGRBlockTitleBg,fg=FHGRTxt}
|
||||
\setbeamercolor{note date}{fg=FHGRTxt}
|
||||
|
||||
|
||||
% =============================
|
||||
% Tables (opt-in)
|
||||
% \begin{FHGRTable}[<width>]{<colspec>} width optional, default \textwidth
|
||||
% \textbf{Head A} & \textbf{Head B} & \textbf{Head C} \\
|
||||
% a1 & b1 & c1 \\
|
||||
% a2 & b2 & c2 \\
|
||||
% \end{FHGRTable}
|
||||
% Header row is shaded camel; data rows auto-alternate plain / FHGRBlockTitleBg,
|
||||
% so no manual \rowcolor per row is needed. Columns use tabularx (X, l, c, r, ...).
|
||||
% Defined with \NewEnviron, so the body is captured wholesale in \BODY -- write
|
||||
% ordinary rows, no \\ trickery. \rowcolors{2} is what drives the alternation,
|
||||
% starting at row 2 so the camel header keeps its own colour.
|
||||
% =============================
|
||||
\NewEnviron{FHGRTable}[2][\textwidth]{%
|
||||
\rowcolors{2}{FHGRBlockTitleBg}{}%
|
||||
\begin{tabularx}{#1}{#2}%
|
||||
\rowcolor{camel}\BODY
|
||||
\end{tabularx}%
|
||||
}
|
||||
|
||||
|
||||
% =============================
|
||||
% Listings style (opt-in)
|
||||
% Applied to every listing already (\lstset{style=FHGR} below), so just:
|
||||
% \begin{lstlisting}[language=Python,caption=Demo] ... \end{lstlisting}
|
||||
% \lstinputlisting[language=C]{src/main.c}
|
||||
% \lstinline|inline snippet|
|
||||
% A frame containing a listing must be declared \begin{frame}[fragile]{...}.
|
||||
% Override per listing with the usual keys, e.g. [numbers=none,frame=none].
|
||||
% =============================
|
||||
\lstdefinestyle{FHGR}{
|
||||
backgroundcolor=\color{linen},
|
||||
commentstyle=\color{green},
|
||||
keywordstyle=\color{red},
|
||||
numberstyle=\tiny\color{green},
|
||||
stringstyle=\color{blue},
|
||||
basicstyle=\ttfamily\footnotesize\color{black},
|
||||
breaklines=true,
|
||||
captionpos=b,
|
||||
numbers=left,
|
||||
numbersep=5pt,
|
||||
showspaces=false,
|
||||
showstringspaces=false,
|
||||
showtabs=false,
|
||||
tabsize=2,
|
||||
frame=single,
|
||||
}
|
||||
\lstset{style=FHGR}
|
||||
% listings is not UTF-8 aware on its own: map umlauts and ~ to real glyphs.
|
||||
\lstset{literate={Ö}{{\"O}}1 {Ä}{{\"A}}1 {Ü}{{\"U}}1 {ü}{{\"u}}1 {ä}{{\"a}}1 {ö}{{\"o}}1 {~}{{\textasciitilde}}1}
|
||||
% \lstinline inherits the surrounding text colour (white in dark mode, black in
|
||||
% light mode) by overriding basicstyle without a colour in TextStyle mode.
|
||||
\lst@AddToHook{TextStyle}{\lstset{basicstyle=\ttfamily\footnotesize}}
|
||||
|
||||
% =============================
|
||||
% List spacing
|
||||
% =============================
|
||||
\ifFHGR@compactlists
|
||||
\newcommand*\FHGR@compactlistparams{%
|
||||
\setlength{\itemsep}{0.4ex}%
|
||||
\setlength{\topsep}{0.4ex}%
|
||||
\setlength{\parsep}{0pt}% \list derives \parskip from \parsep
|
||||
}
|
||||
\patchcmd{\list}%
|
||||
{\csname @list\romannumeral\the\@listdepth\endcsname}%
|
||||
{\csname @list\romannumeral\the\@listdepth\endcsname
|
||||
\FHGR@compactlistparams}%
|
||||
{}%
|
||||
{\PackageWarning{beamerthemeFHGR}{Could not patch \string\list;
|
||||
compact list spacing is not available}}%
|
||||
\fi
|
||||
|
||||
% =============================
|
||||
% Navigation symbols, progress bar, footline & headline
|
||||
% =============================
|
||||
% `nav=false' (the default) removes beamer's navigation symbol row entirely.
|
||||
\ifFHGR@shownav\else
|
||||
\setbeamertemplate{navigation symbols}{}
|
||||
\fi
|
||||
|
||||
% Headline: current section on the top-left, only with `showsection=true'.
|
||||
% The box is typeset either way, so the 2.2ex strip stays reserved and frame
|
||||
% titles do not jump when a deck mixes both settings.
|
||||
\setbeamertemplate{headline}{%
|
||||
\leavevmode
|
||||
\hbox{\begin{beamercolorbox}[wd=\paperwidth,ht=2.2ex,dp=1ex,leftskip=1em,rightskip=1em]{}
|
||||
\ifFHGR@showsection
|
||||
\usebeamerfont{section in head/foot}\insertsectionhead
|
||||
\fi
|
||||
\end{beamercolorbox}}
|
||||
}
|
||||
|
||||
% Footline: logo | \shortname (or \author) | short title ... frame number,
|
||||
% followed by the progress bar. The logo follows `dark', the counter needs
|
||||
% `framenumber=true', the bar needs `progressbar=true'.
|
||||
\setbeamertemplate{footline}{%
|
||||
\leavevmode
|
||||
\hbox{\begin{beamercolorbox}[wd=\paperwidth,ht=2.8ex,dp=1.2ex,leftskip=1em,rightskip=1em]{}
|
||||
|
||||
\ifFHGR@dark
|
||||
\ifx\FHGR@logowhite\@empty\relax\else
|
||||
\IfFileExists{\FHGR@logowhite}{\raisebox{-0.1ex}{\includegraphics[height=3em]{\FHGR@logowhite}}\hspace{0.6em}}{}%
|
||||
\fi
|
||||
\else
|
||||
\ifx\FHGR@logo\@empty\relax\else
|
||||
\IfFileExists{\FHGR@logo}{\raisebox{-0.1ex}{\includegraphics[height=3em]{\FHGR@logo}}\hspace{0.6em}}{}%
|
||||
\fi
|
||||
\fi
|
||||
{\scriptsize \color{FHGRDeco}\FHGR@footmeta}
|
||||
\hfill
|
||||
\ifFHGR@shownumber{\color{FHGRDeco}
|
||||
\scriptsize\insertframenumber\,/\,\inserttotalframenumber}\fi
|
||||
\end{beamercolorbox}}
|
||||
% Progress bar: width = frame / total, drawn as an overlay on the bottom edge.
|
||||
% The \pgfmath scratch macros are scoped, so the result has to be \global to
|
||||
% survive \endgroup and reach the tikzpicture below.
|
||||
\ifFHGR@progressbar
|
||||
\begingroup
|
||||
\count255=\inserttotalframenumber\relax
|
||||
\ifnum\count255<1 \count255=1\fi
|
||||
\pgfmathsetmacro{\FHGR@ratio}{\insertframenumber/\the\count255}
|
||||
\pgfmathparse{\FHGR@ratio*\paperwidth}%
|
||||
\global\edef\FHGR@pbLen{\pgfmathresult pt}% <-- global!
|
||||
\endgroup
|
||||
|
||||
\begin{tikzpicture}[remember picture,overlay]
|
||||
\fill[FHGRDeco] (current page.south west)
|
||||
rectangle ([xshift=\FHGR@pbLen,yshift=1pt] current page.south west);
|
||||
\end{tikzpicture}%
|
||||
\fi
|
||||
}
|
||||
|
||||
% =============================
|
||||
% Background & title page
|
||||
% =============================
|
||||
|
||||
% Deliberately empty: the page colour comes from \pagecolor (see "Colors"), and
|
||||
% \FHGRClosingPage installs its own background template when it needs one.
|
||||
\setbeamertemplate{background}{%
|
||||
}
|
||||
|
||||
% Title page, drawn as one tikz overlay: background image (titlebg,
|
||||
% titlefillimage), fade PNG (titlegradient), logo (biglogoblack/biglogowhite,
|
||||
% picked by `dark'), \inserttitle/\insertsubtitle, then the author meta line
|
||||
% built from \author + \shortname + \fullname. Activated at the end of this
|
||||
% block; render it with \FHGRTitlePage or beamer's plain \titlepage.
|
||||
\defbeamertemplate*{title page}{FHGR}[1][]{%
|
||||
\begingroup
|
||||
\begin{tikzpicture}[remember picture,overlay]
|
||||
|
||||
% Full-page background image
|
||||
\ifx\FHGR@titlebg\@empty\relax\else
|
||||
\IfFileExists{\FHGR@titlebg}{%
|
||||
\node[
|
||||
anchor=south west,
|
||||
inner sep=0pt,
|
||||
outer sep=0pt
|
||||
] at (current page.south west) {%
|
||||
\ifFHGR@titlefillimage
|
||||
\includegraphics[
|
||||
width=\paperwidth,
|
||||
height=\paperheight,
|
||||
keepaspectratio=false
|
||||
]{\FHGR@titlebg}%
|
||||
\else
|
||||
\includegraphics[
|
||||
width=\paperwidth,
|
||||
height=\paperheight,
|
||||
keepaspectratio
|
||||
]{\FHGR@titlebg}%
|
||||
\fi
|
||||
};
|
||||
}{}%
|
||||
\fi
|
||||
|
||||
% Smooth gradient overlay using PNG with alpha channel
|
||||
\ifFHGR@titlegradient
|
||||
\ifFHGR@dark
|
||||
\IfFileExists{pics/theme_pics/titlefade_dark.png}{%
|
||||
\node[
|
||||
anchor=south west,
|
||||
inner sep=0pt,
|
||||
outer sep=0pt
|
||||
] at (current page.south west) {%
|
||||
\includegraphics[
|
||||
width=\paperwidth,
|
||||
height=\paperheight
|
||||
]{pics/theme_pics/titlefade_dark.png}%
|
||||
};
|
||||
}{}%
|
||||
\else
|
||||
\IfFileExists{pics/theme_pics/titlefade_light.png}{%
|
||||
\node[
|
||||
anchor=south west,
|
||||
inner sep=0pt,
|
||||
outer sep=0pt
|
||||
] at (current page.south west) {%
|
||||
\includegraphics[
|
||||
width=\paperwidth,
|
||||
height=\paperheight
|
||||
]{pics/theme_pics/titlefade_light.png}%
|
||||
};
|
||||
}{}%
|
||||
\fi
|
||||
\fi
|
||||
|
||||
% Logo top-left
|
||||
\ifFHGR@dark
|
||||
\IfFileExists{\FHGR@biglogowhite}{%
|
||||
\node[
|
||||
anchor=north west,
|
||||
inner sep=0mm,
|
||||
outer sep=3mm
|
||||
] at (current page.north west) {%
|
||||
\includegraphics[height=2.5em]{\FHGR@biglogowhite}%
|
||||
};
|
||||
}{}%
|
||||
\else
|
||||
\IfFileExists{\FHGR@biglogoblack}{%
|
||||
\node[
|
||||
anchor=north west,
|
||||
inner sep=0mm,
|
||||
outer sep=3mm
|
||||
] at (current page.north west) {%
|
||||
\includegraphics[height=2.5em]{\FHGR@biglogoblack}%
|
||||
};
|
||||
}{}%
|
||||
\fi
|
||||
|
||||
% Title/subtitle block
|
||||
\node[
|
||||
anchor=south west,
|
||||
text width=.8\paperwidth,
|
||||
inner sep=0pt
|
||||
] at ([xshift=8mm,yshift=25mm]current page.south west) {%
|
||||
{\usebeamerfont{title}\color{FHGRTxt}\bfseries\inserttitle\par}
|
||||
\vspace{0.6ex}
|
||||
{\usebeamerfont{subtitle}\color{FHGRTxt}\insertsubtitle\par}
|
||||
};
|
||||
|
||||
% Author/meta line at the very bottom-left
|
||||
\node[
|
||||
anchor=south west,
|
||||
inner sep=0pt
|
||||
] at ([xshift=1mm,yshift=1mm]current page.south west) {%
|
||||
{\scriptsize\color{FHGRDeco}\FHGR@titlemeta}
|
||||
};
|
||||
|
||||
\end{tikzpicture}
|
||||
\endgroup
|
||||
}
|
||||
|
||||
% ============================================
|
||||
% \FHGRTitlePage[<extra>]
|
||||
% - wraps \titlepage in one [plain,noframenumbering] frame, so the title slide
|
||||
% carries no headline/footline and is not counted
|
||||
% - <extra> is placed inside that frame, after the title page:
|
||||
% \FHGRTitlePage
|
||||
% \FHGRTitlePage[\note{Welcome, introduce yourself}]
|
||||
% ============================================
|
||||
\newcommand{\FHGRTitlePage}[1][]{%
|
||||
\begin{frame}[plain,noframenumbering]
|
||||
\titlepage
|
||||
#1
|
||||
\end{frame}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
% Select our title page
|
||||
\setbeamertemplate{title page}[FHGR]
|
||||
|
||||
% =============================
|
||||
% Appendix
|
||||
% Write \appendix before your backup slides: appendixnumberbeamer restarts
|
||||
% the frame numbering there, and the \pretocmd below additionally swaps in a
|
||||
% footline without the "n / total" counter, so backup slides are not counted.
|
||||
% (The \makeatletter/\makeatother pairs in this file are no-ops inside a .sty;
|
||||
% they are kept so these blocks can be pasted into a preamble unchanged.)
|
||||
% =============================
|
||||
|
||||
% Bookmarks are plain PDF strings, where \translate cannot be executed: make it
|
||||
% expand to its argument so translated headings stay readable in the outline.
|
||||
\makeatletter
|
||||
\pdfstringdefDisableCommands{%
|
||||
\let\translate\@firstofone % \translate{Text} -> "Text"
|
||||
}
|
||||
\makeatother
|
||||
|
||||
|
||||
\makeatletter
|
||||
\pretocmd{\appendix}{%
|
||||
% Footline without the frame counter (the appendix restarts numbering, so a
|
||||
% "n / total" reading from here on would be misleading).
|
||||
\setbeamertemplate{footline}{%
|
||||
\leavevmode
|
||||
\hbox{\begin{beamercolorbox}[wd=\paperwidth,ht=2.8ex,dp=1.2ex,leftskip=1em,rightskip=1em]{}
|
||||
\ifFHGR@dark
|
||||
\ifx\FHGR@logowhite\@empty\relax\else
|
||||
\IfFileExists{\FHGR@logowhite}{\raisebox{-0.1ex}{\includegraphics[height=3em]{\FHGR@logowhite}}}{}%
|
||||
\fi
|
||||
\else
|
||||
\ifx\FHGR@logo\@empty\relax\else
|
||||
\IfFileExists{\FHGR@logo}{\raisebox{-0.1ex}{\includegraphics[height=3em]{\FHGR@logo}}}{}%
|
||||
\fi
|
||||
\fi
|
||||
{\scriptsize \color{FHGRDeco}\FHGR@footmeta}
|
||||
\hfill
|
||||
\end{beamercolorbox}}%
|
||||
}%
|
||||
}{}{}
|
||||
\makeatother
|
||||
|
||||
% ============================================
|
||||
% TOC frame with image on the left
|
||||
% \FHGRToC[<toc options>][<image>]{<title>}[<extra>]
|
||||
% - <toc options> -> passed to \tableofcontents
|
||||
% e.g. currentsection,currentsubsection
|
||||
% - <image> -> optional; if empty use \FHGR@titlebg
|
||||
% - <title> -> frame title, set in the frametitle font/colour
|
||||
% - <extra> -> optional; added at the end of the frame, e.g. \note{...}
|
||||
% Examples:
|
||||
% \FHGRToC{Agenda}
|
||||
% \FHGRToC[currentsection][pics/chapter2.png]{Where we are}
|
||||
% ============================================
|
||||
|
||||
% Internal helper (used by \FHGRToC): image + fade on the left half of the
|
||||
% slide, then an opaque FHGRBg panel on the right half to hold the ToC.
|
||||
\makeatletter
|
||||
\newcommand{\FHGR@tocimage}[1]{%
|
||||
\begin{tikzpicture}[remember picture,overlay]
|
||||
% Decide which image to use: argument or fallback to titlebg
|
||||
\def\FHGR@img{#1}%
|
||||
\ifx\FHGR@img\@empty
|
||||
\def\FHGR@img{\FHGR@titlebg}%
|
||||
\fi
|
||||
|
||||
% Draw image on the left half, full height
|
||||
\ifx\FHGR@img\@empty\relax\else
|
||||
\IfFileExists{\FHGR@img}{%
|
||||
\node[
|
||||
anchor=south west,
|
||||
inner sep=0pt,
|
||||
outer sep=0pt
|
||||
] at (current page.south west)
|
||||
{\includegraphics[height=\paperheight]{\FHGR@img}};
|
||||
}{}%
|
||||
\fi
|
||||
|
||||
% Gradient overlay on the image half
|
||||
\ifFHGR@titlegradient
|
||||
\ifFHGR@dark
|
||||
\IfFileExists{pics/theme_pics/titlefade_dark.png}{%
|
||||
\node[
|
||||
anchor=south west,
|
||||
inner sep=0pt,
|
||||
outer sep=0pt
|
||||
] at (current page.south west)
|
||||
{\includegraphics[width=.5\paperwidth,height=\paperheight]{pics/theme_pics/titlefade_dark.png}};
|
||||
}{}%
|
||||
\else
|
||||
\IfFileExists{pics/theme_pics/titlefade_light.png}{%
|
||||
\node[
|
||||
anchor=south west,
|
||||
inner sep=0pt,
|
||||
outer sep=0pt
|
||||
] at (current page.south west)
|
||||
{\includegraphics[width=.5\paperwidth,height=\paperheight]{pics/theme_pics/titlefade_light.png}};
|
||||
}{}%
|
||||
\fi
|
||||
\fi
|
||||
|
||||
% Panel on the right half for the table of contents
|
||||
\fill[FHGRBg]
|
||||
([xshift=-.5\paperwidth]current page.north east)
|
||||
rectangle
|
||||
(current page.south east);
|
||||
\end{tikzpicture}%
|
||||
}
|
||||
|
||||
% \FHGRToC[<toc options>][<image>]{<title>}[<extra>] -- see the block above
|
||||
\NewDocumentCommand{\FHGRToC}{ O{} O{} m O{}}{%
|
||||
\begin{frame}
|
||||
\FHGR@tocimage{#2}%
|
||||
\begin{columns}[T,totalwidth=\paperwidth]
|
||||
\column{0.5\paperwidth}
|
||||
\column{0.5\paperwidth}
|
||||
{\usebeamerfont{frametitle}%
|
||||
\usebeamercolor[fg]{frametitle}%
|
||||
\raggedright #3\par}%
|
||||
\vspace{2em}%
|
||||
\tableofcontents[#1]
|
||||
\end{columns}
|
||||
#4
|
||||
\end{frame}
|
||||
}
|
||||
\makeatother
|
||||
|
||||
% ============================================
|
||||
% Final slide
|
||||
%
|
||||
% \FHGRClosingPage [<image>] [<text>] -> fills slide (may stretch)
|
||||
% \FHGRClosingPage*[<image>] [<text>] -> keepaspectratio
|
||||
% - If <image> empty: uses \FHGR@titlebg
|
||||
% - <text> optional: centered on slide
|
||||
% Examples:
|
||||
% \FHGRClosingPage % background only
|
||||
% \FHGRClosingPage[][Thank you!] % default image + centered text
|
||||
% \FHGRClosingPage*[pics/outro.png][Q&A] % own image, aspect kept
|
||||
% \usebackgroundtemplate is set inside a \begingroup, so the background does
|
||||
% not leak into the following slides. The frame itself is counted as usual.
|
||||
% ============================================
|
||||
|
||||
\makeatletter
|
||||
\NewDocumentCommand{\FHGRClosingPage}{ s O{} O{} }{%
|
||||
\begingroup
|
||||
|
||||
% Decide which image to use: argument or fallback to titlebg
|
||||
\def\FHGR@img{#2}%
|
||||
\ifx\FHGR@img\@empty
|
||||
\def\FHGR@img{\FHGR@titlebg}%
|
||||
\fi
|
||||
|
||||
% Background image
|
||||
\ifx\FHGR@img\@empty\relax\else
|
||||
\IfFileExists{\FHGR@img}{%
|
||||
\IfBooleanTF{#1}{%
|
||||
% Starred: keep aspect ratio
|
||||
\usebackgroundtemplate{%
|
||||
\vbox to \paperheight{%
|
||||
\vfil
|
||||
\hbox to \paperwidth{%
|
||||
\hfil
|
||||
\includegraphics[
|
||||
width=\paperwidth,
|
||||
height=\paperheight,
|
||||
keepaspectratio
|
||||
]{\FHGR@img}%
|
||||
\hfil
|
||||
}%
|
||||
\vfil
|
||||
}%
|
||||
}%
|
||||
}{%
|
||||
% Unstarred: fill whole slide
|
||||
\usebackgroundtemplate{%
|
||||
{\setkeys{Gin}{keepaspectratio=false}%
|
||||
\includegraphics[
|
||||
width=\paperwidth,
|
||||
height=\paperheight
|
||||
]{\FHGR@img}}%
|
||||
}%
|
||||
}%
|
||||
}{}%
|
||||
\fi
|
||||
|
||||
\frame{%
|
||||
% Gradient overlay across the whole slide
|
||||
\ifFHGR@titlegradient
|
||||
\begin{tikzpicture}[remember picture,overlay]
|
||||
\ifFHGR@dark
|
||||
\IfFileExists{pics/theme_pics/titlefade_dark.png}{%
|
||||
\node[
|
||||
anchor=south west,
|
||||
inner sep=0pt,
|
||||
outer sep=0pt
|
||||
] at (current page.south west) {%
|
||||
\includegraphics[
|
||||
width=\paperwidth,
|
||||
height=\paperheight
|
||||
]{pics/theme_pics/titlefade_dark.png}%
|
||||
};
|
||||
}{}%
|
||||
\else
|
||||
\IfFileExists{pics/theme_pics/titlefade_light.png}{%
|
||||
\node[
|
||||
anchor=south west,
|
||||
inner sep=0pt,
|
||||
outer sep=0pt
|
||||
] at (current page.south west) {%
|
||||
\includegraphics[
|
||||
width=\paperwidth,
|
||||
height=\paperheight
|
||||
]{pics/theme_pics/titlefade_light.png}%
|
||||
};
|
||||
}{}%
|
||||
\fi
|
||||
\end{tikzpicture}%
|
||||
\fi
|
||||
|
||||
% Optional centered text
|
||||
\def\FHGR@finaltext{#3}%
|
||||
\ifx\FHGR@finaltext\@empty\relax\else
|
||||
\begin{tikzpicture}[remember picture,overlay]
|
||||
\node[
|
||||
anchor=center,
|
||||
align=center
|
||||
] at (current page.center) {%
|
||||
{\usebeamerfont{title}\bfseries\color{FHGRTxt}\FHGR@finaltext}
|
||||
};
|
||||
\end{tikzpicture}%
|
||||
\fi
|
||||
}%
|
||||
|
||||
\endgroup
|
||||
}
|
||||
\makeatother
|
||||
|
||||
% =============================
|
||||
% Convenience commands: small attribution lines, e.g. under a figure.
|
||||
% \credit{Jane Doe} -> "Credit: Jane Doe"
|
||||
% \imagesource{FHGR} -> "Bildquelle: FHGR"
|
||||
% \source{Studie 2024} -> "Quelle: Studie 2024"
|
||||
% Each one breaks the paragraph and flushes right, \tiny italic in FHGRDeco.
|
||||
% Only the label differs -- pick by language, or \renewcommand one of them.
|
||||
% =============================
|
||||
\newcommand{\credit}[1]{\par\hfill {\tiny\color{FHGRDeco} Credit:\,\itshape #1}}
|
||||
\newcommand{\imagesource}[1]{\par\hfill {\tiny\color{FHGRDeco} Bildquelle:\,\itshape #1}}
|
||||
\newcommand{\source}[1]{\par\hfill {\tiny\color{FHGRDeco} Quelle:\,\itshape #1}}
|
||||
|
||||
% =============================
|
||||
% End of file
|
||||
% =============================
|
||||
BIN
Folien/original_default_theme/AISE502_Vorlesung_1_Folien.pdf
Normal file
776
Folien/original_default_theme/AISE502_Vorlesung_1_Folien.tex
Normal file
@ -0,0 +1,776 @@
|
||||
\documentclass[aspectratio=169,12pt]{beamer}
|
||||
|
||||
% ============================================
|
||||
% THEME AND APPEARANCE
|
||||
% ============================================
|
||||
\usetheme{default}
|
||||
\usecolortheme{default}
|
||||
\usefonttheme{professionalfonts}
|
||||
\setbeamertemplate{navigation symbols}{}
|
||||
\setbeamertemplate{footline}{}
|
||||
\setbeamertemplate{frametitle continuation}{}
|
||||
|
||||
% ============================================
|
||||
% PACKAGES
|
||||
% ============================================
|
||||
\usepackage[utf8]{inputenc}
|
||||
\usepackage[T1]{fontenc}
|
||||
\usepackage[british]{babel}
|
||||
\usepackage{graphicx}
|
||||
\usepackage{hyperref}
|
||||
\usepackage{xcolor}
|
||||
\usepackage{booktabs}
|
||||
\usepackage{tcolorbox}
|
||||
\usepackage{amsmath}
|
||||
\usepackage{amssymb}
|
||||
\usepackage{tikz}
|
||||
\usetikzlibrary{shapes.geometric, arrows.meta, positioning, fit, backgrounds, calc}
|
||||
|
||||
% ============================================
|
||||
% COLORS (same as script)
|
||||
% ============================================
|
||||
\definecolor{bankblue}{rgb}{0.0,0.28,0.67}
|
||||
\definecolor{bankgreen}{rgb}{0.13,0.55,0.13}
|
||||
\definecolor{bankred}{rgb}{0.7,0.13,0.13}
|
||||
\definecolor{aiviolet}{rgb}{0.42,0.19,0.58}
|
||||
\definecolor{backcolour}{rgb}{0.95,0.95,0.92}
|
||||
\definecolor{codegray}{rgb}{0.5,0.5,0.5}
|
||||
|
||||
% Beamer color setup
|
||||
\setbeamercolor{structure}{fg=bankblue}
|
||||
\setbeamercolor{frametitle}{fg=white,bg=bankblue}
|
||||
\setbeamercolor{title}{fg=white,bg=bankblue}
|
||||
\setbeamercolor{block title}{fg=white,bg=bankblue}
|
||||
\setbeamercolor{block body}{bg=blue!5!white}
|
||||
\setbeamercolor{block title alerted}{fg=white,bg=bankred}
|
||||
\setbeamercolor{block body alerted}{bg=red!5!white}
|
||||
\setbeamercolor{block title example}{fg=white,bg=bankgreen}
|
||||
\setbeamercolor{block body example}{bg=green!5!white}
|
||||
\setbeamercolor{item}{fg=bankblue}
|
||||
\setbeamercolor{subitem}{fg=bankblue!80}
|
||||
\setbeamercolor{itemize item}{fg=bankblue}
|
||||
\setbeamercolor{enumerate item}{fg=bankblue}
|
||||
|
||||
% Bullet style
|
||||
\setbeamertemplate{itemize item}{\raisebox{0.12ex}{$\blacktriangleright$}}
|
||||
\setbeamertemplate{itemize subitem}{\raisebox{0.12ex}{\small$\triangleright$}}
|
||||
\setbeamertemplate{enumerate items}[default]
|
||||
|
||||
% ============================================
|
||||
% CUSTOM TCOLORBOXES (same as script)
|
||||
% ============================================
|
||||
\newtcolorbox{keypoint}{
|
||||
colback=blue!5!white,
|
||||
colframe=bankblue,
|
||||
title=Key Concept,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{examplebox}[1][]{
|
||||
colback=green!5!white,
|
||||
colframe=bankgreen,
|
||||
title={Example: #1},
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{definitionbox}[1][]{
|
||||
colback=yellow!5!white,
|
||||
colframe=yellow!50!black,
|
||||
title={Definition: #1},
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{thinkbox}{
|
||||
colback=orange!5!white,
|
||||
colframe=orange!60!black,
|
||||
title=Discussion,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{hinweisbox}{
|
||||
colback=red!5!white,
|
||||
colframe=bankred,
|
||||
title=Important Note,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{ailinse}[1][]{
|
||||
colback=violet!5!white,
|
||||
colframe=aiviolet,
|
||||
title={AI Lens: #1},
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{projektbox}{
|
||||
colback=blue!3!white,
|
||||
colframe=bankblue!70,
|
||||
title=Project Link: Portfolio Intelligence Platform,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
% ============================================
|
||||
% FOOTER WITH LOGO
|
||||
% ============================================
|
||||
\setbeamertemplate{footline}{%
|
||||
\leavevmode%
|
||||
\hbox{%
|
||||
\begin{beamercolorbox}[wd=0.5\paperwidth,ht=2ex,dp=0.5ex,leftskip=0.5em]{footline}%
|
||||
\usebeamerfont{footline}\textcolor{codegray}{\tiny\insertframenumber{} / \inserttotalframenumber}%
|
||||
\end{beamercolorbox}%
|
||||
\begin{beamercolorbox}[wd=0.35\paperwidth,ht=2ex,dp=0.5ex,center]{footline}%
|
||||
\usebeamerfont{footline}\textcolor{codegray}{\tiny AISE502 -- AI in Software Engineering II}%
|
||||
\end{beamercolorbox}%
|
||||
\begin{beamercolorbox}[wd=0.15\paperwidth,ht=2ex,dp=0.5ex,rightskip=0.5em,right]{footline}%
|
||||
\includegraphics[height=1.5ex]{FHGR_Logo_small}%
|
||||
\end{beamercolorbox}%
|
||||
}%
|
||||
\vskip0pt%
|
||||
}
|
||||
|
||||
% ============================================
|
||||
% DOCUMENT
|
||||
% ============================================
|
||||
\begin{document}
|
||||
|
||||
% ============================================
|
||||
% TITLE SLIDE
|
||||
% ============================================
|
||||
{
|
||||
\setbeamertemplate{footline}{}
|
||||
\begin{frame}[plain]
|
||||
\vfill
|
||||
\begin{center}
|
||||
\includegraphics[width=0.3\textwidth]{FHGR_Logo_Large}\\[1cm]
|
||||
{\LARGE\bfseries\textcolor{bankblue}{AISE502: AI in Software Engineering II}}\\[0.6cm]
|
||||
{\large Lecture 1: Architecture as a Decision Problem}\\[0.3cm]
|
||||
{\small\textcolor{codegray}{Script: Part I, Sections 1--2}}\\[0.8cm]
|
||||
{\normalsize Dr.\ Florian Herzog}\\[0.2cm]
|
||||
{\small Fachhochschule Graub\"unden, Chur}\\[0.2cm]
|
||||
{\small Autumn Semester 2026}
|
||||
\end{center}
|
||||
\vfill
|
||||
\end{frame}
|
||||
}
|
||||
|
||||
% ============================================
|
||||
% AGENDA
|
||||
% ============================================
|
||||
\begin{frame}{Agenda}
|
||||
\begin{enumerate}
|
||||
\item The module: aims, assessment, semester plan, project
|
||||
\item Four production systems -- two facts
|
||||
\item The decision problem
|
||||
\item What software architecture is (and is not)
|
||||
\item The framework at a glance
|
||||
\item The two AI axes of this module
|
||||
\item Six load-bearing assumptions (A1--A6)
|
||||
\item From questions to dimensions
|
||||
\end{enumerate}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% SECTION 1: THE MODULE
|
||||
% ============================================
|
||||
\section{The Module}
|
||||
|
||||
\begin{frame}{The module in one question}
|
||||
\begin{keypoint}
|
||||
\emph{How do I design, justify, and operate the structure of a software system so that it meets its quality attributes and remains maintainable for years -- even when individual components (AI) are non-deterministic, fallible, and expensive?}
|
||||
\end{keypoint}
|
||||
|
||||
\vspace{0.4cm}
|
||||
This module makes that question \textbf{decidable} -- with a framework of five elements:
|
||||
\begin{itemize}
|
||||
\item a \textbf{demand side} (what the application requires),
|
||||
\item a \textbf{supply side} (what a structure can deliver),
|
||||
\item a \textbf{matching rule}, a \textbf{decision record}, and a \textbf{measurement contract}.
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\textcolor{codegray}{\small Lectures in German -- all materials, the script, and the exam in English.}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Learning objectives}
|
||||
After this module you can \dots
|
||||
\begin{itemize}
|
||||
\item explain why architecture selection is a \textbf{matching problem} -- no pattern is good or bad in itself
|
||||
\item construct a \textbf{requirements profile} $R(a)$: scenarios with response measures, utility tree, weights
|
||||
\item derive the \textbf{capability profile} $C(p)$ of seven architectural patterns from their tactics
|
||||
\item run the \textbf{three-stage, non-compensatory match} and defend the result
|
||||
\item record decisions as \textbf{ADRs} and attach a \textbf{measurement contract} (fitness functions, DORA)
|
||||
\item engineer \textbf{AI components} into a system (Axis B) and use \textbf{AI tools} in the process (Axis A) -- with the same discipline
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Assessment}
|
||||
\begin{columns}[T]
|
||||
\begin{column}{0.48\textwidth}
|
||||
\begin{block}{Project (50\,\%)}
|
||||
\begin{itemize}
|
||||
\item Portfolio Intelligence Platform (group work, all semester)
|
||||
\item Requirements dossier (A1, week 3)
|
||||
\item Architecture dossier: ADR $+$ measurement contract (A2, week 7)
|
||||
\item Implementation (weeks 8--13)
|
||||
\item Final presentation with \textbf{architecture defence} (week 14)
|
||||
\end{itemize}
|
||||
\end{block}
|
||||
\end{column}
|
||||
\begin{column}{0.48\textwidth}
|
||||
\begin{block}{Written examination (50\,\%)}
|
||||
\begin{itemize}
|
||||
\item End of semester, 60 minutes
|
||||
\item \textbf{Open book:} script and own notes, on paper
|
||||
\item \textbf{Closed internet}
|
||||
\item Focus: architecture reasoning -- profiles, matching, trade-offs
|
||||
\end{itemize}
|
||||
\end{block}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{The semester at a glance}
|
||||
\small
|
||||
\begin{center}
|
||||
\begin{tabular}{@{}p{1.5cm}p{4.3cm}p{4.2cm}p{2.7cm}@{}}
|
||||
\toprule
|
||||
\textbf{Weeks} & \textbf{Lectures} & \textbf{Exercise / project} & \textbf{Deliverables} \\
|
||||
\midrule
|
||||
1--3 & Part I: the framework -- dimensions, scenarios, weights & Kickoff; requirements workshops & \textbf{A1} (week 3) \\
|
||||
4--7 & Part II: seven patterns; the match & Architecture study; the match; design & \textbf{A2 $+$ design gate} (week 7) \\
|
||||
8--13 & Parts III--V: classes, fit at scale, the AI dimension & Implementation sprints $+$ coaching & Milestones (weeks 9/11/13) \\
|
||||
14 & Synthesis, exam preparation & \textbf{Presentations $+$ defence} & \textbf{A3} \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\textbf{Design phase} (weeks 1--7): 2 lessons lecture $+$ 2 exercise -- design first, code later.\\
|
||||
\textbf{Implementation phase} (weeks 8--13): 3 lessons lecture $+$ 1 coaching.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{The course project}
|
||||
\begin{projektbox}
|
||||
You will design and build an \textbf{AI-native advisory platform}: answers generated by LLMs over a grounded knowledge base, with deterministic services for portfolio analytics around them. Everything this module teaches -- profiles, matching, ADRs, measurement -- you will apply to \emph{this} system, and defend at the end.
|
||||
\end{projektbox}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\textbf{This week (kickoff exercise):}
|
||||
\begin{itemize}
|
||||
\item form teams; set up repository and tooling (including agentic coding tools)
|
||||
\item build domain understanding; sketch a first ontology
|
||||
\item collect \emph{raw} stakeholder wishes -- unfiltered, unweighted
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\textcolor{codegray}{\small Next week those wishes become \emph{scenarios}; in week 3 they become your requirements profile (deliverable A1).}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% SECTION 2: FOUR SYSTEMS, TWO FACTS
|
||||
% ============================================
|
||||
\section{Four Production Systems -- Two Facts}
|
||||
|
||||
\begin{frame}{Discussion}
|
||||
\begin{thinkbox}
|
||||
\begin{itemize}
|
||||
\item Which software architectures can you name -- and which is the \emph{best} one?
|
||||
\item Is a monolith outdated? Are microservices the professional default?
|
||||
\item Netflix and Amazon run microservices. Should your two-person startup?
|
||||
\item How would you even \emph{decide} -- and how would you defend the decision a year later?
|
||||
\end{itemize}
|
||||
\end{thinkbox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Four production systems, four structures}
|
||||
\footnotesize
|
||||
\begin{center}
|
||||
\begin{tabular}{@{}p{2.2cm}p{4.5cm}p{6.4cm}@{}}
|
||||
\toprule
|
||||
\textbf{System} & \textbf{Structure} & \textbf{Documented outcome} \\
|
||||
\midrule
|
||||
Stack Overflow & \texttt{.NET} monolith, $\sim 9$ on-premise web servers & $\sim 1.3$ billion page views/month at $\sim 12$\,ms render -- scaled \emph{up}, not \emph{out} \\
|
||||
Monzo & $\sim 2{,}800$ Go microservices; one language, one monorepo & retail banking at scale -- viable through extreme technological homogeneity \\
|
||||
Segment & $> 140$ microservices, one per analytics destination & public 2018 \textbf{rollback to a monolith}: complexity crushed a small team \\
|
||||
Prime Video & serverless orchestration: Step Functions, Lambda, S3 & consolidation into one process cut infrastructure cost by $> 90\,\%$ \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\textcolor{codegray}{\scriptsize Sources: Craver 2016; Sewell 2024; Noonan 2018; Kolny 2023 -- each described by the system's own engineers.}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Reading the four cases}
|
||||
\begin{columns}[T]
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankgreen}{\textbf{Same problem, opposite structures}}
|
||||
\begin{itemize}
|
||||
\item Monzo and Stack Overflow both serve millions of users, interactively, at high availability
|
||||
\item one does it with $\sim 2{,}800$ deployment units -- the other with essentially \textbf{one}
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankred}{\textbf{Fashionable structure, expensive failure}}
|
||||
\begin{itemize}
|
||||
\item Prime Video: distributed boundaries in the middle of a tightly coupled data flow
|
||||
\item Segment: services cut along \emph{configuration instances}, not domain seams
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
|
||||
\vspace{0.4cm}
|
||||
\begin{hinweisbox}
|
||||
Neither fact proves monoliths good or microservices bad. Each failure was a \textbf{mismatch} between a workload and a structure -- not a bad pattern.
|
||||
\end{hinweisbox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Two facts -- and the maxim they force}
|
||||
\textbf{Fact 1: Structures differ radically for similar-looking problems.}\\
|
||||
\textcolor{codegray}{\small The grade portal and Instagram share the same load question -- at different magnitudes.}
|
||||
|
||||
\vspace{0.3cm}
|
||||
\textbf{Fact 2: No structure dominates.}\\
|
||||
\textcolor{codegray}{\small For every pattern there is a documented context where it failed expensively -- and one where its unfashionable opposite succeeded at scale (Instagram, Shopify).}
|
||||
|
||||
\vspace{0.4cm}
|
||||
\begin{keypoint}
|
||||
\textbf{Maxim 1.} Patterns are neither good nor bad; only the \textbf{fit} between a requirements profile and a capability profile is.
|
||||
\end{keypoint}
|
||||
|
||||
\vspace{0.3cm}
|
||||
The decision problem: choose among \textbf{non-dominated} alternatives whose value depends on the \textbf{match} -- knowing the choice is \textbf{expensive to reverse}.
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% SECTION 3: WHAT ARCHITECTURE IS
|
||||
% ============================================
|
||||
\section{What Software Architecture Is}
|
||||
|
||||
\begin{frame}{What is ``software architecture''?}
|
||||
The term has a documented tendency to mean \emph{everything and therefore nothing} (Fowler 2003).
|
||||
|
||||
\vspace{0.3cm}
|
||||
\begin{definitionbox}[Software architecture (ISO/IEC/IEEE 42010:2022)]
|
||||
``Fundamental concepts or properties of an entity in its environment and governing principles for the realization and evolution of this entity and its related life cycle processes.''
|
||||
\end{definitionbox}
|
||||
|
||||
\vspace{0.3cm}
|
||||
The standard also creates one \textbf{obligation} this module builds on directly:\\
|
||||
a conformant architecture description \textbf{must record architecture decisions \emph{and their rationale}} (Clause 6.10).
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Four definition families -- each contributes one element}
|
||||
\footnotesize
|
||||
\begin{columns}[T]
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankblue}{\textbf{1. Normative (ISO 42010)}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item shared vocabulary: stakeholders, concerns, views
|
||||
\item obligation: record decisions $+$ rationale
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\textcolor{bankblue}{\textbf{2. Decision-centric (Booch)}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item the \emph{significant} decisions -- significance $=$ \textbf{cost of change}
|
||||
\item lost decision knowledge (\emph{knowledge vaporization}) $\to$ erosion
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankblue}{\textbf{3. Social (Fowler/Johnson)}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item the experts' \emph{shared understanding}; ``the important stuff''
|
||||
\item perceived \textbf{irreversibility} is the core -- architects work to \emph{remove} it
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\textcolor{bankblue}{\textbf{4. Structural-analytic (SEI)}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item ``the set of structures needed to reason about the system''
|
||||
\item functionality is structure-neutral; structure determines \emph{how well}
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
|
||||
\vspace{0.05cm}
|
||||
\begin{keypoint}
|
||||
Distilled: \emph{architecture is the set of hard-to-reverse structural decisions that determine the quality behaviour of a system.}
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Architecture -- design -- implementation: a cost-of-change boundary}
|
||||
\begin{center}
|
||||
\footnotesize
|
||||
\begin{tabular}{@{}llll@{}}
|
||||
\toprule
|
||||
\textbf{Level} & \textbf{Example decision} & \textbf{Reversal cost} & \\
|
||||
\midrule
|
||||
\textcolor{bankred}{Architecture} & monolith vs.\ microservices & months (a migration) & hard to reverse \\
|
||||
\textcolor{bankblue}{Design} & choice of logging library & days (behind an interface) & revisable \\
|
||||
\textcolor{bankgreen}{Implementation} & a variable name & seconds & trivial \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.3cm}
|
||||
\begin{itemize}
|
||||
\item The boundary is \textbf{gradual and context-dependent}: a database choice is architectural without a persistence abstraction -- closer to design in a hexagonal system
|
||||
\item That is the point: \textbf{good architecture pushes decisions from irreversible towards reversible}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Two refusals -- enforced throughout the module}
|
||||
\begin{columns}[T]
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankred}{\textbf{No fashion}}
|
||||
\begin{itemize}
|
||||
\item the dominance claim behind every hype cycle is falsified by the four production cases
|
||||
\item no pattern is chosen because it is modern
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankred}{\textbf{No taste}}
|
||||
\begin{itemize}
|
||||
\item a claim that cannot be measured or falsified has no place in an architectural decision
|
||||
\item ``elegant'' is not an argument -- a response measure is
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
|
||||
\vspace{0.4cm}
|
||||
\begin{hinweisbox}
|
||||
Every judgement in this module must trace to a \textbf{measurable} property of a \textbf{documented} context.
|
||||
\end{hinweisbox}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% SECTION 4: THE FRAMEWORK
|
||||
% ============================================
|
||||
\section{The Framework at a Glance}
|
||||
|
||||
\begin{frame}{The framework: five elements}
|
||||
\begin{definitionbox}[Architecture--application fit]
|
||||
\footnotesize
|
||||
\begin{enumerate}
|
||||
\item \textbf{Requirements profile} $R(a) = \bigl(w_1, \dots, w_{12};\; S(a);\; K(a)\bigr)$ -- priority weights (High/Medium/Low), workload shape, hard constraints: the \emph{demand side}
|
||||
\item \textbf{Capability profile} $C(p) = \bigl(c_1, \dots, c_{12};\; S(p)\bigr)$ -- ordinal ratings $\{++, +, \circ, -, --\}$ plus native workload shape: the \emph{supply side}
|
||||
\item \textbf{Fit} $\mathrm{fit}(a,p)$ -- an ordinal, \emph{non-compensatory} match, computed by rules, not arithmetic
|
||||
\item \textbf{Architecture Decision Record (ADR)} -- the permanent, auditable record of decision $+$ rationale
|
||||
\item \textbf{Measurement contract} -- fitness functions and thresholds under which the decision is continuously tested
|
||||
\end{enumerate}
|
||||
\end{definitionbox}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\small Both profiles range over the \textbf{same twelve dimensions} -- introduced today, completed next week.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{The framework as a pipeline -- and the map of the script}
|
||||
\begin{center}
|
||||
\resizebox{0.94\textwidth}{!}{%
|
||||
\begin{tikzpicture}[
|
||||
node distance=0.9cm and 1.0cm,
|
||||
sysbox/.style={rectangle, draw, rounded corners=4pt, text width=3.2cm, minimum height=1.3cm, align=center, font=\small\sffamily, line width=0.8pt},
|
||||
core/.style={sysbox, fill=bankblue!20, draw=bankblue},
|
||||
comp/.style={sysbox, fill=bankgreen!15, draw=bankgreen},
|
||||
meas/.style={sysbox, fill=violet!15, draw=aiviolet},
|
||||
arr/.style={-{Stealth[length=2.5mm]}, thick, gray!60!black},
|
||||
farr/.style={-{Stealth[length=2.5mm]}, thick, dashed, bankred}
|
||||
]
|
||||
\node[core] (klass) {Application class\\ \scriptsize (Part III)};
|
||||
\node[core, right=0.9cm of klass] (profil) {Requirements profile $R(a)$\\ \scriptsize scenarios, utility tree};
|
||||
\node[core, right=0.9cm of profil] (match) {Matching $\mathrm{fit}(a,p)$\\ \scriptsize against $C(p)$ (Parts II, IV)};
|
||||
\node[comp, below=1.4cm of match] (adr) {Architecture decision\\ \scriptsize ADR with rationale};
|
||||
\node[meas, left=0.9cm of adr] (fitness) {Measurement contract\\ \scriptsize fitness functions in CI/CD};
|
||||
\node[meas, left=0.9cm of fitness] (ops) {Operation\\ \scriptsize DORA, SLOs, Lehman trends};
|
||||
\draw[arr] (klass) -- (profil);
|
||||
\draw[arr] (profil) -- (match);
|
||||
\draw[arr] (match) -- (adr);
|
||||
\draw[arr] (adr) -- (fitness);
|
||||
\draw[arr] (fitness) -- (ops);
|
||||
\draw[farr] (ops.north) -- node[midway, right=2pt, font=\scriptsize\sffamily, text=bankred, align=left] {profile drift (A5):\\ re-measure, evolve, supersede} (klass.south);
|
||||
\end{tikzpicture}%
|
||||
}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\small Demand is matched against supply; the match ends in a \textbf{recorded decision} with a \textbf{measurement contract} -- and operation continuously tests whether the decision's promises hold. The dashed edge is not decoration.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{The two AI axes of this module}
|
||||
\begin{ailinse}[Where AI enters -- twice]
|
||||
\begin{itemize}
|
||||
\item \textbf{Axis A -- AI as a tool in the development process:} assistants and agents generate code, tests, documentation -- changing \emph{how} we make and guard architectural decisions.
|
||||
\item \textbf{Axis B -- AI as a runtime component of the system:} an LLM, an ML model, an optimiser \emph{inside} the architecture -- bringing non-determinism, seconds-scale latency, per-call cost -- changing \emph{what} we must decide about.
|
||||
\end{itemize}
|
||||
\end{ailinse}
|
||||
|
||||
\vspace{0.3cm}
|
||||
\begin{itemize}
|
||||
\item Both axes are treated systematically in Part V of the script
|
||||
\item Until then, \textcolor{aiviolet}{\textbf{AI Lens}} boxes flag where each axis touches the classical material
|
||||
\item Your project lives on \textbf{both} axes: you build an AI-native system, using AI tools
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% SECTION 5: SIX ASSUMPTIONS
|
||||
% ============================================
|
||||
\section{Six Load-Bearing Assumptions}
|
||||
|
||||
\begin{frame}{Six load-bearing assumptions}
|
||||
The framework rests on six assumptions -- each anchored in established literature, each justifying \textbf{one element} of the framework.
|
||||
|
||||
\vspace{0.3cm}
|
||||
\begin{center}
|
||||
\small
|
||||
\begin{tabular}{@{}llp{5.4cm}@{}}
|
||||
\toprule
|
||||
& \textbf{Assumption (short)} & \textbf{Justifies} \\
|
||||
\midrule
|
||||
A1 & architecture $=$ hard-to-reverse decisions & the ADR (element 4) \\
|
||||
A2 & everything is a trade-off & the matching problem (element 3) \\
|
||||
A3 & quality attributes drive architecture & the twelve dimensions \\
|
||||
A4 & requirements $=$ measurable scenarios & the demand-side method (element 1) \\
|
||||
A5 & a decision is a tested hypothesis & the measurement contract (element 5) \\
|
||||
A6 & AI extends the space, not the method & D12 $+$ eval harness -- nothing else \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\textcolor{codegray}{\small The next three slides give each assumption its evidence.}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{A1 -- Decisions. \quad A2 -- Trade-offs.}
|
||||
\small
|
||||
\textbf{A1 -- Architecture is the set of significant, hard-to-reverse design decisions.}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item significance measured by \textbf{cost of change}; ``decisions you wish you could get right early''
|
||||
\item lost decision knowledge is a documented cause of erosion $\to$ every decision becomes an \textbf{ADR}
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.25cm}
|
||||
\textbf{A2 -- Everything in software architecture is a trade-off} \textcolor{codegray}{(First Law, Richards \& Ford)}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item \dots and if you think you have found something that is not, \emph{you have not yet identified the trade-off}
|
||||
\item the star ratings show it: microservices lead overall yet one star on cost and simplicity; layered is the exact mirror -- \textbf{dominance does not occur} $\to$ a matching problem exists
|
||||
\item corollary: a proposal claiming \emph{only benefits} is incomplete \emph{by assumption}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{A3 -- Quality attributes. \quad A4 -- Scenarios.}
|
||||
\small
|
||||
\textbf{A3 -- Quality attributes, not functionality, drive architecture.}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item functionality is largely \textbf{structure-neutral}; structure determines \emph{how well}: performance, availability, modifiability, security
|
||||
\item non-functional properties can rarely be refactored in afterwards
|
||||
\item $\to$ the coordinate system consists of quality attributes -- never feature lists
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.25cm}
|
||||
\textbf{A4 -- Requirements are architecturally usable only as measurable scenarios.}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item ``the system shall be scalable'' decides nothing and tests nothing
|
||||
\item decision-relevant only as a six-part scenario with a \textbf{response measure} -- number and unit
|
||||
\item empirically, such requirements are vague and implicit -- they must be \emph{elicited} (next week: QAW, utility tree)
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{A5 -- A tested hypothesis. \quad A6 -- AI absorbed.}
|
||||
\small
|
||||
\textbf{A5 -- An architecture decision is a hypothesis, continuously tested over the life cycle.}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item Lehman: change continually or decay; maintenance $\approx 40$--$80\,\%$ of life-cycle cost $\to$ design-time fit \textbf{decays}
|
||||
\item re-measure: fitness functions in CI/CD, the four DORA metrics; change \emph{within} an architecture is cheap -- change \emph{of} it stays steep (Segment, Prime Video)
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.3cm}
|
||||
\textbf{A6 -- AI components extend the quality attribute space but do not change the method.}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item non-deterministic, fallible, latency-heavy, priced per call, subject to drift -- yet ISO/IEC 25010:2023 already carries the vocabulary (Safety, Flexibility, Security/resistance)
|
||||
\item AI is \textbf{absorbed}: one new dimension (D12) $+$ one new test artefact (eval harness) -- \emph{the method stays}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Maxim 2}
|
||||
\begin{keypoint}
|
||||
\textbf{Maxim 2.} Because everything is a trade-off (A2) and quality drives structure (A3), architecture selection is \textbf{matching}; because decisions are costly to reverse (A1) and decay over time (A5), the match must be \textbf{documented} and \textbf{continuously measured}.
|
||||
\end{keypoint}
|
||||
|
||||
\vspace{0.4cm}
|
||||
\begin{center}
|
||||
\large
|
||||
demand $\;\to\;$ supply $\;\to\;$ match $\;\to\;$ record $\;\to\;$ test
|
||||
\end{center}
|
||||
|
||||
\vspace{0.3cm}
|
||||
\centering\small\textcolor{codegray}{This chain is the red line of the whole script -- every part instantiates one link at scale.}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% SECTION 6: FROM QUESTIONS TO DIMENSIONS
|
||||
% ============================================
|
||||
\section{From Questions to Dimensions}
|
||||
|
||||
\begin{frame}{Imagine you are on the on-call rota \dots}
|
||||
Forget frameworks for a moment. You are responsible -- personally -- for a system real people use. These questions \emph{will} find you:
|
||||
|
||||
\vspace{0.2cm}
|
||||
\small
|
||||
\begin{itemize}\setlength\itemsep{3pt}
|
||||
\item \emph{The grade-release portal: what happens at 08:00 on publication day, when the whole semester refreshes the same page at once?}
|
||||
\item \emph{An e-banking transfer: can the same payment ever be booked twice -- or disappear halfway?}
|
||||
\item \emph{One component crashes at noon: does the whole application go dark, or does one widget show a spinner while everything else keeps working?}
|
||||
\item \emph{The regulator calls: ``prove to us, step by step, what happened to this one transaction.'' How long does that take you?}
|
||||
\item \emph{A new feature request arrives: how many places in the code must change -- one module, or seventeen?}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{\dots and the questions keep coming}
|
||||
\small
|
||||
\begin{itemize}\setlength\itemsep{3pt}
|
||||
\item \emph{Two students must ship a working MVP in one semester: does the structure let them -- or does it demand a platform team they do not have?}
|
||||
\item \emph{The monthly cloud bill triples: which part of the structure is spending the money, and what was it doing at 03:00?}
|
||||
\item \emph{The team grows from three to thirty: do releases get faster -- or does everyone now wait for everyone else?}
|
||||
\item \emph{Product adds a feature whose core is an LLM call: it takes eight seconds, costs money on every single request, and is sometimes confidently wrong. Where does that live in the architecture?}
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{hinweisbox}
|
||||
Every one of these questions has ended budgets, products, or careers.
|
||||
\end{hinweisbox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Three observations turn the list into a method}
|
||||
\begin{enumerate}\setlength\itemsep{3pt}
|
||||
\item \textbf{The questions recur} -- across wildly different systems: the grade portal and Instagram share the first question, merely at different magnitudes.
|
||||
\item \textbf{None of them asks \emph{what} the system does} -- functionality is structure-neutral (A3); every question is about \emph{how well}, \emph{at what cost}, \emph{under which failure}.
|
||||
\item \textbf{Each can be answered with a number} -- requests per second, double bookings per million, per cent of functionality lost, hours to an audit trail, modules touched per feature, cost per request \dots
|
||||
\end{enumerate}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{keypoint}
|
||||
The twelve profile dimensions D1--D12 are exactly this: the recurring questions -- \textbf{grouped, named, and equipped with defined measures}. Nothing more mysterious than that.
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{The twelve dimensions: five groups (preview)}
|
||||
\small
|
||||
\begin{center}
|
||||
\begin{tabular}{@{}llp{6.6cm}@{}}
|
||||
\toprule
|
||||
\textbf{Group} & \textbf{Dimensions} & \textbf{The underlying question} \\
|
||||
\midrule
|
||||
Load and speed & D1, D2, D3 & does the structure survive its own success? \\
|
||||
Correctness and trust & D4, D5, D6 & can it be trusted -- with money, uptime, history? \\
|
||||
Change and delivery & D7, D8, D9 & what does the \emph{next} change cost? \\
|
||||
Economics and organisation & D10, D11 & what does it cost to run -- and can teams work in parallel? \\
|
||||
The new dimension & D12 & how cheaply can it host a slow, fallible, per-call-priced AI component? \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{itemize}
|
||||
\item Next week: all twelve, one by one -- each with its question, its vocabulary, and its \textbf{measurement instrument}
|
||||
\item Both profiles -- demand $R(a)$ and supply $C(p)$ -- will be vectors over \emph{these} twelve dimensions
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Discussion}
|
||||
\begin{thinkbox}
|
||||
Pick an app you use daily.
|
||||
\begin{itemize}
|
||||
\item Which \textbf{three dimensions} dominate it?
|
||||
\item On which dimension would its operator accept a \emph{bad} rating without losing sleep?
|
||||
\item Compare with your neighbour -- where you disagree, you have found a \textbf{weight} discussion. Next week's utility tree resolves exactly that.
|
||||
\end{itemize}
|
||||
\end{thinkbox}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% SUMMARY
|
||||
% ============================================
|
||||
\section{Summary}
|
||||
|
||||
\begin{frame}{Summary}
|
||||
\small
|
||||
\begin{enumerate}\setlength\itemsep{2pt}
|
||||
\item Four production systems: structures differ radically, none dominates -- failures were \textbf{mismatches}
|
||||
\item \textbf{Maxim 1:} patterns are neither good nor bad; only the \emph{fit} is
|
||||
\item Architecture $=$ the \textbf{hard-to-reverse structural decisions} that determine quality behaviour
|
||||
\item The framework: $R(a)$ (demand) $\to$ $C(p)$ (supply) $\to$ $\mathrm{fit}(a,p)$ $\to$ \textbf{ADR} $\to$ \textbf{measurement contract}
|
||||
\item AI enters twice: \textbf{Axis A} (tool in the process), \textbf{Axis B} (component in the system)
|
||||
\item Six assumptions A1--A6 carry the framework; the twelve dimensions are \textbf{recurring engineering questions} -- grouped, named, measurable
|
||||
\item \textbf{Maxim 2:} match, then document, then measure
|
||||
\end{enumerate}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Next week}
|
||||
\begin{columns}[T]
|
||||
\begin{column}{0.55\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Lecture 2 -- the twelve dimensions, completed}}
|
||||
\begin{itemize}
|
||||
\item D1--D12 one by one: question, vocabulary, instrument
|
||||
\item why exactly these twelve (ISO/IEC 25010:2023)
|
||||
\item six-part quality attribute scenarios
|
||||
\item ASR, Quality Attribute Workshop
|
||||
\item the utility tree: from scenarios to \textbf{weights}
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\begin{column}{0.42\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Reading}}
|
||||
\begin{itemize}
|
||||
\item this week: script Part I, Sections 1--2
|
||||
\item ahead: Part I, Section 3
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.3cm}
|
||||
\textcolor{bankblue}{\textbf{Exercise}}
|
||||
\begin{itemize}
|
||||
\item kickoff: teams, repo, domain, ontology sketch, raw stakeholder wishes
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% END
|
||||
% ============================================
|
||||
{
|
||||
\setbeamertemplate{footline}{}
|
||||
\begin{frame}[plain]
|
||||
\vfill
|
||||
\begin{center}
|
||||
\includegraphics[width=0.25\textwidth]{FHGR_Logo_Large}\\[1cm]
|
||||
{\LARGE\bfseries\textcolor{bankblue}{Thank you!}}\\[0.8cm]
|
||||
{\large Dr.\ Florian Herzog}\\[0.2cm]
|
||||
{\normalsize Fachhochschule Graub\"unden, Chur}\\[0.5cm]
|
||||
{\small\textcolor{codegray}{AISE502 -- AI in Software Engineering II}}
|
||||
\end{center}
|
||||
\vfill
|
||||
\end{frame}
|
||||
}
|
||||
|
||||
\end{document}
|
||||
BIN
Folien/original_default_theme/AISE502_Vorlesung_2_Folien.pdf
Normal file
913
Folien/original_default_theme/AISE502_Vorlesung_2_Folien.tex
Normal file
@ -0,0 +1,913 @@
|
||||
\documentclass[aspectratio=169,12pt]{beamer}
|
||||
|
||||
% ============================================
|
||||
% THEME AND APPEARANCE
|
||||
% ============================================
|
||||
\usetheme{default}
|
||||
\usecolortheme{default}
|
||||
\usefonttheme{professionalfonts}
|
||||
\setbeamertemplate{navigation symbols}{}
|
||||
\setbeamertemplate{footline}{}
|
||||
\setbeamertemplate{frametitle continuation}{}
|
||||
|
||||
% ============================================
|
||||
% PACKAGES
|
||||
% ============================================
|
||||
\usepackage[utf8]{inputenc}
|
||||
\usepackage[T1]{fontenc}
|
||||
\usepackage[british]{babel}
|
||||
\usepackage{graphicx}
|
||||
\usepackage{hyperref}
|
||||
\usepackage{xcolor}
|
||||
\usepackage{booktabs}
|
||||
\usepackage{tcolorbox}
|
||||
\usepackage{amsmath}
|
||||
\usepackage{amssymb}
|
||||
\usepackage{tikz}
|
||||
\usetikzlibrary{shapes.geometric, arrows.meta, positioning, fit, backgrounds, calc}
|
||||
|
||||
% ============================================
|
||||
% COLORS (same as script)
|
||||
% ============================================
|
||||
\definecolor{bankblue}{rgb}{0.0,0.28,0.67}
|
||||
\definecolor{bankgreen}{rgb}{0.13,0.55,0.13}
|
||||
\definecolor{bankred}{rgb}{0.7,0.13,0.13}
|
||||
\definecolor{aiviolet}{rgb}{0.42,0.19,0.58}
|
||||
\definecolor{backcolour}{rgb}{0.95,0.95,0.92}
|
||||
\definecolor{codegray}{rgb}{0.5,0.5,0.5}
|
||||
|
||||
% Beamer color setup
|
||||
\setbeamercolor{structure}{fg=bankblue}
|
||||
\setbeamercolor{frametitle}{fg=white,bg=bankblue}
|
||||
\setbeamercolor{title}{fg=white,bg=bankblue}
|
||||
\setbeamercolor{block title}{fg=white,bg=bankblue}
|
||||
\setbeamercolor{block body}{bg=blue!5!white}
|
||||
\setbeamercolor{block title alerted}{fg=white,bg=bankred}
|
||||
\setbeamercolor{block body alerted}{bg=red!5!white}
|
||||
\setbeamercolor{block title example}{fg=white,bg=bankgreen}
|
||||
\setbeamercolor{block body example}{bg=green!5!white}
|
||||
\setbeamercolor{item}{fg=bankblue}
|
||||
\setbeamercolor{subitem}{fg=bankblue!80}
|
||||
\setbeamercolor{itemize item}{fg=bankblue}
|
||||
\setbeamercolor{enumerate item}{fg=bankblue}
|
||||
|
||||
% Bullet style
|
||||
\setbeamertemplate{itemize item}{\raisebox{0.12ex}{$\blacktriangleright$}}
|
||||
\setbeamertemplate{itemize subitem}{\raisebox{0.12ex}{\small$\triangleright$}}
|
||||
\setbeamertemplate{enumerate items}[default]
|
||||
|
||||
% ============================================
|
||||
% CUSTOM TCOLORBOXES (same as script)
|
||||
% ============================================
|
||||
\newtcolorbox{keypoint}{
|
||||
colback=blue!5!white,
|
||||
colframe=bankblue,
|
||||
title=Key Concept,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{examplebox}[1][]{
|
||||
colback=green!5!white,
|
||||
colframe=bankgreen,
|
||||
title={Example: #1},
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{definitionbox}[1][]{
|
||||
colback=yellow!5!white,
|
||||
colframe=yellow!50!black,
|
||||
title={Definition: #1},
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{thinkbox}{
|
||||
colback=orange!5!white,
|
||||
colframe=orange!60!black,
|
||||
title=Discussion,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{hinweisbox}{
|
||||
colback=red!5!white,
|
||||
colframe=bankred,
|
||||
title=Important Note,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{ailinse}[1][]{
|
||||
colback=violet!5!white,
|
||||
colframe=aiviolet,
|
||||
title={AI Lens: #1},
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{projektbox}{
|
||||
colback=blue!3!white,
|
||||
colframe=bankblue!70,
|
||||
title=Project Link: Portfolio Intelligence Platform,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
% Measurement line used on every dimension slide
|
||||
\newcommand{\measured}[2]{%
|
||||
\vspace{0.12cm}
|
||||
\begin{tcolorbox}[colback=gray!6!white, colframe=gray!55!black, boxrule=0.6pt, arc=2pt, top=1pt, bottom=1pt, left=4pt, right=4pt]
|
||||
\footnotesize \textbf{Measured:} #1\\ \textbf{Instrument:} #2
|
||||
\end{tcolorbox}}
|
||||
|
||||
% ============================================
|
||||
% FOOTER WITH LOGO
|
||||
% ============================================
|
||||
\setbeamertemplate{footline}{%
|
||||
\leavevmode%
|
||||
\hbox{%
|
||||
\begin{beamercolorbox}[wd=0.5\paperwidth,ht=2ex,dp=0.5ex,leftskip=0.5em]{footline}%
|
||||
\usebeamerfont{footline}\textcolor{codegray}{\tiny\insertframenumber{} / \inserttotalframenumber}%
|
||||
\end{beamercolorbox}%
|
||||
\begin{beamercolorbox}[wd=0.35\paperwidth,ht=2ex,dp=0.5ex,center]{footline}%
|
||||
\usebeamerfont{footline}\textcolor{codegray}{\tiny AISE502 -- AI in Software Engineering II}%
|
||||
\end{beamercolorbox}%
|
||||
\begin{beamercolorbox}[wd=0.15\paperwidth,ht=2ex,dp=0.5ex,rightskip=0.5em,right]{footline}%
|
||||
\includegraphics[height=1.5ex]{FHGR_Logo_small}%
|
||||
\end{beamercolorbox}%
|
||||
}%
|
||||
\vskip0pt%
|
||||
}
|
||||
|
||||
% ============================================
|
||||
% DOCUMENT
|
||||
% ============================================
|
||||
\begin{document}
|
||||
|
||||
% ============================================
|
||||
% TITLE SLIDE
|
||||
% ============================================
|
||||
{
|
||||
\setbeamertemplate{footline}{}
|
||||
\begin{frame}[plain]
|
||||
\vfill
|
||||
\begin{center}
|
||||
\includegraphics[width=0.3\textwidth]{FHGR_Logo_Large}\\[1cm]
|
||||
{\LARGE\bfseries\textcolor{bankblue}{AISE502: AI in Software Engineering II}}\\[0.6cm]
|
||||
{\large Lecture 2: The Twelve Dimensions -- and How Requirements Become Measurable}\\[0.3cm]
|
||||
{\small\textcolor{codegray}{Script: Part I, Sections 2--3}}\\[0.8cm]
|
||||
{\normalsize Dr.\ Florian Herzog}\\[0.2cm]
|
||||
{\small Fachhochschule Graub\"unden, Chur}\\[0.2cm]
|
||||
{\small Autumn Semester 2026}
|
||||
\end{center}
|
||||
\vfill
|
||||
\end{frame}
|
||||
}
|
||||
|
||||
% ============================================
|
||||
% AGENDA
|
||||
% ============================================
|
||||
\begin{frame}{Agenda}
|
||||
\small
|
||||
\begin{enumerate}\setlength\itemsep{1pt}
|
||||
\item Recap: the framework and the nine questions
|
||||
\item Load and speed: D1--D3
|
||||
\item Correctness and trust: D4--D6
|
||||
\item Change and delivery: D7--D9
|
||||
\item Economics and organisation: D10--D11
|
||||
\item The new dimension: D12 (AI integrability)
|
||||
\item Why exactly these twelve -- ISO/IEC 25010:2023
|
||||
\item From wishes to scenarios: ASR, QAW, the six-part form
|
||||
\item The utility tree: from scenarios to weights
|
||||
\item Workload shape, hard constraints -- $R(a)$ assembled
|
||||
\end{enumerate}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% RECAP
|
||||
% ============================================
|
||||
\section{Recap}
|
||||
|
||||
\begin{frame}{Recap: where we are}
|
||||
\footnotesize
|
||||
\textbf{Last week:}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item Maxim 1: patterns are neither good nor bad -- only the \textbf{fit} is
|
||||
\item the framework: $R(a) \to C(p) \to \mathrm{fit}(a,p) \to$ ADR $\to$ measurement contract
|
||||
\item six assumptions A1--A6; the chain \emph{demand $\to$ supply $\to$ match $\to$ record $\to$ test}
|
||||
\item nine recurring on-call questions $\to$ five groups of dimensions
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\textbf{Today} we build the coordinate system and the demand side:
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item the twelve dimensions \textbf{D1--D12}, one by one -- each with vocabulary and \textbf{instrument}
|
||||
\item then the method that turns stakeholder wishes into \textbf{weights}: scenarios, QAW, utility tree
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{keypoint}
|
||||
Rule of the day (A4, applied to the theory itself): \textbf{no instrument, no dimension.}
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% D1-D3 LOAD AND SPEED
|
||||
% ============================================
|
||||
\section{Load and Speed: D1--D3}
|
||||
|
||||
\begin{frame}{D1 -- Read scalability \hfill \normalsize\textcolor{white}{group: load and speed}}
|
||||
\emph{\textcolor{bankblue}{What happens at 08:00 on grade-release day, when the whole semester refreshes at once?}}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item the ability to serve a growing volume of \textbf{read} requests -- requests that look at data without changing it
|
||||
\item most interactive systems are \textbf{read-dominated by orders of magnitude}: thousands check a result for every one who appeals it
|
||||
\item reads are friendly: they can be served from \textbf{copies} -- replicas and \emph{caches} (fast stores holding ready-made answers)
|
||||
\item Stack Overflow: $\sim 1.3$ billion page views/month from a handful of servers; Instagram: a monolith -- \textbf{the single write path is the hard part}
|
||||
\end{itemize}
|
||||
|
||||
\measured{throughput at $k\times$ replication (does doubling servers double throughput?); cache hit ratio; p95 read latency}{step-profile load tests; production RED metrics (Rate, Errors, Duration)}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{D2 -- Write scalability and elasticity}
|
||||
\emph{\textcolor{bankblue}{Black Friday: checkout traffic jumps to dozens of times the baseline for one weekend -- and is gone on Monday.}}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item the D1 question for requests that \textbf{change} state -- the harder half: a write cannot be served from a copy; every order must reach the \emph{one authoritative record}, durably and in order
|
||||
\item \textbf{elasticity} adds the time axis: how quickly capacity follows load -- up \emph{and back down}
|
||||
\item reference point: Shopify's BFCM weekend, peaks $\sim 280$ million requests/minute, carried by replicated ``pods'' of a monolith
|
||||
\item the opposite end: \textbf{scale-to-zero} -- costing nothing while unused (the serverless promise)
|
||||
\end{itemize}
|
||||
|
||||
\measured{sustained ingest rate (durably absorbed writes/s); time-to-capacity after a load step; cost of idling at zero}{load tests with load steps; elasticity-lag measurement}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{D3 -- Latency and predictability}
|
||||
\emph{\textcolor{bankblue}{How long does one click take -- and how long does it take on a bad day?}}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item \textbf{latency}: time between request and response; \textbf{predictability}: the distribution matters, not the average
|
||||
\item \textbf{averages lie}: a system can average $120$\,ms while every twentieth request takes four seconds -- and the most active users hit those most often
|
||||
\item vocabulary: \textbf{p50/p95/p99} percentiles; \textbf{tail-latency ratio} p99/p50; \textbf{cold start} $=$ extra delay when the serving component must first wake up
|
||||
\item stakes: Amazon $\sim 1\,\%$ of sales lost per additional $100$\,ms; Akamai: up to $7\,\%$ of conversions
|
||||
\end{itemize}
|
||||
|
||||
\measured{p50/p95/p99 response times; cold-start frequency; tail-latency ratio}{distributed tracing (OpenTelemetry) -- following one request across every component; latency budgets as CI gates}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% D4-D6 CORRECTNESS AND TRUST
|
||||
% ============================================
|
||||
\section{Correctness and Trust: D4--D6}
|
||||
|
||||
\begin{frame}{D4 -- Consistency and transactional integrity}
|
||||
\emph{\textcolor{bankblue}{An e-banking transfer: can the same payment ever be booked twice -- or vanish halfway?}}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item can concurrency and partial failure \textbf{corrupt the data} -- can the numbers silently stop being true?
|
||||
\item classic failure, the \textbf{lost update}: two processes read the same balance, both write -- the second silently overwrites the first
|
||||
\item vocabulary: \textbf{invariant} (must always hold: debit $=$ credit); \textbf{transactional integrity} (all or nothing); \textbf{staleness} (seconds a copy may lag)
|
||||
\item a single database hands you transactions \emph{for free}; every distribution boundary takes part of that away
|
||||
\end{itemize}
|
||||
|
||||
\measured{anomaly rate under concurrent load; invariant-violation count (\textbf{target 0} for ledgers); staleness bound}{Jepsen-style tests (concurrent ops $+$ injected failures); reconciliation jobs}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{D5 -- Availability and fault isolation}
|
||||
\emph{\textcolor{bankblue}{One component crashes at noon: does the whole app go dark, or does one widget show a spinner?}}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item availability: share of time the system does its job; fault isolation: \textbf{how much of the product dies when one part dies}
|
||||
\item \textbf{blast radius}: \% of functionality lost per component failure -- in a single process it is $100\,\%$ \emph{by construction}; \textbf{MTTR}: mean time to recovery
|
||||
\item operations vocabulary: \textbf{SLO} (``$99.9\,\%$ of requests succeed this month''), \textbf{error budget} (the tolerated $0.1\,\%$), \textbf{burn rate}
|
||||
\item run continuously in the pipeline, such an automated check of an architectural property is a \textbf{fitness function} -- a term we will use constantly
|
||||
\end{itemize}
|
||||
|
||||
\measured{SLO attainment; error-budget burn; blast radius; MTTR}{chaos experiments -- deliberately kill components under load and measure what users lose}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{D6 -- Security and auditability}
|
||||
\emph{\textcolor{bankblue}{The regulator asks: prove what happened to this one transaction, end to end.}}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item keeping attackers out is necessary \emph{everywhere}; what discriminates between \textbf{structures} is \textbf{auditability} -- the ability to reconstruct history
|
||||
\item \textbf{audit trail}: complete, tamper-evident record of who changed what, when, on whose authority -- a \emph{legal duty} in supervised industries (FINMA, PCI DSS)
|
||||
\item \textbf{audit scope}: the portion of the system auditors must examine -- confining sensitive flows to a small region shrinks the scope, and the bill
|
||||
\item some structures record every change as an event \emph{as their normal mode}; others reassemble history from scattered log files
|
||||
\end{itemize}
|
||||
|
||||
\measured{time to reconstruct a complete audit trail for one transaction; \% of state changes journaled (append-only)}{audit drills -- run like fire drills; immutable logs; PCI/FINMA scope reviews}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% D7-D9 CHANGE AND DELIVERY
|
||||
% ============================================
|
||||
\section{Change and Delivery: D7--D9}
|
||||
|
||||
\begin{frame}{D7 -- Evolvability and maintainability}
|
||||
\emph{\textcolor{bankblue}{A feature request arrives: how many places in the code must change?}}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item prices the \textbf{next} change -- which, over a lifetime dominated by evolution (A5), dominates most others
|
||||
\item central measure, worth memorising: \textbf{change dispersion} $=$ modules touched by an average feature -- \emph{one is excellent, seventeen is an architecture problem}
|
||||
\item underlying variable: \textbf{coupling} -- metrics: CBO (coupling between objects), Martin's \emph{instability}
|
||||
\item \textbf{declared-boundary violations} (code bypassing declared module boundaries): target 0, enforceable in CI with ArchUnit / Spring Modulith
|
||||
\end{itemize}
|
||||
|
||||
\measured{change dispersion over the version history; coupling metrics (CBO, instability); boundary violations (target 0)}{ArchUnit / Spring Modulith verification as CI gates; CK metric suite}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{D8 -- Simplicity and time-to-market}
|
||||
\emph{\textcolor{bankblue}{Two students must ship a working MVP in one semester. Does the structure let them?}}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item how much machinery must \emph{exist, be understood, and be kept alive} before the first unit of value reaches a user
|
||||
\item a structure that requires a container orchestrator, a message broker, and a dozen repositories before ``hello, world'' has \textbf{failed this dimension for that team} -- however well it would carry Shopify's Black Friday
|
||||
\item this is where A2 bites hardest: the structures that win D8 tend to concede D2 or D11 -- a small team's rational choice \emph{differs} from a platform company's
|
||||
\end{itemize}
|
||||
|
||||
\measured{time from empty repository to first production release; onboarding time to first merged contribution; count of distinct runtime technologies}{delivery calendar; team surveys; tech-radar count}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{D9 -- Testability and deployability}
|
||||
\emph{\textcolor{bankblue}{Can a developer know within seconds that a change is safe -- and release it this afternoon without coordinating with three teams?}}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item two abilities, \textbf{deliberately fused}: fast, trustworthy verification \emph{and} independent, low-risk release
|
||||
\item vocabulary: \textbf{hermetic test} (fully self-contained -- no shared staging, no live external service); \textbf{deployment frequency}; \textbf{change failure rate} (share of releases that break something)
|
||||
\item why fused: DORA 2017 found precisely this pair -- test without an integrated environment, deploy independently -- predicted delivery performance \emph{more strongly than automation itself}; both are surface expressions of \textbf{coupling}
|
||||
\end{itemize}
|
||||
|
||||
\measured{test feedback time; \% hermetic tests; deployment frequency; change failure rate}{pipeline telemetry; DORA capability items}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% D10-D11 ECONOMICS AND ORGANISATION
|
||||
% ============================================
|
||||
\section{Economics and Organisation: D10--D11}
|
||||
|
||||
\begin{frame}{D10 -- Operating cost efficiency}
|
||||
\emph{\textcolor{bankblue}{The cloud bill tripled. Which part of the structure spends the money -- and what was it doing at 03:00?}}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item prices the running system -- \textbf{machines and people}
|
||||
\item vocabulary: \textbf{cost per request}; \textbf{idle cost} (capacity doing nothing -- the 03:00 question); \textbf{TCO}; \textbf{FTE}
|
||||
\item the hidden term matters most: a self-managed container platform is dominated not by compute prices but by \textbf{platform-team FTEs} -- the ``microservice premium'' materialises as staffing
|
||||
\item Prime Video's $> 90\,\%$ cost cut: the same dimension, seen from the infrastructure side
|
||||
\end{itemize}
|
||||
|
||||
\measured{TCO split build/platform/run; cost per request; idle cost; platform-team FTEs}{FinOps reporting -- making cloud spend visible and attributable per team and feature}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{D11 -- Team scaling (Conway fit)}
|
||||
\emph{\textcolor{bankblue}{The team grows from three to thirty. Do releases speed up -- or does everyone wait on everyone?}}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item \textbf{Conway's law}, in one sentence: a system's structure ends up mirroring the communication structure of the organisation that builds it
|
||||
\item consequence: \emph{every architecture decision is a team-structure decision} -- whether the architect intends it or not
|
||||
\item operational core: how many teams can design, build, and \textbf{release without waiting for each other}?
|
||||
\item DORA: \emph{deployments per developer per day} \textbf{rises} with team count in loosely coupled organisations -- and \textbf{falls} in tightly coupled ones
|
||||
\end{itemize}
|
||||
|
||||
\measured{deployments per developer per day as the team count grows; number of teams releasing without cross-team coordination}{DORA scaling analysis; Team Topologies review}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% D12 THE NEW DIMENSION
|
||||
% ============================================
|
||||
\section{The New Dimension: D12}
|
||||
|
||||
\begin{frame}{D12 -- AI integrability}
|
||||
\emph{\textcolor{bankblue}{The new feature's core is an LLM call: eight seconds, paid per request, sometimes confidently wrong. How hard does the structure fight it?}}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\footnotesize
|
||||
How cheaply can the structure host a component that is \textbf{slow, fallible, priced per call}? It needs three things:
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item a \textbf{queue}: a waiting line, so an eight-second call -- or a provider outage -- does not block everything behind it
|
||||
\item a \textbf{port}: a narrow, contract-shaped interface isolating the non-determinism, so deterministic tests can substitute a \emph{fake}
|
||||
\item a \textbf{measurement point}: cost and quality of \emph{every single call} observable -- providers price per \textbf{token}, so cost accrues \emph{per request}
|
||||
\end{itemize}
|
||||
|
||||
\measured{seconds-scale latency tolerance; isolability of non-determinism behind contracts; token-cost observability per request}{\textbf{eval harness}: versioned test inputs with expected qualities; pass rate $\geq$ threshold as a CI gate -- the AI counterpart of a regression suite}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{One system, one profile}
|
||||
\begin{examplebox}[a retail e-banking application, walked through the five groups]
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item \textbf{Load and speed:} payday-morning peaks; reads $\gg$ writes; two seconds tolerated, not ten $\to$ D1, D3 matter; D2 modest
|
||||
\item \textbf{Correctness and trust:} a double-booked transfer is existential; the audit trail is a legal duty $\to$ D4, D6 \emph{as high as they go}; D5 high
|
||||
\item \textbf{Change and delivery:} monthly, formally reviewed releases -- but decades of regulatory change $\to$ D7 high, D9 moderate
|
||||
\item \textbf{Economics and organisation:} platform organisation exists anyway; dozens of teams $\to$ D10 medium, D11 high
|
||||
\item \textbf{AI:} a chat assistant is attractive -- but a confidently wrong answer about a balance is a \emph{safety} problem $\to$ D12 medium, hard guardrails
|
||||
\end{itemize}
|
||||
\end{examplebox}
|
||||
|
||||
\vspace{0.05cm}
|
||||
\footnotesize The judgements are debatable; the point is not: \textbf{a real system has a \emph{profile}} -- demanding on a few dimensions, relaxed on others. Writing it down rigorously is the second half of today.
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% WHY EXACTLY THESE TWELVE
|
||||
% ============================================
|
||||
\section{Why Exactly These Twelve}
|
||||
|
||||
\begin{frame}{Quality attributes, not functions}
|
||||
\footnotesize
|
||||
\begin{columns}[T]
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Functional requirement}}
|
||||
\begin{itemize}
|
||||
\item \emph{what} the system shall do
|
||||
\item compute interest, post a booking, render a feed
|
||||
\item largely \textbf{structure-neutral} (A3)
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Quality attribute requirement}}
|
||||
\begin{itemize}
|
||||
\item \emph{how well}, under which conditions, at what cost
|
||||
\item the misleading classic term: ``non-functional''
|
||||
\item this is what \textbf{structure determines}
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
|
||||
\vspace{0.3cm}
|
||||
\begin{examplebox}[the same function, three structures]
|
||||
``Post a booking'' can run inside a layered monolith, as a \emph{saga} across microservices, or as an event-sourced log. The \textbf{function is identical} -- the consistency guarantee, the latency distribution, the audit trail, and the cost of the next change are \textbf{radically different}.
|
||||
\end{examplebox}
|
||||
|
||||
\vspace{0.15cm}
|
||||
All twelve dimensions are quality attributes or workload/constraint characteristics -- \textbf{never features}.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{The names: ISO/IEC 25010:2023}
|
||||
\footnotesize
|
||||
The naming standard for quality attributes -- nine characteristics, each with sub-characteristics:
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{center}
|
||||
\footnotesize
|
||||
functional suitability $\cdot$ performance efficiency $\cdot$ compatibility $\cdot$ interaction capability $\cdot$ reliability $\cdot$ \textbf{security} $\cdot$ maintainability $\cdot$ \textbf{flexibility} $\cdot$ \textbf{safety}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.15cm}
|
||||
Three 2023 changes matter directly for this module:
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item \textbf{Safety} became a new top-level characteristic (fail safe, hazard warning) -- exactly what a confidently-wrong AI component requires
|
||||
\item \emph{portability} became \textbf{Flexibility}, with an explicit new \emph{scalability} sub-characteristic
|
||||
\item \textbf{Security} gained \emph{resistance} -- sustaining operation under attack: the normative hook for prompt-injection robustness
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{keypoint}
|
||||
The 2023 vocabulary covers AI-bearing systems \textbf{without private extensions} -- A6 starts with the quality model itself.
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Three admission conditions}
|
||||
\small
|
||||
A candidate became one of the twelve only if it passed all three:
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{enumerate}\setlength\itemsep{2pt}
|
||||
\item \textbf{Standard anchoring} -- maps to ISO/IEC 25010:2023 vocabulary (reaching beyond it -- cost, organisation -- is stated explicitly)
|
||||
\item \textbf{Discrimination} -- must distinguish at least two of the seven patterns; a dimension on which all patterns score alike carries no matching information
|
||||
\item \textbf{Instrumentation} -- must have a defined \textbf{response measure and measurement instrument}: every rating is a testable prediction, not an adjective
|
||||
\end{enumerate}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{hinweisbox}
|
||||
\footnotesize \textbf{No instrument, no dimension} -- this excludes ``elegance'' and ``future-proofness''. And ISO 25010 is a \emph{taxonomy}, not a \emph{metric}: do not argue about the box a concern belongs to -- write it as a \textbf{scenario with a response measure} and the question dissolves.
|
||||
\end{hinweisbox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{The reference card (1/2): D1--D6}
|
||||
\begin{center}
|
||||
\scriptsize
|
||||
\begin{tabular}{@{}p{0.6cm}p{2.9cm}p{4.6cm}p{4.4cm}@{}}
|
||||
\toprule
|
||||
\textbf{\#} & \textbf{Dimension} & \textbf{Response measure (examples)} & \textbf{Instrument} \\
|
||||
\midrule
|
||||
D1 & Read scalability & throughput at $k\times$ replication; cache hit ratio & load tests; RED metrics \\
|
||||
D2 & Write scalability \& elasticity & sustained ingest rate; time-to-capacity; scale-to-zero cost & load steps; elasticity lag \\
|
||||
D3 & Latency \& predictability & p50/p95/p99; cold starts; tail ratio p99/p50 & distributed tracing; latency budgets in CI \\
|
||||
D4 & Consistency \& integrity & anomaly rate; invariant violations ($0$ for ledgers); staleness bound & Jepsen-style tests; reconciliation jobs \\
|
||||
D5 & Availability \& fault isolation & SLO attainment; error-budget burn; blast radius; MTTR & SLOs; chaos experiments \\
|
||||
D6 & Security \& auditability & time to reconstruct an audit trail; \% changes journaled & audit drills; immutable logs; scope reviews \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\footnotesize\textcolor{codegray}{Full version with ISO anchors: the script's canonical reference card (Table 3).}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{The reference card (2/2): D7--D12}
|
||||
\begin{center}
|
||||
\scriptsize
|
||||
\begin{tabular}{@{}p{0.6cm}p{2.9cm}p{4.6cm}p{4.4cm}@{}}
|
||||
\toprule
|
||||
\textbf{\#} & \textbf{Dimension} & \textbf{Response measure (examples)} & \textbf{Instrument} \\
|
||||
\midrule
|
||||
D7 & Evolvability \& maintainability & change dispersion; coupling (CBO, instability); boundary violations ($0$) & ArchUnit / Spring Modulith in CI \\
|
||||
D8 & Simplicity \& time-to-market & empty repo $\to$ first release; onboarding time; technology count & delivery calendar; surveys \\
|
||||
D9 & Testability \& deployability & test feedback time; \% hermetic tests; deployment frequency; change failure rate & pipeline telemetry; DORA items \\
|
||||
D10 & Operating cost efficiency & TCO build/platform/run; cost per request; idle cost; platform FTEs & FinOps reporting \\
|
||||
D11 & Team scaling (Conway) & deployments per developer per day; teams releasing without coordination & DORA scaling; Team Topologies \\
|
||||
D12 & AI integrability & seconds-scale latency tolerance; isolable non-determinism; token-cost observability & eval-harness pass rate in CI; cost budgets \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% DEMAND SIDE: ASR, QAW, SCENARIOS
|
||||
% ============================================
|
||||
\section{From Wishes to Scenarios}
|
||||
|
||||
\begin{frame}{The demand side: what we are building}
|
||||
\begin{center}
|
||||
\Large
|
||||
$R(a) \;=\; \bigl(\underbrace{w_1, \dots, w_{12}}_{\text{priority weights}};\;\; \underbrace{S(a)}_{\text{workload shape}};\;\; \underbrace{K(a)}_{\text{hard constraints}}\bigr)$
|
||||
\end{center}
|
||||
|
||||
\vspace{0.4cm}
|
||||
None of these is written down by intuition -- each is \textbf{produced} by a defined method:
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{center}
|
||||
\small
|
||||
\begin{tabular}{@{}lll@{}}
|
||||
\toprule
|
||||
\textbf{Step} & \textbf{Method} & \textbf{Produces} \\
|
||||
\midrule
|
||||
1 & elicitation (QAW) & a prioritised pool of candidate \textbf{ASRs} \\
|
||||
2 & six-part scenarios & the candidates in \textbf{falsifiable form} \\
|
||||
3 & utility tree & the twelve \textbf{weights} $w_1, \dots, w_{12}$ \\
|
||||
4 & inventory & workload shape $S(a)$, constraints $K(a)$ \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Architecturally significant requirements (ASR)}
|
||||
\begin{definitionbox}[Architecturally significant requirement]
|
||||
A requirement with a \textbf{profound effect on the architecture} -- one whose late accommodation would be disproportionately expensive -- and typically \textbf{difficult to achieve}.
|
||||
\end{definitionbox}
|
||||
|
||||
\vspace{0.3cm}
|
||||
\small
|
||||
Empirical finding (Chen et al.\ 2013; 90 practitioners, $> 500$ organisations):
|
||||
\begin{itemize}
|
||||
\item ASRs are typically \textbf{poorly specified, vague, and implicit}
|
||||
\item they hide inside business goals: \emph{``we plan to enter three new markets next year''} $\;\to\;$ a scalability ASR \emph{and} a compliance ASR
|
||||
\item they cannot be read off a requirements document -- they must be \textbf{elicited}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Eliciting ASRs: the Quality Attribute Workshop (QAW)}
|
||||
\small
|
||||
The SEI's established format -- its essence is two design choices:
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{columns}[T]
|
||||
\begin{column}{0.44\textwidth}
|
||||
\textcolor{bankblue}{\textbf{1. Who is in the room}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item \emph{not} the development team alone
|
||||
\item the stakeholders whose concerns the architecture must balance:
|
||||
\item users, operators, auditors, regulators, product owners
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\begin{column}{0.52\textwidth}
|
||||
\textcolor{bankblue}{\textbf{2. The sequence}}
|
||||
\begin{enumerate}\setlength\itemsep{1pt}
|
||||
\item business and mission drivers first
|
||||
\item identify architectural drivers
|
||||
\item scenario \textbf{brainstorming}
|
||||
\item consolidation
|
||||
\item \textbf{prioritisation by stakeholder vote}
|
||||
\item refinement of the top candidates into the measurable six-part form
|
||||
\end{enumerate}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
|
||||
\vspace{0.3cm}
|
||||
\emph{Produced:} the raw material of $R(a)$ -- prioritised candidate ASRs, \textbf{not yet measurable}.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{The measurable form: the six-part scenario}
|
||||
\begin{definitionbox}[Quality attribute scenario]
|
||||
\footnotesize
|
||||
\begin{enumerate}\setlength\itemsep{0pt}
|
||||
\item \textbf{Source of stimulus} -- who or what triggers it: a user, another system, an attacker
|
||||
\item \textbf{Stimulus} -- the arriving event: a request, a failure, a load spike
|
||||
\item \textbf{Environment} -- the operating condition: normal, overload, degraded
|
||||
\item \textbf{Artifact} -- the part of the system stimulated
|
||||
\item \textbf{Response} -- the desired observable reaction
|
||||
\item \textbf{Response measure} -- the quantity, \textbf{with number and unit}, by which success is judged
|
||||
\end{enumerate}
|
||||
\end{definitionbox}
|
||||
|
||||
\vspace{0.05cm}
|
||||
\begin{hinweisbox}
|
||||
\small The \textbf{response measure} is the non-negotiable part: ``the system shall be scalable'' names an \emph{aspiration}; a scenario with a response measure names a \emph{test}.
|
||||
\end{hinweisbox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Worked scenario 1: availability in a payment service}
|
||||
\begin{examplebox}[banking]
|
||||
\footnotesize
|
||||
\emph{Source:} a heartbeat monitor. \emph{Stimulus:} reports the failure of one application server. \emph{Environment:} normal operation, mid-day load. \emph{Artifact:} the payment service. \emph{Response:} requests are redirected to replicas; operations staff notified; in-flight transactions complete or roll back atomically. \emph{\textbf{Response measure:}} failover $< 30$\,s; \textbf{zero} transactions lost or double-posted.
|
||||
\end{examplebox}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\footnotesize
|
||||
``The payment service shall be highly available'' hides \textbf{three architectural decisions} the scenario exposes:
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item replicas (redundancy tactic) \quad $\cdot$ \quad failure detection (heartbeat tactic)
|
||||
\item transactional atomicity \emph{across} the failover -- a guarantee some patterns provide structurally, others do not
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.1cm}
|
||||
The response measure is \textbf{directly executable} as a chaos experiment: kill an instance under load, measure.\\
|
||||
\textbf{One artefact, three roles:} requirement, design driver, test specification.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Worked scenario 2: safety in an AI advisory platform}
|
||||
\begin{examplebox}[Axis B]
|
||||
\footnotesize
|
||||
\emph{Source:} a customer. \emph{Stimulus:} submits a request for which the LLM generates a \textbf{factually wrong} recommendation. \emph{Environment:} normal operation. \emph{Artifact:} the advisory platform. \emph{Response:} the deterministic validation layer detects and blocks the answer and escalates to a human advisor. \emph{\textbf{Response measure:}} detection rate $\geq 99\,\%$ on the \emph{versioned evaluation set}, $< 2$\,s added latency.
|
||||
\end{examplebox}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\footnotesize Two things are notable:
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item the six-part form needed \textbf{no extension} for a non-deterministic component -- \textbf{A6 at work}: the stimulus is probabilistic (the model \emph{will} sometimes hallucinate), and the requirement is placed \textbf{on the system around the model}, not on the model
|
||||
\item the response measure \emph{presupposes an artefact}: a versioned evaluation set -- the \textbf{eval harness} (D12)
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\textcolor{codegray}{In ISO/IEC 25010:2023 terms: a \emph{Safety} scenario (fail safe, hazard warning).}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% UTILITY TREE
|
||||
% ============================================
|
||||
\section{The Utility Tree}
|
||||
|
||||
\begin{frame}{The utility tree: prioritising scenarios}
|
||||
\small A workshop produces more scenarios than any analysis can carry. The \textbf{utility tree} (ATAM) prioritises them top-down; every leaf is rated H/M/L on \textbf{business importance} (what does failure cost us?) and \textbf{achievement difficulty} (how hard, architecturally?).
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{center}
|
||||
\resizebox{0.72\textwidth}{!}{%
|
||||
\begin{tikzpicture}[
|
||||
sysbox/.style={rectangle, draw, rounded corners=4pt, align=center, font=\scriptsize\sffamily, line width=0.8pt, inner sep=4pt},
|
||||
root/.style={sysbox, fill=bankblue!20, draw=bankblue, font=\small\sffamily\bfseries, minimum height=1.1cm, minimum width=1.9cm},
|
||||
attr/.style={sysbox, fill=bankgreen!15, draw=bankgreen, minimum width=2.6cm, minimum height=0.85cm},
|
||||
leafhh/.style={sysbox, fill=bankred!15, draw=bankred, text width=6.6cm},
|
||||
leaf/.style={sysbox, fill=gray!12, draw=gray!60!black, text width=6.6cm},
|
||||
arr/.style={-{Stealth[length=2.2mm]}, thick, gray!60!black}
|
||||
]
|
||||
\node[root] (util) at (0,0) {Utility};
|
||||
\node[attr] (cons) at (3.6,2.7) {Consistency \&\\integrity};
|
||||
\node[attr] (avail) at (3.6,0.9) {Availability};
|
||||
\node[attr] (perf) at (3.6,-0.9) {Performance};
|
||||
\node[attr] (mod) at (3.6,-2.7) {Modifiability};
|
||||
\node[leafhh] (l1) at (9.2,2.7) {\textbf{(H,\,H)} No booking lost or double-posted under concurrent node failure; invariant violations $= 0$};
|
||||
\node[leafhh] (l2) at (9.2,0.9) {\textbf{(H,\,H)} Failover of the payment service $< 30$\,s with zero transaction loss};
|
||||
\node[leaf] (l3) at (9.2,-0.9) {(H,\,M) Card authorisation p95 $< 2$\,s at $3\times$ baseline load};
|
||||
\node[leaf] (l4) at (9.2,-2.7) {(M,\,H) New regulatory report integrated in $\leq 10$ person-days, touching $\leq 2$ modules};
|
||||
\draw[arr] (util) -- (cons);
|
||||
\draw[arr] (util) -- (avail);
|
||||
\draw[arr] (util) -- (perf);
|
||||
\draw[arr] (util) -- (mod);
|
||||
\draw[arr] (cons) -- (l1);
|
||||
\draw[arr] (avail) -- (l2);
|
||||
\draw[arr] (perf) -- (l3);
|
||||
\draw[arr] (mod) -- (l4);
|
||||
\end{tikzpicture}%
|
||||
}
|
||||
\end{center}
|
||||
|
||||
\centering\small The \textcolor{bankred}{\textbf{(H,\,H) leaves}} -- important \emph{and} hard -- are the architecturally critical points.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{From leaves to weights}
|
||||
\small The utility tree is the \textbf{methodical derivation of the weights}:
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{keypoint}
|
||||
\small Dimension $D_i$ receives $w_i(a) = \textbf{High}$ exactly when the class's characteristic utility tree has \textbf{(H,\,H) leaves} under the corresponding attribute. Medium and Low follow from the remaining leaf ratings.
|
||||
\end{keypoint}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\footnotesize What a weight \emph{asserts}:
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item \textbf{High} is not enthusiasm -- it is a claim with teeth: binding scenarios exist whose failure is \emph{existential}. High weights carry \textbf{veto power} in the match (week 3).
|
||||
\item Every High must survive the question: \emph{``show me the (H,\,H) leaf.''}
|
||||
\item \textbf{Low} is equally deliberate: not ``we do not care'' but \emph{``we will not pay structure for this''}
|
||||
\item \textbf{Medium} is the tradeable middle.
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{What High and Low look like (selection)}
|
||||
\scriptsize
|
||||
\begin{center}
|
||||
\begin{tabular}{@{}p{2.6cm}p{5.3cm}p{5.2cm}@{}}
|
||||
\toprule
|
||||
\textbf{Dimension} & \textbf{High: example} & \textbf{Low: example} \\
|
||||
\midrule
|
||||
D1 Read scalability & a public social/content feed: thousands of reads per write & an ERP used by clerks: load bounded by headcount \\
|
||||
D2 Write scal.\ \& elasticity & Black Friday checkout: $10$--$50\times$ seasonal write peaks & a BI warehouse loaded once, nightly \\
|
||||
D4 Consistency & a payments ledger: one double booking is existential & a social feed: a stale like-count harms nobody \\
|
||||
D8 Simplicity \& TTM & an internal back-office tool: its value is shipping this quarter & a core ledger: care beats speed \\
|
||||
D11 Team scaling & a platform built by thirty teams & a two-person project: nothing to mirror \\
|
||||
D12 AI integrability & the AI-native advisory platform: hosting fallible components \emph{is} the product & a classical accounting module \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\footnotesize Note the \textbf{D4 row}: ledger and feed are near-perfect \emph{mirror images} -- a structure optimised for one is close to pessimal for the other. Part III uses exactly this pair as its anchor.
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% SHAPE, CONSTRAINTS, R(a) ASSEMBLED
|
||||
% ============================================
|
||||
\section{Workload Shape, Constraints, and $R(a)$}
|
||||
|
||||
\begin{frame}{The last two components: shape and constraints}
|
||||
\footnotesize
|
||||
\textbf{Workload shape $S(a)$} -- how load arrives:
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item \emph{interactive} $\cdot$ \emph{continuous stream} $\cdot$ \emph{scheduled batch} $\cdot$ explicitly \emph{hybrid} -- with its signature: read/write ratio, load pattern, latency budget, data volume, change rate
|
||||
\item \textbf{measured, not guessed}: ratios from access logs, patterns from telemetry
|
||||
\item patterns have native shapes too -- the match enforces this as a \emph{gate}: a batch pipeline cannot carry an interactive core
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\textbf{Hard constraints $K(a)$} -- an explicit inventory:
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item regulatory obligations (BCBS 239, PCI DSS, EU AI Act), team size and skills, budget, mandated platforms
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{hinweisbox}
|
||||
\textbf{Constraints are knock-out filters, never weights.} A violating pattern is excluded \emph{before} any scoring -- never averaged away: an architecture that cannot produce the legally required audit trail is \textbf{not a candidate}.
|
||||
\end{hinweisbox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Worked construction: $R(\text{C10})$ -- the advisory platform (your project!)}
|
||||
\footnotesize
|
||||
\begin{center}
|
||||
\footnotesize
|
||||
\begin{tabular}{@{}lp{9.6cm}@{}}
|
||||
\toprule
|
||||
\textbf{High} & D6 auditability (provenance) $\cdot$ D7 evolvability (model/prompt churn) $\cdot$ D9 testability (evals) $\cdot$ D10 cost \emph{per request} $\cdot$ D12 AI \\
|
||||
\textbf{Medium} & D1, D3, D4, D5, D8 \\
|
||||
\textbf{Low} & D2, D11 \\
|
||||
\textbf{Shape} & \emph{hybrid}: interactive advisory dialogue $+$ batch pipelines (indexing, eval runs) \\
|
||||
\textbf{Constraints} & EU AI Act (logging, documentation, human oversight); GDPR \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.2cm}
|
||||
Two Mediums surprise students:
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item \textbf{D3}: users accept seconds for an advisory answer -- the concern is \emph{cost per request}, not speed
|
||||
\item \textbf{D4}: a hybrid -- knowledge index eventually consistent, transaction and audit path strictly ACID
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.1cm}
|
||||
Every High traces to (H,\,H) scenarios; the constraints are knock-out conditions for the match.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{This week's exercise: your QAW}
|
||||
\begin{projektbox}
|
||||
\footnotesize Run a \textbf{compressed QAW} in stakeholder roles (retail customer, compliance officer, operations engineer, product owner):
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item brainstorm, consolidate, prioritise scenarios; refine the top candidates into the \textbf{six-part form} -- each with a \emph{numeric} response measure
|
||||
\item assemble a \textbf{utility tree}; identify the \textbf{(H,\,H) leaves}
|
||||
\end{itemize}
|
||||
\textbf{Deliverable:} $\geq 8$ scenarios, $\geq 3$ addressing the AI components (answer correctness, token cost per request, provider migration).
|
||||
\end{projektbox}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{hinweisbox}
|
||||
\small Not a warm-up: the (H,\,H) leaves become the \textbf{weights of your requirements profile} (A1, next week) -- matched in your week-6 ADR, defended in week 14.
|
||||
\end{hinweisbox}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% SUMMARY
|
||||
% ============================================
|
||||
\section{Summary}
|
||||
|
||||
\begin{frame}{Summary}
|
||||
\footnotesize
|
||||
\begin{enumerate}\setlength\itemsep{2pt}
|
||||
\item Twelve dimensions in five groups -- each a recurring question, \textbf{named and instrumented}: \emph{no instrument, no dimension}
|
||||
\item ISO/IEC 25010:2023 supplies the names -- and since 2023 covers AI systems without private extensions
|
||||
\item ASRs are vague and implicit $\to$ \textbf{elicited} in a QAW; they discriminate only as \textbf{six-part scenarios} -- the response measure (number $+$ unit) is non-negotiable
|
||||
\item The \textbf{utility tree} derives the weights: (H,\,H) leaves $\to$ High; \textbf{High $=$ veto claim}
|
||||
\item $R(a) = (w_1, \dots, w_{12};\, S(a);\, K(a))$ -- weights, measured shape, knock-out constraints
|
||||
\end{enumerate}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{keypoint}
|
||||
\textbf{Maxim 6.} An architecture decision without a response measure is an \emph{opinion}; with a response measure and a fitness function it is a \emph{testable hypothesis}.
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Next week}
|
||||
\begin{columns}[T]
|
||||
\begin{column}{0.55\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Lecture 3 -- the supply side and the match}}
|
||||
\begin{itemize}
|
||||
\item the seven candidate patterns, previewed
|
||||
\item capability profiles $C(p)$ via \textbf{tactics}
|
||||
\item the three-stage, non-compensatory \textbf{fit} procedure
|
||||
\item worked mini-match: the advisory platform (C10!) against three candidates
|
||||
\item recording decisions: \textbf{ADR / MADR}
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\begin{column}{0.42\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Reading}}
|
||||
\begin{itemize}
|
||||
\item this week: script Part I, Sections 2--3
|
||||
\item ahead: Part I, Sections 4--6
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.3cm}
|
||||
\textcolor{bankblue}{\textbf{Exercise}}
|
||||
\begin{itemize}
|
||||
\item Requirements workshop I: QAW $+$ utility tree
|
||||
\item \textbf{A1 due end of week 3}
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% END
|
||||
% ============================================
|
||||
{
|
||||
\setbeamertemplate{footline}{}
|
||||
\begin{frame}[plain]
|
||||
\vfill
|
||||
\begin{center}
|
||||
\includegraphics[width=0.25\textwidth]{FHGR_Logo_Large}\\[1cm]
|
||||
{\LARGE\bfseries\textcolor{bankblue}{Thank you!}}\\[0.8cm]
|
||||
{\large Dr.\ Florian Herzog}\\[0.2cm]
|
||||
{\normalsize Fachhochschule Graub\"unden, Chur}\\[0.5cm]
|
||||
{\small\textcolor{codegray}{AISE502 -- AI in Software Engineering II}}
|
||||
\end{center}
|
||||
\vfill
|
||||
\end{frame}
|
||||
}
|
||||
|
||||
\end{document}
|
||||
BIN
Folien/original_default_theme/AISE502_Vorlesung_3_Folien.pdf
Normal file
717
Folien/original_default_theme/AISE502_Vorlesung_3_Folien.tex
Normal file
@ -0,0 +1,717 @@
|
||||
\documentclass[aspectratio=169,12pt]{beamer}
|
||||
|
||||
% ============================================
|
||||
% THEME AND APPEARANCE
|
||||
% ============================================
|
||||
\usetheme{default}
|
||||
\usecolortheme{default}
|
||||
\usefonttheme{professionalfonts}
|
||||
\setbeamertemplate{navigation symbols}{}
|
||||
\setbeamertemplate{footline}{}
|
||||
\setbeamertemplate{frametitle continuation}{}
|
||||
|
||||
% ============================================
|
||||
% PACKAGES
|
||||
% ============================================
|
||||
\usepackage[utf8]{inputenc}
|
||||
\usepackage[T1]{fontenc}
|
||||
\usepackage[british]{babel}
|
||||
\usepackage{graphicx}
|
||||
\usepackage{hyperref}
|
||||
\usepackage{xcolor}
|
||||
\usepackage{booktabs}
|
||||
\usepackage{tcolorbox}
|
||||
\usepackage{amsmath}
|
||||
\usepackage{amssymb}
|
||||
\usepackage{tikz}
|
||||
\usetikzlibrary{shapes.geometric, arrows.meta, positioning, fit, backgrounds, calc}
|
||||
|
||||
% ============================================
|
||||
% COLORS (same as script)
|
||||
% ============================================
|
||||
\definecolor{bankblue}{rgb}{0.0,0.28,0.67}
|
||||
\definecolor{bankgreen}{rgb}{0.13,0.55,0.13}
|
||||
\definecolor{bankred}{rgb}{0.7,0.13,0.13}
|
||||
\definecolor{aiviolet}{rgb}{0.42,0.19,0.58}
|
||||
\definecolor{backcolour}{rgb}{0.95,0.95,0.92}
|
||||
\definecolor{codegray}{rgb}{0.5,0.5,0.5}
|
||||
|
||||
% Beamer color setup
|
||||
\setbeamercolor{structure}{fg=bankblue}
|
||||
\setbeamercolor{frametitle}{fg=white,bg=bankblue}
|
||||
\setbeamercolor{title}{fg=white,bg=bankblue}
|
||||
\setbeamercolor{block title}{fg=white,bg=bankblue}
|
||||
\setbeamercolor{block body}{bg=blue!5!white}
|
||||
\setbeamercolor{block title alerted}{fg=white,bg=bankred}
|
||||
\setbeamercolor{block body alerted}{bg=red!5!white}
|
||||
\setbeamercolor{block title example}{fg=white,bg=bankgreen}
|
||||
\setbeamercolor{block body example}{bg=green!5!white}
|
||||
\setbeamercolor{item}{fg=bankblue}
|
||||
\setbeamercolor{subitem}{fg=bankblue!80}
|
||||
\setbeamercolor{itemize item}{fg=bankblue}
|
||||
\setbeamercolor{enumerate item}{fg=bankblue}
|
||||
|
||||
% Bullet style
|
||||
\setbeamertemplate{itemize item}{\raisebox{0.12ex}{$\blacktriangleright$}}
|
||||
\setbeamertemplate{itemize subitem}{\raisebox{0.12ex}{\small$\triangleright$}}
|
||||
\setbeamertemplate{enumerate items}[default]
|
||||
|
||||
% ============================================
|
||||
% CUSTOM TCOLORBOXES (same as script)
|
||||
% ============================================
|
||||
\newtcolorbox{keypoint}{
|
||||
colback=blue!5!white,
|
||||
colframe=bankblue,
|
||||
title=Key Concept,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{examplebox}[1][]{
|
||||
colback=green!5!white,
|
||||
colframe=bankgreen,
|
||||
title={Example: #1},
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{definitionbox}[1][]{
|
||||
colback=yellow!5!white,
|
||||
colframe=yellow!50!black,
|
||||
title={Definition: #1},
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{thinkbox}{
|
||||
colback=orange!5!white,
|
||||
colframe=orange!60!black,
|
||||
title=Discussion,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{hinweisbox}{
|
||||
colback=red!5!white,
|
||||
colframe=bankred,
|
||||
title=Important Note,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{ailinse}[1][]{
|
||||
colback=violet!5!white,
|
||||
colframe=aiviolet,
|
||||
title={AI Lens: #1},
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{projektbox}{
|
||||
colback=blue!3!white,
|
||||
colframe=bankblue!70,
|
||||
title=Project Link: Portfolio Intelligence Platform,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
% ============================================
|
||||
% FOOTER WITH LOGO
|
||||
% ============================================
|
||||
\setbeamertemplate{footline}{%
|
||||
\leavevmode%
|
||||
\hbox{%
|
||||
\begin{beamercolorbox}[wd=0.5\paperwidth,ht=2ex,dp=0.5ex,leftskip=0.5em]{footline}%
|
||||
\usebeamerfont{footline}\textcolor{codegray}{\tiny\insertframenumber{} / \inserttotalframenumber}%
|
||||
\end{beamercolorbox}%
|
||||
\begin{beamercolorbox}[wd=0.35\paperwidth,ht=2ex,dp=0.5ex,center]{footline}%
|
||||
\usebeamerfont{footline}\textcolor{codegray}{\tiny AISE502 -- AI in Software Engineering II}%
|
||||
\end{beamercolorbox}%
|
||||
\begin{beamercolorbox}[wd=0.15\paperwidth,ht=2ex,dp=0.5ex,rightskip=0.5em,right]{footline}%
|
||||
\includegraphics[height=1.5ex]{FHGR_Logo_small}%
|
||||
\end{beamercolorbox}%
|
||||
}%
|
||||
\vskip0pt%
|
||||
}
|
||||
|
||||
% ============================================
|
||||
% DOCUMENT
|
||||
% ============================================
|
||||
\begin{document}
|
||||
|
||||
% ============================================
|
||||
% TITLE SLIDE
|
||||
% ============================================
|
||||
{
|
||||
\setbeamertemplate{footline}{}
|
||||
\begin{frame}[plain]
|
||||
\vfill
|
||||
\begin{center}
|
||||
\includegraphics[width=0.3\textwidth]{FHGR_Logo_Large}\\[1cm]
|
||||
{\LARGE\bfseries\textcolor{bankblue}{AISE502: AI in Software Engineering II}}\\[0.6cm]
|
||||
{\large Lecture 3: The Supply Side, the Match, and the Decision Record}\\[0.3cm]
|
||||
{\small\textcolor{codegray}{Script: Part I, Sections 4--6}}\\[0.8cm]
|
||||
{\normalsize Dr.\ Florian Herzog}\\[0.2cm]
|
||||
{\small Fachhochschule Graub\"unden, Chur}\\[0.2cm]
|
||||
{\small Autumn Semester 2026}
|
||||
\end{center}
|
||||
\vfill
|
||||
\end{frame}
|
||||
}
|
||||
|
||||
% ============================================
|
||||
% AGENDA
|
||||
% ============================================
|
||||
\begin{frame}{Agenda}
|
||||
\small
|
||||
\begin{enumerate}\setlength\itemsep{1pt}
|
||||
\item Recap: the demand side is built
|
||||
\item The seven candidates: a first look
|
||||
\item Tactics: the causal mechanism from structure to quality
|
||||
\item Deriving a capability rating $c_i(p)$
|
||||
\item The match: what the construction dictates
|
||||
\item The three-stage fit procedure
|
||||
\item The mechanics on a real case: matching the advisory platform (C10)
|
||||
\item Why the weighted sum fails
|
||||
\item Recording the decision: ADR and MADR
|
||||
\item The measurement contract
|
||||
\end{enumerate}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% RECAP
|
||||
% ============================================
|
||||
\section{Recap}
|
||||
|
||||
\begin{frame}{Recap: where we are}
|
||||
\footnotesize
|
||||
\begin{center}
|
||||
\small demand $\;\to\;$ \textbf{supply} $\;\to\;$ \textbf{match} $\;\to\;$ \textbf{record} $\;\to\;$ test
|
||||
\end{center}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\textbf{Done} (weeks 1--2): twelve dimensions; scenarios with response measures; utility tree; weights, shape, constraints -- $R(a)$, worked for C10 and the back-office tool.
|
||||
|
||||
\vspace{0.15cm}
|
||||
\textbf{Today} -- the remaining three framework elements:
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item the \textbf{supply side} $C(p)$: seven candidate patterns, rated \emph{by derivation}, not by taste
|
||||
\item the \textbf{match} $\mathrm{fit}(a,p)$: three stages, non-compensatory -- run live on your project class C10
|
||||
\item the \textbf{record}: ADR/MADR and the measurement contract
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{hinweisbox}
|
||||
\footnotesize \textbf{A1 (requirements dossier) is due this week} -- scenarios, utility tree, $R(\text{platform})$ with weights, shape, and constraints.
|
||||
\end{hinweisbox}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% SEVEN CANDIDATES
|
||||
% ============================================
|
||||
\section{The Seven Candidates}
|
||||
|
||||
\begin{frame}{The seven candidates (1/2)}
|
||||
\footnotesize
|
||||
The set $P$ of the framework -- each in one sentence, with its signature strength and cost:
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{center}
|
||||
\scriptsize
|
||||
\begin{tabular}{@{}p{2.5cm}p{5.0cm}p{2.6cm}p{2.8cm}@{}}
|
||||
\toprule
|
||||
\textbf{Pattern (code)} & \textbf{Structure in one sentence} & \textbf{Signature strength} & \textbf{Signature cost} \\
|
||||
\midrule
|
||||
Layered / 3-tier (L) & one deployable, cut into horizontal \emph{technical} layers & simple and cheap: one build, one database & a typical feature cuts across all layers \\
|
||||
Modular monolith (MM) & one deployable, cut into \emph{domain} modules with machine-enforced boundaries & monolith economics with modular evolvability & boundaries erode without governance \\
|
||||
Hexagonal (HX) & a domain core behind technology-neutral ports with swappable adapters & hermetic testability; swappable technology & indirection that pays off only under change \\
|
||||
Microservices (MS) & many independently deployable services, database per service & team scaling; independent deployment & no ACID across services; highest operating cost \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\scriptsize\textcolor{codegray}{You have met four in production dress: Stack Overflow ran L-style, Monzo runs MS, Prime Video's failed design was SL, Segment's rollback was an MS cut.}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{The seven candidates (2/2)}
|
||||
\footnotesize
|
||||
\begin{center}
|
||||
\scriptsize
|
||||
\begin{tabular}{@{}p{2.5cm}p{5.0cm}p{2.6cm}p{2.8cm}@{}}
|
||||
\toprule
|
||||
\textbf{Pattern (code)} & \textbf{Structure in one sentence} & \textbf{Signature strength} & \textbf{Signature cost} \\
|
||||
\midrule
|
||||
Event-driven (EDA) & components communicate through asynchronous events via a broker & decoupling, elasticity, fault isolation & eventual consistency; end-to-end testing hard \\
|
||||
Pipes-and-filters (PF) & data flows through a chain or DAG of processing steps & throughput and reproducibility for batch work & not built for interactive latency \\
|
||||
Serverless / FaaS (SL) & functions on managed infrastructure: scale-to-zero, per-execution billing & elasticity; zero idle cost & cold starts; cost inverts under sustained load \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{hinweisbox}
|
||||
\footnotesize \textbf{HX is not a competitor in the same race.} It organises dependencies \emph{inside} whichever host it is applied to and \textbf{composes} with the other six -- a hexagonal modular monolith is \emph{one} coherent design, not two rival ones.
|
||||
\end{hinweisbox}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% TACTICS
|
||||
% ============================================
|
||||
\section{Tactics}
|
||||
|
||||
\begin{frame}{Three levels of design vocabulary}
|
||||
\begin{definitionbox}[Architectural pattern (style)]
|
||||
\small A named, documented \textbf{macro-structure}: a topology of elements, permitted relations between them, and known consequences.
|
||||
\end{definitionbox}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{definitionbox}[Architectural tactic]
|
||||
\small An \textbf{elementary design decision} that directly influences the response of \emph{one} quality attribute -- the atomic unit of architectural design. Examples: \emph{heartbeat}, \emph{redundancy} (availability); \emph{use an intermediary}, \emph{defer binding} (modifiability); \emph{introduce concurrency}, \emph{maintain multiple copies} (performance).
|
||||
\end{definitionbox}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\small Students routinely conflate the levels -- the framework keeps them apart, because its \textbf{explanatory mechanism lives exactly in the gap} between them.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Patterns are bundles of tactics}
|
||||
\begin{keypoint}
|
||||
\footnotesize A pattern structurally \textbf{privileges} some tactics while \textbf{impeding} others -- so every pattern helps some quality attributes and hurts others \emph{by construction}, not by accident. The causal chain \textbf{topology $\to$ tactics $\to$ quality attribute responses} makes every $++$ and every $--$ explainable and testable.
|
||||
\end{keypoint}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{examplebox}[EDA as a tactics bundle]
|
||||
\footnotesize An event-driven architecture structurally packages \emph{use an intermediary} (modifiability) and \emph{introduce concurrency} (performance) -- while structurally \emph{impeding} \emph{transactions} (consistency). It helps D7 and hurts D4 by construction.
|
||||
\end{examplebox}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\footnotesize
|
||||
And one demarcation for everything that follows: patterns are evaluated \textbf{per subsystem}, not per company logo -- hybrids are the normal case.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Deriving a rating $c_i(p)$: three sources, applied in order}
|
||||
\footnotesize
|
||||
A rating $c_i(p) \in \{++, +, \circ, -, --\}$ is an \emph{ordinal} claim: how well does the topology structurally support dimension $D_i$?
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{enumerate}\setlength\itemsep{3pt}
|
||||
\item \textbf{Tactics analysis} -- which tactics does the topology make cheap, which does it impede? The causal core: a $--$ that cannot be traced to a structural impediment is an \emph{assertion}, not a rating.
|
||||
\item \textbf{Published ratings} -- Richards \& Ford's star ratings calibrate ours, five-step to five-step ($5\star \to ++$, \dots, $1\star \to --$); \textbf{every deviation is footnoted}. Where no stars exist (HX, SL): primary sources, flagged.
|
||||
\item \textbf{Documented production systems} -- calibration points: a rating that contradicts a documented production result must either explain the context difference or \textbf{yield}.
|
||||
\end{enumerate}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize A capability rating is a \textbf{testable prediction}, not a preference. Supply is constructed with the same rigour as demand.
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Micro-derivation 1: why EDA rates $++$ on D7 (evolvability)}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{3pt}
|
||||
\item \textbf{Tactics analysis:} the broker topology \emph{is} the tactic ``use an intermediary'', built into the macro-structure. A new consumer -- a recommendation engine, an audit feed -- attaches to the event stream \textbf{without touching a single producer}. D7's response measure, \emph{change dispersion}, is structurally minimised: adding functionality is additive, not invasive.
|
||||
\item \textbf{Published rating:} Richards \& Ford rate the style's evolvability at five stars $\to$ $++$, no deviation to footnote.
|
||||
\item \textbf{Production evidence:} LinkedIn's Kafka ecosystem grew for a decade by attaching new consumers to the same durable log.
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{hinweisbox}
|
||||
\footnotesize The rating is a \textbf{trade}, exactly as A2 predicts: the same intermediary that decouples producers from consumers also \emph{impedes transactions and hides the workflow} -- the costs land on D4 and D9.
|
||||
\end{hinweisbox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Micro-derivation 2: why microservices rate $--$ on D4 (consistency)}
|
||||
\small
|
||||
\begin{itemize}\setlength\itemsep{3pt}
|
||||
\item \textbf{Tactics analysis:} the weakness is \emph{structural}. Database-per-service is constitutive of the pattern -- so \textbf{no ACID transaction spans a service boundary}. An invariant crossing services (order $\to$ stock $\to$ ledger) must be maintained by a \textbf{saga}: a sequence of local transactions with \emph{compensating actions}. Intermediate states are visible; compensation is \emph{not} rollback.
|
||||
\item Against D4's response measures (invariant violations: target 0 for ledgers), the topology impedes the transaction tactic \textbf{by construction}. Hence $--$.
|
||||
\item \textbf{Production evidence:} a documented mitigation exists but is conditional -- Monzo makes sagas work under \emph{extreme technological homogeneity}.
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\small The matching procedure handles exactly this case: a \textbf{veto} on a High-weight dimension that only a \emph{documented} mitigation can lift.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{What $++$ and $--$ look like (selection)}
|
||||
\scriptsize
|
||||
\begin{center}
|
||||
\begin{tabular}{@{}p{2.4cm}p{5.4cm}p{5.3cm}@{}}
|
||||
\toprule
|
||||
\textbf{Dimension} & \textbf{What $++$ looks like structurally} & \textbf{What $--$ (or the weak end) looks like} \\
|
||||
\midrule
|
||||
D2 Write scalability & partitioned ingest with elastic consumers (EDA, SL) & one relational database receiving every write (L) \\
|
||||
D4 Consistency & one ACID transaction boundary around all state (L, MM) & sagas across service databases (MS); eventual consistency through a broker (EDA) \\
|
||||
D5 Availability & bulkheaded services: blast radius one service (MS, EDA) & one process: blast radius $100\,\%$ by construction (L, MM: $-$) \\
|
||||
D8 Simplicity \& TTM & one repository, one pipeline, shipping this week (L, PF) & platform engineering before the first feature (MS, EDA) \\
|
||||
D9 Testability & hermetic domain tests behind ports (HX) & verification only against an integrated environment (L: $-$); event flows resisting end-to-end tests (EDA: $-$) \\
|
||||
D12 AI integrability & a natural queue, port, and measurement point (EDA, HX, PF) & an honest middle: platform timeouts vs.\ minutes-long AI runs (SL: $\circ$) \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\footnotesize Note the refused $--$ entries (D6, D12 in the full table): where a weakness is genuinely two-faced or workload-dependent, the honest rating is a \textbf{middle} one -- the supply-side counterpart of A4's ban on vague requirements.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Native workload shape -- and $C(p)$ assembled}
|
||||
\small
|
||||
Every pattern has a \textbf{native workload shape} $S(p)$ -- a \emph{type}, not a rating:
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{center}
|
||||
\footnotesize
|
||||
\begin{tabular}{@{}ll@{}}
|
||||
\toprule
|
||||
L, MM, MS & interactive request/response \\
|
||||
EDA & streams and asynchronous flows \\
|
||||
PF & scheduled batch \\
|
||||
SL & event-triggered, short-lived work \\
|
||||
HX & inherits its host's shape (composition pattern) \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{definitionbox}[Capability profile $C(p)$]
|
||||
\small $C(p) = \bigl(c_1(p), \dots, c_{12}(p);\; S(p)\bigr)$, $c_i(p) \in \{++, +, \circ, -, --\}$: ordinal ratings of structural support for each dimension, justified through \textbf{tactics}, anchored in published star ratings, deviations footnoted -- plus the native shape, which feeds the workload-shape \textbf{gate} of the match.
|
||||
\end{definitionbox}
|
||||
|
||||
\vspace{0.15cm}
|
||||
Part II derives all seven profiles in full -- starting next week.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{AI Lens: an LLM component stresses D3, D10, and D12}
|
||||
\begin{ailinse}[Axis B preview]
|
||||
\small Suppose one component is an LLM call. Nothing new is needed -- the coordinate system already carries it:
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item \textbf{D3}: LLM calls cost \emph{seconds} where classical calls cost milliseconds -- time behaviour becomes a \emph{structural} concern (queues, asynchronous integration, caching)
|
||||
\item \textbf{D10}: per-token pricing makes operating cost a \emph{per-request} attribute -- a bad prompt chain is a cost regression the way an $n{+}1$ query is a latency regression
|
||||
\item \textbf{D12}: the pattern either provides the \emph{queue, port, and measurement point} -- or it does not; the seven patterns differ sharply on exactly that
|
||||
\end{itemize}
|
||||
\end{ailinse}
|
||||
|
||||
\vspace{0.25cm}
|
||||
\small The supply side absorbs AI as \textbf{ratings on existing dimensions} -- assumption A6 at work.
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% THE MATCH
|
||||
% ============================================
|
||||
\section{The Match}
|
||||
|
||||
\begin{frame}{What the construction dictates}
|
||||
\footnotesize
|
||||
Three properties of the profiles are \emph{results of their construction} -- and each imposes a requirement on any admissible aggregation:
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{enumerate}\setlength\itemsep{3pt}
|
||||
\item \textbf{Constraints are knock-outs.} A violated obligation cannot be traded against merit $\to$ eliminate \emph{before} any scoring. The \textbf{workload shape} belongs to the same family: a pattern whose native $S(p)$ contradicts the dominant $S(a)$ cannot carry the class's core.
|
||||
\item \textbf{High weights carry vetoes.} A High weight \emph{was defined} as the presence of (H,\,H) leaves -- scenarios whose failure is existential. A pattern structurally weak exactly there fails those scenarios; excellence elsewhere does not un-fail them $\to$ \textbf{non-compensatory} on High-weight dimensions.
|
||||
\item \textbf{Everything is ordinal.} Ordinal inputs license ordinal outputs -- \emph{rankings and exclusions, never percentages} -- and every result must be checked for stability under plausible re-weighting.
|
||||
\end{enumerate}
|
||||
|
||||
\vspace{0.15cm}
|
||||
These three requirements admit \textbf{essentially one procedure} \dots
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{The three-stage fit procedure}
|
||||
\begin{definitionbox}[Architecture--application fit $\mathrm{fit}(a,p)$]
|
||||
\footnotesize An ordinal aggregate on the scale $\{++, +, \circ, -, --\}$, determined by a deliberately \textbf{non-compensatory, three-stage procedure}:
|
||||
\begin{enumerate}\setlength\itemsep{2pt}
|
||||
\item \textbf{Knock-out screening.} Hard constraints $K(a)$ eliminate patterns before any scoring. The \emph{workload-shape gate}: if $S(p)$ does not match the dominant $S(a)$, the cell is capped at $\circ$ (subsystem role) -- $+$ only for a \emph{constitutive} subsystem of a shape-hybrid class; $-$/$--$ where it would harm binding scenarios.
|
||||
\item \textbf{Veto rule on High-weight dimensions.} $c_i(p) = --$ on a High dimension caps the fit at $-$; $c_i(p) = -$ caps it at $\circ$ -- \emph{unless a documented mitigation exists} (a tactic or hybrid with production evidence), in which case the cell says so and the cap is lifted.
|
||||
\item \textbf{Holistic ordinal reading with mandatory sensitivity analysis.} Survivors are ranked by support of the High set; clustering Medium conflicts can downgrade one step. Result: a \emph{ranking with exclusions}. If it flips under plausible re-weighting, that instability is a genuine \textbf{trade-off point} -- escalate to scenario-based analysis (ATAM).
|
||||
\end{enumerate}
|
||||
\end{definitionbox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Why non-compensatory -- and why the veto can be lifted}
|
||||
\footnotesize
|
||||
\textbf{Non-compensatory mirrors how architectural failure actually works:} Prime Video's serverless design was \emph{excellent} on elasticity and deployability -- none of that compensated for the cost structure its workload shape imposed.
|
||||
|
||||
\vspace{0.15cm}
|
||||
\textbf{The mitigation clause keeps the rule honest:}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item a veto can be lifted -- but only by a \emph{documented} tactic or hybrid with production evidence
|
||||
\item ``pod-sharded replication of the monolith'' (Shopify) or ``event-driven edges around an ACID core'' -- \textbf{never by optimism}
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{examplebox}[Same class -- opposite structures: LMAX and Monzo]
|
||||
\footnotesize LMAX runs core trading on \emph{one} deterministic, event-sourced JVM thread ($6$M orders/s); Monzo runs banking on $\sim 2{,}800$ microservices. \textbf{Both} satisfy the class's binding scenarios. Lesson: $R(a)$ alone defines a \emph{feasible set}; the constraints and context in $K(a)$ decide \emph{within} it. A theory pretending to compute a single winner would be falsified by this pair.
|
||||
\end{examplebox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{The mini-match: $R(\text{C10})$ against L, MM, MS -- stage 1}
|
||||
\small
|
||||
\textbf{The demand side} (from week 2): High on $\{$D6, D7, D9, D10, D12$\}$; shape \emph{hybrid}; EU AI Act and GDPR in $K$.
|
||||
|
||||
\vspace{0.25cm}
|
||||
\textbf{Stage 1 -- knock-out and shape gate:}
|
||||
\begin{itemize}\setlength\itemsep{3pt}
|
||||
\item $S(\text{C10})$ is hybrid: an interactive advisory dialogue at the core, batch/asynchronous pipelines (indexing, evaluation) beside it
|
||||
\item all three candidates are natively \emph{interactive} $\to$ all pass the gate \textbf{for the core} -- the pipelines will be carried by PF- and EDA-shaped \emph{subsystems} in any design
|
||||
\item no hard constraint eliminates a candidate outright -- but note for stage 3: the AI Act's logging and oversight duties \emph{favour} structures where every model call flows through \textbf{one auditable path}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{The mini-match -- stage 2: vetoes on the High dimensions}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{4pt}
|
||||
\item \textbf{L (layered):} rates $-$ on High-weighted \textbf{D7} $\to$ cap $\circ$ unless mitigated -- and at C10's extreme change rate of models, prompts, and frameworks \emph{there is none}: technical layers give the non-deterministic component no boundary, no queue, no measurement point. \textbf{D9} is a second $-$ on a High dimension; D12 offers only $\circ$. Two unmitigated vetoes that \emph{cluster} push the stage-3 reading one step below the cap: $\mathbf{-}$.
|
||||
\item \textbf{MS (microservices):} rates $--$ on High-weighted \textbf{D10} $\to$ would cap at $-$ -- but here the \emph{mitigation clause earns its keep}: C10's cost concern is \textbf{per-request AI cost} (tokens, GPU), governed at a \emph{gateway} -- orthogonal to distribution. The platform-cost veto relaxes to $\circ$. What stops MS from rising further: synchronous service chains \emph{multiply} seconds-scale LLM latency and failure rates, and the pattern's signature payoff (team scaling) sits on \textbf{Low-weighted} D11 -- for a student-sized team the microservice premium buys nothing.
|
||||
\item \textbf{MM (modular monolith):} \textbf{no veto fires at all} -- $+$ or better on every High dimension; its one structural $-$ (D5, blast radius) is Medium-weighted and mitigated by replicated instances.
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{The mini-match -- stage 3 and the verdict}
|
||||
\footnotesize
|
||||
MM leads the High set outright; \textbf{HX inside} raises D9/D12 to $++$ -- the LLM becomes a mockable, swappable adapter on a port.
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{center}
|
||||
\scriptsize
|
||||
\begin{tabular}{@{}p{3.4cm}ccc@{}}
|
||||
\toprule
|
||||
\textbf{High dimension of C10} & \textbf{L} & \textbf{MM ($+$ HX inside)} & \textbf{MS} \\
|
||||
\midrule
|
||||
D6 Security \& auditability & $+$ & $+$ & $\circ$ \\
|
||||
D7 Evolvability & $-$ \emph{(veto)} & $+$ & $++$ \\
|
||||
D9 Testability \& deployability & $-$ \emph{(veto)} & $+$ ($++$ with HX) & $+$ \\
|
||||
D10 Operating cost & $++$ & $++$ & $--$ \emph{(veto, relaxed)} \\
|
||||
D12 AI integrability & $\circ$ & $+$ ($++$ with HX) & $\circ$ \\
|
||||
\midrule
|
||||
\textbf{Verdict $\mathrm{fit}(\text{C10},p)$} & $\mathbf{-}$ & $\mathbf{++}$ & $\mathbf{\circ}$ \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize The \textbf{hexagonal modular monolith} is the primary recommendation -- and it is exactly the architecture of your course project. One profile, three candidates, three stages: a \emph{ranking with exclusions}.
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Discussion}
|
||||
\begin{thinkbox}
|
||||
\small Run the same three candidates against $R(\text{back-office})$ from week 2 -- High on D4, D6, D7, D8, D10. Which veto fires first, and does the verdict change?
|
||||
|
||||
\vspace{0.2cm}
|
||||
Check yourselves: MS now hits \textbf{two unmitigated $--$ vetoes at once} (D8 and D10, both High for this class); L's strengths sit exactly on the class's High set (D4, D8, D10), and only D7 caps it -- liftable by scoping to a small, stable domain. The verdicts become \textbf{L $+$, MM $++$, MS $--$}: the same winner, but a radically re-ordered field.
|
||||
\end{thinkbox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Why the obvious alternative fails}
|
||||
\small
|
||||
Why not score $1$--$5$, multiply by weights, add up ($V = \sum_i w_i \cdot v_i$)? The additive form is licensed only under three conditions -- \textbf{all three fail here}:
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{enumerate}\setlength\itemsep{2pt}
|
||||
\item \textbf{Cardinal (interval) scales} -- but the ratings are ordinal by construction: what would ``microservices score $4.3$ on consistency'' \emph{mean}?
|
||||
\item \textbf{Preferential independence} -- violated \emph{by definition}: A2 says the value of ``scalability $= ++$'' depends on what happens to consistency; trade-offs \emph{are} preferential dependence
|
||||
\item \textbf{Weights as trade-off rates} -- nobody can state, or defend to an auditor, the rate at which audit-trail quality is exchangeable for deployment frequency
|
||||
\end{enumerate}
|
||||
|
||||
\vspace{0.2cm}
|
||||
The AHP repair inherits documented defects: adding an alternative (even a \emph{copy}) can \textbf{reverse the ranking}; Dyer's verdict: ``flawed as a procedure for ranking alternatives''.
|
||||
|
||||
\vspace{0.15cm}
|
||||
\textbf{Kept} from multi-criteria analysis: the \emph{explication discipline} -- criteria on the table, weights argued, options compared. \textbf{Dropped}: the arithmetic pretensions.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Beware pseudo-precision}
|
||||
\begin{hinweisbox}
|
||||
\small A weighted-sum matrix over ordinal ratings produces numbers -- ``pattern A: $3.87$; pattern B: $3.79$'' -- whose significant digits are \textbf{artefacts of the procedure}, not measurements of anything. Such numbers end discussions that should be had (the $0.08$ gap will not survive any plausible re-weighting) and lend false authority to buried assumptions.
|
||||
\end{hinweisbox}
|
||||
|
||||
\vspace{0.3cm}
|
||||
\small The professional habit this module trains is the opposite:
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item report \textbf{rankings with exclusions}, and state the \textbf{veto} behind each exclusion
|
||||
\item run the \textbf{sensitivity analysis}
|
||||
\item if the recommendation flips under plausible weights, you have found a genuine \textbf{trade-off point} -- a \emph{finding} to escalate to stakeholders, not an error to hide with more decimals
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{The status of the matrix}
|
||||
\small
|
||||
Applying the procedure to all pairs yields the $7 \times 10$ matrix of Part IV. One point governs how every cell is read:
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize The matrix is an \textbf{explication and communication instrument} -- a compressed, teachable heuristic that forces criteria, weights, and assumptions into the open -- \emph{not} a computation that determines decisions. The rigorous method behind every contested cell is the \textbf{ATAM}: scenario walk-throughs, sensitivity points, trade-off points, risks.
|
||||
\end{keypoint}
|
||||
|
||||
\vspace{0.2cm}
|
||||
Three honest limits, holding throughout:
|
||||
\begin{enumerate}\setlength\itemsep{2pt}
|
||||
\item the scales are \textbf{ordinal} -- no percentages, ever
|
||||
\item the ratings are \textbf{context-dependent} -- the serverless cost rating literally \emph{inverts} with load shape
|
||||
\item \textbf{hybrids are the normal case} -- the matrix is read \emph{per subsystem}
|
||||
\end{enumerate}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% RECORDING THE DECISION
|
||||
% ============================================
|
||||
\section{Recording the Decision}
|
||||
|
||||
\begin{frame}{The decision is the primary artefact}
|
||||
\small
|
||||
A1 says: what we choose is a \textbf{decision} with high reversal cost -- and undocumented decisions \emph{evaporate}:
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item the code shows \emph{what} was built, never \emph{why}
|
||||
\item within a few staff rotations the rationale is gone; later changes violate constraints nobody remembers -- which is what teams experience as \textbf{``legacy''}
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.15cm}
|
||||
ISO/IEC/IEEE 42010:2022 draws the normative conclusion: a conformant architecture description \textbf{must} record architecture decisions \emph{and their rationale} (Clause 6.10).
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{definitionbox}[Architecture Decision Record (ADR)]
|
||||
\footnotesize A short text document -- one to two pages, \textbf{versioned in the code repository}, one decision per file -- with Nygard's structure: \textbf{Title} $\cdot$ \textbf{Status} (proposed / accepted / deprecated / superseded) $\cdot$ \textbf{Context} (the forces at play, value-neutral) $\cdot$ \textbf{Decision} (active voice: ``We will \dots'') $\cdot$ \textbf{Consequences} (positive \emph{and} negative).
|
||||
\end{definitionbox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Three design choices make the format work -- and MADR extends it}
|
||||
\footnotesize
|
||||
\begin{enumerate}\setlength\itemsep{2pt}
|
||||
\item \textbf{Co-location} -- ADRs live in the repository, next to the code they govern, not in a wiki that dies with the project office
|
||||
\item \textbf{Brevity} -- one decision, one page: a format cheap enough to be used beats a comprehensive one that is not
|
||||
\item \textbf{Immutability} -- a superseded ADR is never edited or deleted; a new ADR supersedes it. The record of \emph{why we changed our minds} is often more valuable than the current answer.
|
||||
\end{enumerate}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\textbf{MADR} adds explicit \textbf{decision drivers} and \textbf{considered options} (each with pros and cons), plus an optional \textbf{confirmation} section.
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize MADR is this module's format for a structural reason: \emph{decision drivers $+$ considered options} is exactly \textbf{one row of the matching matrix in narrative long form} -- a completed matrix is the tabular compression of many MADRs.
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{ADR-011: the LLM gateway decision (your project, week 6)}
|
||||
\begin{tcolorbox}[colback=gray!4!white, colframe=gray!55!black, boxrule=0.6pt, arc=2pt, top=3pt, bottom=3pt, left=6pt, right=6pt]
|
||||
\scriptsize\ttfamily
|
||||
\textbf{ADR-011: Route all LLM calls through one gateway port}\\[2pt]
|
||||
Status: accepted | supersedes ADR-004\\[4pt]
|
||||
\textbf{Context:} providers deprecate models on 6--12-month cycles; token costs must be attributable per request; domain logic must stay testable without paid, non-deterministic API calls.\\[4pt]
|
||||
\textbf{Drivers:} D7 evolvability -- provider change stays cheap $\cdot$ D9 testability -- hermetic tests $\cdot$ D12 -- per-request cost observability\\[4pt]
|
||||
\textbf{Options:} (1) direct provider-SDK calls from domain services $\cdot$ \textbf{(2) one gateway behind a domain-owned port} $\leftarrow$ chosen $\cdot$ (3) per-feature adapters without a shared gateway\\[4pt]
|
||||
\textbf{Consequences:} $+$ provider migration is an adapter task; domain tests run against fakes. $-$ one more runtime component; $\sim$20--50\,ms latency; the gateway needs its own SLO.
|
||||
\end{tcolorbox}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\footnotesize
|
||||
\textbf{Confirmation (measurement contract, in embryonic form):}
|
||||
\begin{itemize}\setlength\itemsep{0pt}
|
||||
\item static rule: no domain module imports the provider SDK (ArchUnit, CI gate, 0 violations)
|
||||
\item eval-harness pass rate $\geq 95\,\%$ on every model/prompt change
|
||||
\item token cost per request $\leq$ budget (p95), monitored continually
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Diagrams and the measurement contract}
|
||||
\small
|
||||
\textbf{C4 -- diagrams for decisions, sparingly:} four zoom levels (system context, container, component, code). For this module, \textbf{container level dominates}: a modular monolith is \emph{one} container with enforced internal boundaries, a microservice system is \emph{many}, an event-driven system inserts a \emph{broker} container between them.
|
||||
|
||||
\vspace{0.25cm}
|
||||
\textbf{The measurement contract} -- the fifth framework element:
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item every ADR ends with the \textbf{fitness functions and thresholds that would tell us the decision has failed}
|
||||
\item static rules as CI gates $\cdot$ scenario response measures as automated tests $\cdot$ cost and latency budgets as telemetry alarms
|
||||
\item in operation, the four \textbf{DORA metrics} test whether the delivery-relevant promises hold
|
||||
\item on breach: a documented evolution path (Strangler Fig) recorded as a \emph{superseding ADR} -- never a silent rewrite
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{AI Lens: an agent drafts the ADR -- a human owns the decision}
|
||||
\begin{ailinse}[Axis A]
|
||||
\small ADRs are an ideal task for AI assistance and a \textbf{hard boundary for AI authority}. An agent with access to the repository, the utility tree, and the matrix can \emph{draft} a competent MADR in minutes: enumerate options, fill pros and cons from the capability profiles, propose fitness functions. Use that. But the decision itself is an \textbf{act of accountability}: a nameable person weighs the drivers, accepts the negative consequences, and answers for them later.
|
||||
\end{ailinse}
|
||||
|
||||
\vspace{0.25cm}
|
||||
\small Second-order effect: agents \emph{read} ADRs and convention files on every run -- documentation quality is reproduced \textbf{at machine speed, in whichever direction it points}. A precise ADR corpus is leverage; a stale one is automated misdirection.
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% SUMMARY
|
||||
% ============================================
|
||||
\section{Summary}
|
||||
|
||||
\begin{frame}{Summary: Part I is complete}
|
||||
\footnotesize
|
||||
\begin{enumerate}\setlength\itemsep{2pt}
|
||||
\item \textbf{Supply:} seven candidates; ratings derived from \emph{tactics}, calibrated against published stars, checked against production -- never taste
|
||||
\item \textbf{Match:} knock-outs and shape gate $\to$ vetoes on High dimensions (liftable only by documented mitigations) $\to$ ordinal reading with sensitivity analysis; weighted sums fail three preconditions -- the matrix is an \emph{explication instrument}, not a computation
|
||||
\item Worked end to end: C10 vs.\ L/MM/MS $\to$ \textbf{hexagonal modular monolith} ($++$) -- your project architecture
|
||||
\item \textbf{Record:} MADR -- drivers $+$ options $=$ one matrix row; co-located, brief, immutable
|
||||
\item \textbf{Measure:} every ADR ends in a measurement contract; breach $\to$ superseding ADR
|
||||
\end{enumerate}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize The chain to remember: class $\to$ scenarios $\to$ utility tree $\to$ $R(a)$ $\to$ non-compensatory match against $C(p)$ $\to$ ADR $\to$ measurement contract $\to$ operation -- and, because profiles drift, back around.
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{This week and next week}
|
||||
\begin{columns}[T]
|
||||
\begin{column}{0.55\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Exercise this week}}
|
||||
\begin{itemize}\small
|
||||
\item Requirements workshop II: finalise $R(\text{platform})$ -- weights, workload shape, knock-out constraints
|
||||
\item ontology as a contract
|
||||
\item \textbf{A1 due: requirements dossier} (scenarios $+$ utility tree $+$ $R(a)$)
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\begin{column}{0.42\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Lecture 4}}
|
||||
\begin{itemize}\small
|
||||
\item Part II begins: \textbf{Layered, Modular Monolith, Hexagonal}
|
||||
\item problem $\to$ profile $\to$ engineering $\to$ ``build it and study it''
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\textcolor{bankblue}{\textbf{Reading}}
|
||||
\begin{itemize}\small
|
||||
\item this week: Part I, Sections 4--6
|
||||
\item ahead: Part II, L/MM/HX
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% END
|
||||
% ============================================
|
||||
{
|
||||
\setbeamertemplate{footline}{}
|
||||
\begin{frame}[plain]
|
||||
\vfill
|
||||
\begin{center}
|
||||
\includegraphics[width=0.25\textwidth]{FHGR_Logo_Large}\\[1cm]
|
||||
{\LARGE\bfseries\textcolor{bankblue}{Thank you!}}\\[0.8cm]
|
||||
{\large Dr.\ Florian Herzog}\\[0.2cm]
|
||||
{\normalsize Fachhochschule Graub\"unden, Chur}\\[0.5cm]
|
||||
{\small\textcolor{codegray}{AISE502 -- AI in Software Engineering II}}
|
||||
\end{center}
|
||||
\vfill
|
||||
\end{frame}
|
||||
}
|
||||
|
||||
\end{document}
|
||||
BIN
Folien/original_default_theme/AISE502_Vorlesung_4_Folien.pdf
Normal file
866
Folien/original_default_theme/AISE502_Vorlesung_4_Folien.tex
Normal file
@ -0,0 +1,866 @@
|
||||
\documentclass[aspectratio=169,12pt]{beamer}
|
||||
|
||||
% ============================================
|
||||
% THEME AND APPEARANCE
|
||||
% ============================================
|
||||
\usetheme{default}
|
||||
\usecolortheme{default}
|
||||
\usefonttheme{professionalfonts}
|
||||
\setbeamertemplate{navigation symbols}{}
|
||||
\setbeamertemplate{footline}{}
|
||||
\setbeamertemplate{frametitle continuation}{}
|
||||
|
||||
% ============================================
|
||||
% PACKAGES
|
||||
% ============================================
|
||||
\usepackage[utf8]{inputenc}
|
||||
\usepackage[T1]{fontenc}
|
||||
\usepackage[british]{babel}
|
||||
\usepackage{graphicx}
|
||||
\usepackage{hyperref}
|
||||
\usepackage{xcolor}
|
||||
\usepackage{booktabs}
|
||||
\usepackage{tcolorbox}
|
||||
\usepackage{amsmath}
|
||||
\usepackage{amssymb}
|
||||
\usepackage{tikz}
|
||||
\usetikzlibrary{shapes.geometric, arrows.meta, positioning, fit, backgrounds, calc}
|
||||
|
||||
% ============================================
|
||||
% COLORS (same as script)
|
||||
% ============================================
|
||||
\definecolor{bankblue}{rgb}{0.0,0.28,0.67}
|
||||
\definecolor{bankgreen}{rgb}{0.13,0.55,0.13}
|
||||
\definecolor{bankred}{rgb}{0.7,0.13,0.13}
|
||||
\definecolor{aiviolet}{rgb}{0.42,0.19,0.58}
|
||||
\definecolor{backcolour}{rgb}{0.95,0.95,0.92}
|
||||
\definecolor{codegray}{rgb}{0.5,0.5,0.5}
|
||||
|
||||
% Beamer color setup
|
||||
\setbeamercolor{structure}{fg=bankblue}
|
||||
\setbeamercolor{frametitle}{fg=white,bg=bankblue}
|
||||
\setbeamercolor{title}{fg=white,bg=bankblue}
|
||||
\setbeamercolor{block title}{fg=white,bg=bankblue}
|
||||
\setbeamercolor{block body}{bg=blue!5!white}
|
||||
\setbeamercolor{block title alerted}{fg=white,bg=bankred}
|
||||
\setbeamercolor{block body alerted}{bg=red!5!white}
|
||||
\setbeamercolor{block title example}{fg=white,bg=bankgreen}
|
||||
\setbeamercolor{block body example}{bg=green!5!white}
|
||||
\setbeamercolor{item}{fg=bankblue}
|
||||
\setbeamercolor{subitem}{fg=bankblue!80}
|
||||
\setbeamercolor{itemize item}{fg=bankblue}
|
||||
\setbeamercolor{enumerate item}{fg=bankblue}
|
||||
|
||||
% Bullet style
|
||||
\setbeamertemplate{itemize item}{\raisebox{0.12ex}{$\blacktriangleright$}}
|
||||
\setbeamertemplate{itemize subitem}{\raisebox{0.12ex}{\small$\triangleright$}}
|
||||
\setbeamertemplate{enumerate items}[default]
|
||||
|
||||
% ============================================
|
||||
% CUSTOM TCOLORBOXES (same as script)
|
||||
% ============================================
|
||||
\newtcolorbox{keypoint}{
|
||||
colback=blue!5!white,
|
||||
colframe=bankblue,
|
||||
title=Key Concept,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{examplebox}[1][]{
|
||||
colback=green!5!white,
|
||||
colframe=bankgreen,
|
||||
title={Example: #1},
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{definitionbox}[1][]{
|
||||
colback=yellow!5!white,
|
||||
colframe=yellow!50!black,
|
||||
title={Definition: #1},
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{thinkbox}{
|
||||
colback=orange!5!white,
|
||||
colframe=orange!60!black,
|
||||
title=Discussion,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{hinweisbox}{
|
||||
colback=red!5!white,
|
||||
colframe=bankred,
|
||||
title=Important Note,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{ailinse}[1][]{
|
||||
colback=violet!5!white,
|
||||
colframe=aiviolet,
|
||||
title={AI Lens: #1},
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{projektbox}{
|
||||
colback=blue!3!white,
|
||||
colframe=bankblue!70,
|
||||
title=Project Link: Portfolio Intelligence Platform,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
% ============================================
|
||||
% FOOTER WITH LOGO
|
||||
% ============================================
|
||||
\setbeamertemplate{footline}{%
|
||||
\leavevmode%
|
||||
\hbox{%
|
||||
\begin{beamercolorbox}[wd=0.5\paperwidth,ht=2ex,dp=0.5ex,leftskip=0.5em]{footline}%
|
||||
\usebeamerfont{footline}\textcolor{codegray}{\tiny\insertframenumber{} / \inserttotalframenumber}%
|
||||
\end{beamercolorbox}%
|
||||
\begin{beamercolorbox}[wd=0.35\paperwidth,ht=2ex,dp=0.5ex,center]{footline}%
|
||||
\usebeamerfont{footline}\textcolor{codegray}{\tiny AISE502 -- AI in Software Engineering II}%
|
||||
\end{beamercolorbox}%
|
||||
\begin{beamercolorbox}[wd=0.15\paperwidth,ht=2ex,dp=0.5ex,rightskip=0.5em,right]{footline}%
|
||||
\includegraphics[height=1.5ex]{FHGR_Logo_small}%
|
||||
\end{beamercolorbox}%
|
||||
}%
|
||||
\vskip0pt%
|
||||
}
|
||||
|
||||
% ============================================
|
||||
% DOCUMENT
|
||||
% ============================================
|
||||
\begin{document}
|
||||
|
||||
% ============================================
|
||||
% TITLE SLIDE
|
||||
% ============================================
|
||||
{
|
||||
\setbeamertemplate{footline}{}
|
||||
\begin{frame}[plain]
|
||||
\vfill
|
||||
\begin{center}
|
||||
\includegraphics[width=0.3\textwidth]{FHGR_Logo_Large}\\[1cm]
|
||||
{\LARGE\bfseries\textcolor{bankblue}{AISE502: AI in Software Engineering II}}\\[0.6cm]
|
||||
{\large Lecture 4: Patterns I -- Layered, Modular Monolith, Hexagonal}\\[0.3cm]
|
||||
{\small\textcolor{codegray}{Script: Part II, Sections L / MM / HX}}\\[0.8cm]
|
||||
{\normalsize Dr.\ Florian Herzog}\\[0.2cm]
|
||||
{\small Fachhochschule Graub\"unden, Chur}\\[0.2cm]
|
||||
{\small Autumn Semester 2026}
|
||||
\end{center}
|
||||
\vfill
|
||||
\end{frame}
|
||||
}
|
||||
|
||||
% ============================================
|
||||
% AGENDA
|
||||
% ============================================
|
||||
\begin{frame}{Agenda}
|
||||
\small
|
||||
\begin{enumerate}\setlength\itemsep{1pt}
|
||||
\item How Part II works: examples first, generalisation after
|
||||
\item \textbf{L} -- Layered architecture: the simplest structure that does the whole job
|
||||
\item \textbf{MM} -- Modular monolith: hard boundaries inside one deployable
|
||||
\item \textbf{HX} -- Hexagonal architecture: dependency direction as a compiler-checked property
|
||||
\item The three side by side
|
||||
\item This week's exercise: architecture study I
|
||||
\end{enumerate}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% HOW PART II WORKS
|
||||
% ============================================
|
||||
\section{How Part II Works}
|
||||
|
||||
\begin{frame}{How Part II works -- and why in this order}
|
||||
\footnotesize
|
||||
Every pattern section follows the \textbf{same rhythm}:
|
||||
\begin{enumerate}\setlength\itemsep{1pt}
|
||||
\item what the pattern \emph{is} -- definition, topology, variants
|
||||
\item what real-world \textbf{problem} it was invented to solve, with named production systems
|
||||
\item how it behaves on the \textbf{twelve dimensions} -- rating and structural reason, side by side
|
||||
\item what it does to your \textbf{engineering day} -- build, test, CI/CD, operations, teams
|
||||
\item where you can \textbf{build it and study it} -- plus \textbf{anti-patterns} with measurable alarms, and \textbf{selection signals}
|
||||
\end{enumerate}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize The order is the point: software engineering is not mathematics. Its patterns were not derived from axioms -- they were \textbf{abstracted from systems that worked and systems that failed expensively}. Part II follows that order of discovery; the generalisation comes at the \emph{end}, once you have seen the cases.
|
||||
\end{keypoint}
|
||||
|
||||
\vspace{0.1cm}
|
||||
Every rating is \textbf{anchored}, and \textbf{every deviation is footnoted} in the script.
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% L -- LAYERED
|
||||
% ============================================
|
||||
\section{L -- Layered Architecture}
|
||||
|
||||
\begin{frame}{L -- Layered architecture / 3-tier}
|
||||
\emph{\textcolor{bankblue}{Two of you must ship a working product by December: what is the simplest structure that does the whole job?}}
|
||||
|
||||
\vspace{0.25cm}
|
||||
\begin{definitionbox}[Layered architecture (L)]
|
||||
\small A macro-structure that partitions a system into \textbf{horizontal technical layers} -- typically presentation, business logic, persistence, database -- with a directed dependency rule: each layer may use only the layer(s) beneath it. The whole system is deployed, scaled, and fails as \textbf{one unit}: exactly one \emph{architecture quantum}.
|
||||
\end{definitionbox}
|
||||
|
||||
\vspace{0.25cm}
|
||||
\small Two terms to keep in view -- they recur in \emph{every} pattern section:
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item \textbf{technically partitioned}: units cut by technical role, not by business capability
|
||||
\item \textbf{architecture quantum}: one unit of deployment, scaling, and failure
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{L -- topology}
|
||||
\begin{center}
|
||||
\resizebox{!}{0.66\textheight}{%
|
||||
\begin{tikzpicture}[
|
||||
sysbox/.style={rectangle, draw, rounded corners=4pt, minimum width=3.2cm, minimum height=1.2cm, align=center, font=\small\sffamily, line width=0.8pt},
|
||||
layer/.style={sysbox, fill=bankgreen!15, draw=bankgreen, minimum width=7.2cm, minimum height=0.95cm},
|
||||
extern/.style={sysbox, fill=gray!15, draw=gray!60!black, minimum width=7.2cm, minimum height=0.95cm},
|
||||
arr/.style={-{Stealth[length=2.5mm]}, thick, gray!60!black}
|
||||
]
|
||||
\node[layer] (pres) at (0,0) {Presentation layer};
|
||||
\node[layer, below=0.45cm of pres] (biz) {Business layer};
|
||||
\node[layer, below=0.45cm of biz] (pers) {Persistence layer};
|
||||
\node[extern, below=0.45cm of pers] (db) {Database};
|
||||
\draw[arr] (pres) -- (biz);
|
||||
\draw[arr] (biz) -- (pers);
|
||||
\draw[arr] (pers) -- (db);
|
||||
\draw[dashed, gray!60!black, rounded corners=6pt]
|
||||
([xshift=-0.5cm,yshift=0.35cm]pres.north west) rectangle ([xshift=0.5cm,yshift=-0.35cm]db.south east);
|
||||
\node[font=\footnotesize\sffamily, text=gray!60!black, below=0.15cm of db, yshift=-0.35cm, align=center]
|
||||
{one architecture quantum: one unit of deployment, scaling, and failure};
|
||||
\draw[-{Stealth[length=2.5mm]}, thick, bankred, dashed]
|
||||
([xshift=-1.3cm]pres.west) -- ([xshift=-1.3cm]db.west)
|
||||
node[midway, left, font=\footnotesize\sffamily, text=bankred, align=center] {typical\\feature\\change};
|
||||
\end{tikzpicture}%
|
||||
}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\small The dashed red arrow marks the structural weakness: a typical business-facing feature \textbf{cuts across every layer} -- the root cause of the $-$ on evolvability (D7).
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{L -- the problem it solves}
|
||||
\footnotesize
|
||||
As old as commercial computing: a business needs a tool -- capture orders, look up customers, post invoices -- and it needs it \emph{soon}. A small team, one relational database, a deadline in months. What such a project needs first is not elasticity; it is \textbf{a structure a handful of developers can hold in their heads while shipping}.
|
||||
|
||||
\vspace{0.2cm}
|
||||
Layering was the natural first answer because it \textbf{mirrors both the technology and the team}:
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item the stack already separates concerns: something renders screens, something executes rules, something persists rows -- and so do the skills in the room
|
||||
\item one added rule -- \emph{dependencies point downwards only} -- turns the habit into a pattern
|
||||
\item the reward: one build, one artefact, one ACID database, one thing to operate
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.2cm}
|
||||
De-facto standard since the 1990s: Spring MVC, .NET, Rails and Django scaffold it by default; Metabase ships its whole BI tier as a single JAR \emph{deliberately}. What it was never designed to give: independent scaling and change isolation.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{L -- capability profile (column L of the consolidated table)}
|
||||
\scriptsize
|
||||
\renewcommand{\arraystretch}{0.84}%
|
||||
\vspace{-0.1cm}
|
||||
\begin{center}
|
||||
\begin{tabular}{@{}p{2.9cm}cp{7.8cm}@{}}
|
||||
\toprule
|
||||
\textbf{Dimension} & \textbf{Rating} & \textbf{Structural reason} \\
|
||||
\midrule
|
||||
D1 Read scalability & $\circ$ & stateless replication $+$ caching scale reads; the single write path remains \\
|
||||
D2 Write scal.\ \& elasticity & $--$ & every write funnels through one database inside one quantum \\
|
||||
D3 Latency \& predictability & $+$ & in-process calls: no network hop, no tail amplification \\
|
||||
D4 Consistency \& integrity & $++$ & one ACID transaction boundary under one process \\
|
||||
D5 Availability \& isolation & $-$ & one process: blast radius $100\,\%$ by construction \\
|
||||
D6 Security \& auditability & $+$ & one audit log, one small compliance scope \\
|
||||
D7 Evolvability & $-$ & technical partitioning: a feature cuts across every layer \\
|
||||
D8 Simplicity \& TTM & $++$ & one repo, one pipeline -- lowest entry threshold in the catalogue \\
|
||||
D9 Testability \& deployability & $-$ & any change redeploys the whole artefact, full regression scope \\
|
||||
D10 Operating cost & $++$ & one cheap deployable, near-zero platform staff \\
|
||||
D11 Team scaling & $-$ & one quantum, one release train: a single-team pattern \\
|
||||
D12 AI integrability & $\circ$ & an AI call is easy to host -- but gets no boundary, queue, or measurement point \\
|
||||
\midrule
|
||||
Native shape $S(p)$ & \multicolumn{2}{l}{interactive} \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{L -- three cells with a story}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{3pt}
|
||||
\item \textbf{D1 $= \circ$, D2 $= --$: the read/write split.} The one-star scalability rating conflates two dimensions: replication $+$ caching demonstrably scale \emph{reads} (Stack Overflow, Instagram) -- the single write path remains the bottleneck.
|
||||
\item \textbf{D3 $= +$: a footnoted deviation.} In-process calls give low, \emph{predictable} latency; the source's two stars reflect throughput, which D1/D2 capture separately.
|
||||
\item \textbf{D7, D9, D11 $= -$: the negative change axis.} A feature disperses across all layers; any change redeploys everything; one release train $=$ a single-team pattern.
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{examplebox}[Stack Overflow -- a layered monolith at planetary scale]
|
||||
\footnotesize $\sim 1.3$ billion page views/month from $\sim 9$ web servers before a RAM-resident SQL Server cluster plus Redis -- $\sim 12$\,ms renders. A read-heavy, cache-friendly workload is exactly what carries D1: a counter-example to ``scale requires microservices'' \emph{and} evidence for the single-write-path limit (D2 $= --$).
|
||||
\end{examplebox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{L -- software engineering implications}
|
||||
\footnotesize
|
||||
\begin{columns}[T]
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Build and CI/CD}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item one build, one pipeline, one artefact -- CI trivially simple
|
||||
\item but release cadence is bounded by \textbf{full-regression scope}: the pipeline is cheap, its gate is expensive
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\textcolor{bankblue}{\textbf{Test}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item in-process integration tests: fast, no network doubles
|
||||
\item risk: suites coupled to technical layers -- refactoring breaks hundreds of tests that verify \emph{structure}, not behaviour
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Deployment and operations}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item whole-system releases and rollbacks; classical APM suffices, \textbf{no distributed tracing needed} -- an underrated virtue
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\textcolor{bankblue}{\textbf{Maintenance and teams}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item without enforced conformance the pattern \textbf{decays predictably} -- Lehman's second law has no structural counterweight here
|
||||
\item one team; sub-teams by layer reproduce the layers as hand-off friction (textbook Conway)
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{L -- build it and study it}
|
||||
\begin{examplebox}[Build it and study it -- layered]
|
||||
\footnotesize \textbf{Build.} Django (Python, BSD-3, very active) scaffolds the pattern out of the box: model--view--template \emph{is} an enforced persistence/logic/presentation layering. Canonical Java stack: Spring Boot MVC with Controller $\to$ Service $\to$ Repository.
|
||||
|
||||
\textbf{Study.} \texttt{healthchecks/healthchecks} ($\sim$10k stars, BSD-3, active): a production Django monolith -- four apps (\texttt{accounts}, \texttt{api}, \texttt{front}, \texttt{payments}), each cleanly layered. Runs locally on SQLite: \emph{the easiest start in this catalogue}.
|
||||
\end{examplebox}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{hinweisbox}
|
||||
\footnotesize \textbf{A habit to build now:} before adopting \emph{any} system -- check its \textbf{licence} and its \textbf{maintenance status} (last commit, open issues). The boxes in this part deliberately leave findings visible: a no-derivatives licence here, an archived flagship there. Verifying this is part of the engineering, and it takes two minutes.
|
||||
\end{hinweisbox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{L -- anti-patterns, alarms, selection signals}
|
||||
\small
|
||||
\textbf{Anti-patterns with measurable alarms:}
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item \emph{Architecture sinkhole} -- requests pass through layers that add no logic; rule of thumb: $> 80\,\%$ pass-through requests signal structure without function. \textbf{Alarm:} instrument the pass-through share; track change dispersion (D7 measure).
|
||||
\item \emph{Big ball of mud} -- unguarded decay. \textbf{Alarm:} rising cross-layer dependency violations; countermeasure: the dependency-rule-as-CI-gate machinery of the modular monolith.
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{columns}[T]
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankgreen}{\textbf{Choose when}}
|
||||
\begin{itemize}\footnotesize\setlength\itemsep{1pt}
|
||||
\item team $\leq$ roughly ten; budget and schedule tight
|
||||
\item domain not yet understood; CRUD-dominant at modest scale
|
||||
\item one ACID database satisfies consistency
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankred}{\textbf{Avoid when}}
|
||||
\begin{itemize}\footnotesize\setlength\itemsep{1pt}
|
||||
\item subdomains need independent scaling
|
||||
\item high change rate per subdomain; fault isolation required
|
||||
\item several teams must release independently
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{L -- AI lens and key concept}
|
||||
\begin{ailinse}[The layered pattern and AI components]
|
||||
\footnotesize D12 $= \circ$ -- instructive because the problem is not difficulty but \textbf{ease}: nothing stops a developer from calling an LLM synchronously from a business-layer service, \emph{and that is precisely the risk}. No structural boundary, no queue, no measurement point; token costs are invisible to classical APM; non-determinism leaks freely across layers, which encode technology, not trust. \textbf{Hosting an AI call is easy; containing one is unsupported.}
|
||||
\end{ailinse}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize The layered architecture buys the \textbf{lowest entry cost in the catalogue} ($++$ on D8, D10, an honest $++$ on D4) and pays on every axis of change and scale (D2, D5, D7, D9, D11 all negative). Not a defect -- a \emph{specific trade}: maximal day-one simplicity against minimal structural options later. Mis-chosen only when the profile weights the options it sold off.
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% MM -- MODULAR MONOLITH
|
||||
% ============================================
|
||||
\section{MM -- Modular Monolith}
|
||||
|
||||
\begin{frame}{MM -- Modular monolith}
|
||||
\emph{\textcolor{bankblue}{You want monolith economics but fear the big ball of mud: can hard boundaries live inside one deployable?}}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\small Yes -- \textbf{provided the boundaries are checked by a machine, not by good intentions.}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{definitionbox}[Modular monolith (MM)]
|
||||
\small A single deployment artefact (one process, one quantum) whose interior is partitioned \textbf{by domain} into modules with enforced boundaries: each module encapsulates one \emph{bounded context} -- including sovereignty over its own persistent data -- and inter-module communication passes exclusively through published module APIs or in-process events. \textbf{Boundary conformance is verified automatically.}
|
||||
\end{definitionbox}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\small \emph{Bounded context} (domain-driven design): a business subdomain with its own self-consistent vocabulary and model.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{MM -- topology}
|
||||
\begin{center}
|
||||
\resizebox{0.88\textwidth}{!}{%
|
||||
\begin{tikzpicture}[
|
||||
sysbox/.style={rectangle, draw, rounded corners=4pt, align=center, font=\small\sffamily, line width=0.8pt},
|
||||
module/.style={sysbox, fill=bankblue!20, draw=bankblue, minimum width=3.0cm, minimum height=1.1cm, font=\small\sffamily\bfseries},
|
||||
data/.style={sysbox, fill=gray!15, draw=gray!60!black, minimum width=3.0cm, minimum height=0.8cm, font=\footnotesize\sffamily},
|
||||
arr/.style={-{Stealth[length=2.5mm]}, thick, gray!60!black},
|
||||
darr/.style={{Stealth[length=2.5mm]}-{Stealth[length=2.5mm]}, thick, bankgreen}
|
||||
]
|
||||
\node[module] (m1) at (-4.2,0) {Portfolio\\module};
|
||||
\node[module] (m2) at (0,0) {Instrument\\module};
|
||||
\node[module] (m3) at (4.2,0) {Reporting\\module};
|
||||
\node[data, below=0.5cm of m1] (d1) {owned tables};
|
||||
\node[data, below=0.5cm of m2] (d2) {owned tables};
|
||||
\node[data, below=0.5cm of m3] (d3) {owned tables};
|
||||
\draw[arr] (m1) -- (d1);
|
||||
\draw[arr] (m2) -- (d2);
|
||||
\draw[arr] (m3) -- (d3);
|
||||
\draw[darr] (m1) -- node[above, font=\footnotesize\sffamily, text=bankgreen] {public API /} node[below, font=\footnotesize\sffamily, text=bankgreen] {in-process events} (m2);
|
||||
\draw[darr] (m2) -- node[above, font=\footnotesize\sffamily, text=bankgreen] {public API /} node[below, font=\footnotesize\sffamily, text=bankgreen] {in-process events} (m3);
|
||||
\draw[rounded corners=6pt, line width=1pt, gray!60!black]
|
||||
(-6.1,1.1) rectangle (6.1,-2.6);
|
||||
\node[font=\footnotesize\sffamily, text=gray!60!black, align=center] at (0,-3.05)
|
||||
{single deployable: one process, one architecture quantum};
|
||||
\node[font=\footnotesize\sffamily, text=bankred, align=center] at (0,1.55)
|
||||
{boundary conformance verified in CI (ArchUnit, Spring Modulith, Packwerk)};
|
||||
\end{tikzpicture}%
|
||||
}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\small The boundaries are \textbf{not a diagram convention but a CI subject} -- violations fail the build.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{MM -- the problem it solves}
|
||||
\footnotesize
|
||||
The failure mode every successful layered system eventually demonstrates: \textbf{growth without boundaries} -- features smear across the layers, and the system decays into the big ball of mud.
|
||||
|
||||
\vspace{0.1cm}
|
||||
The fashionable 2010s escape was to \emph{distribute}: let the network enforce the boundaries. But \textbf{distribution charges rent} -- platform staffing, eventual consistency, operational complexity -- even when all the organisation needed was the boundaries.
|
||||
|
||||
\vspace{0.1cm}
|
||||
Hence the precise problem: \emph{how does a team keep monolith economics -- one build, one deployable, one ACID database -- and still get hard, change-absorbing domain boundaries?}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{examplebox}[Shopify -- the canonical modular monolith]
|
||||
\footnotesize One of the largest Rails codebases ($> 2.8$M lines of Ruby); decided deliberately \emph{against} microservices. Since 2017: components with enforced boundaries, checked by the purpose-built tool \textbf{Packwerk}. Scaling: \textbf{sharding whole monolith instances into pods} -- carrying BFCM peaks of $\sim 280$M requests/minute. Both halves in one case: microservices-grade modularity (D7) at monolith-grade cost (D10) -- and the mitigation that lifts D2 from $--$ to $-$.
|
||||
\end{examplebox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{MM -- capability profile (column MM)}
|
||||
\scriptsize
|
||||
\renewcommand{\arraystretch}{0.84}%
|
||||
\vspace{-0.1cm}
|
||||
\begin{center}
|
||||
\begin{tabular}{@{}p{2.9cm}cp{7.8cm}@{}}
|
||||
\toprule
|
||||
\textbf{Dimension} & \textbf{Rating} & \textbf{Structural reason} \\
|
||||
\midrule
|
||||
D1 Read scalability & $\circ$ & same single quantum as L: replication and caching scale reads \\
|
||||
D2 Write scal.\ \& elasticity & $-$ & one database inside one quantum; pod/tenant sharding is the documented mitigation (lifts it from $--$) \\
|
||||
D3 Latency \& predictability & $+$ & in-process calls between modules: no network hop between contexts \\
|
||||
D4 Consistency \& integrity & $++$ & one process, one ACID transaction scope across all modules \\
|
||||
D5 Availability \& isolation & $-$ & single process, single blast radius; replication mitigates \\
|
||||
D6 Security \& auditability & $+$ & one audit log, one compliance scope; module boundaries as policy seams \\
|
||||
D7 Evolvability & $+$ & the domain cut absorbs a typical feature \emph{inside one module} \\
|
||||
D8 Simplicity \& TTM & $+$ & monolith-simple minus one step: boundary governance is a permanent line item \\
|
||||
D9 Testability \& deployability & $+$ & module APIs as natural test seams; module-scoped test selection \\
|
||||
D10 Operating cost & $++$ & one artefact, one process, classical monitoring \\
|
||||
D11 Team scaling & $\circ$ & roughly three to five teams can share one release train \\
|
||||
D12 AI integrability & $+$ & a hard, CI-verifiable module boundary contains the AI subsystem at monolith cost \\
|
||||
\midrule
|
||||
Native shape $S(p)$ & \multicolumn{2}{l}{interactive} \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{MM -- read the profile \emph{against} L}
|
||||
\footnotesize
|
||||
The most instructive reading isolates the effect of the \textbf{partitioning axis} at a constant quantum count:
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{center}
|
||||
\scriptsize
|
||||
\begin{tabular}{@{}lccl@{}}
|
||||
\toprule
|
||||
& \textbf{L} & \textbf{MM} & \\
|
||||
\midrule
|
||||
D4 Consistency & $++$ & $++$ & unchanged -- same single quantum \\
|
||||
D10 Operating cost & $++$ & $++$ & unchanged -- same single quantum \\
|
||||
D7 Evolvability & $-$ & $+$ & \textcolor{bankgreen}{\textbf{domain partitioning buys this}} \\
|
||||
D9 Testability & $-$ & $+$ & \textcolor{bankgreen}{\textbf{domain partitioning buys this}} \\
|
||||
D8 Simplicity & $++$ & $+$ & the price: permanent boundary governance \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\textbf{Architecture conformance becomes a CI subject} -- the declared structure is executable, a failing test rather than a slide:
|
||||
|
||||
\vspace{0.05cm}
|
||||
\begin{tcolorbox}[colback=gray!4!white, colframe=gray!55!black, boxrule=0.6pt, arc=2pt, top=2pt, bottom=2pt, left=6pt, right=6pt]
|
||||
\scriptsize\ttfamily
|
||||
rule "module boundaries hold" \{\\
|
||||
\hspace*{1em}classes in module("portfolio") may only be accessed through its published API;\\
|
||||
\hspace*{1em}no cycles between modules(); domain packages must not depend on framework packages;\\
|
||||
\hspace*{1em}no module accesses tables owned by another module;\\
|
||||
\}
|
||||
\end{tcolorbox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{MM -- software engineering implications}
|
||||
\footnotesize
|
||||
\begin{columns}[T]
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Build and CI/CD}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item still one build -- but the domain cut enables \textbf{module-scoped test selection}: a reporting change runs the reporting tests, not the world
|
||||
\item architecture verification runs on every build -- \emph{the first fitness function most teams ever write}
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\textcolor{bankblue}{\textbf{Test}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item module APIs as test seams; hermetic module tests replace whole-system fixtures
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Deployment and operations}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item identical to the monolith, identically cheap
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\textcolor{bankblue}{\textbf{Maintenance and teams}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item failure mode: \textbf{boundary erosion}; countermeasure: automated verification -- Lehman's second law never sleeps, and code review alone demonstrably does not hold the line
|
||||
\item roughly three to five teams with accepted release coordination; beyond that, the single release train binds and D11 is exhausted
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{MM -- build it and study it}
|
||||
\begin{examplebox}[Build it and study it -- modular monolith]
|
||||
\footnotesize \textbf{Build.} Spring Modulith (Java, Apache-2.0, active): module boundaries as first-class artefacts -- verification tests, recorded event publication, generated module documentation inside one Spring Boot deployable. In Python the same discipline is a linter: \texttt{import-linter} (BSD-2, active) declares layer and independence contracts and fails CI on violation -- \emph{remember it, it returns unchanged for the hexagonal pattern}.
|
||||
|
||||
\textbf{Study.} Apache Fineract ($\sim$2.3k stars, Apache-2.0, active): core banking at industrial scale -- \textbf{34 \texttt{fineract-*} Gradle modules} (\texttt{-loan}, \texttt{-accounting}, \texttt{-savings}, \dots) composed into \emph{one} deployable, plus a \texttt{custom/} extension directory. Runs via docker-compose (JVM, heavy: moderate effort). Smaller first contact: \texttt{sivaprasadreddy/spring-modular-monolith} (Apache-2.0).
|
||||
\end{examplebox}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\footnotesize
|
||||
\textbf{Anti-patterns and alarms:} \emph{boundary erosion without automated verification} (alarms: declared-boundary violations $> 0$ in CI; rising share of features touching $> 2$ modules); \emph{shared database tables across module boundaries} (alarms: foreign keys crossing module schemas; migrations that only pass when several modules deploy together).
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{MM -- selection signals, AI lens, key concept}
|
||||
\footnotesize
|
||||
\textbf{Choose when:} domain known or explorable; organisation $<$ roughly fifty developers; time-to-market \emph{and} long-term evolvability both matter (MonolithFirst). \quad \textbf{Avoid when:} modules have fundamentally different scaling or compliance profiles, or independent deployment is business-critical.
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{ailinse}[The modular monolith as an AI host]
|
||||
\footnotesize D12 $= +$: hosts the deterministic majority of an AI-bearing system at monolith cost, and gives the AI subsystem what L cannot: a \textbf{hard, CI-verifiable module boundary}. Your project's determinism boundary -- \emph{no domain module talks to the LLM gateway except through its declared port} -- is exactly one more rule in the boundary fitness function.
|
||||
\end{ailinse}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize MM dominates L on almost every dimension except day-one simplicity, at the price of \textbf{continuous boundary governance}. The default starting point of modern systems: \emph{domain partitioning now, distribution only when a measured requirement demands it}.
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% HX -- HEXAGONAL
|
||||
% ============================================
|
||||
\section{HX -- Hexagonal Architecture}
|
||||
|
||||
\begin{frame}{HX -- Hexagonal architecture / ports and adapters}
|
||||
\emph{\textcolor{bankblue}{How do you make the domain logic testable in milliseconds when the database, the broker, and an LLM provider all sit at the edges?}}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\small By making ``at the edges'' \textbf{a property the compiler can check}.
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{definitionbox}[Hexagonal architecture / ports and adapters (HX)]
|
||||
\footnotesize A pattern of \textbf{dependency organisation}: the application core interacts with the outside exclusively through technology-neutral interfaces (\emph{ports}) that \emph{the core itself defines}; technology-specific \emph{adapters} plug into them. \textbf{All source-code dependencies point inwards} -- adapters depend on ports, never the reverse.
|
||||
\end{definitionbox}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{hinweisbox}
|
||||
\footnotesize \textbf{Not a distribution style.} Orthogonal to the monolith/microservices axis; \emph{composes} with the other six. Its column is a \textbf{delta}: $\diamond$ inherits the host; its own five cells are what the cut \emph{adds}.
|
||||
\end{hinweisbox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{HX -- topology}
|
||||
\begin{center}
|
||||
\resizebox{0.8\textwidth}{!}{%
|
||||
\begin{tikzpicture}[
|
||||
sysbox/.style={rectangle, draw, rounded corners=4pt, align=center, font=\small\sffamily, line width=0.8pt},
|
||||
drivead/.style={sysbox, fill=bankgreen!15, draw=bankgreen, minimum width=2.6cm, minimum height=0.9cm},
|
||||
drivenad/.style={sysbox, fill=gray!15, draw=gray!60!black, minimum width=2.6cm, minimum height=0.9cm},
|
||||
aiad/.style={sysbox, fill=violet!15, draw=aiviolet, minimum width=2.6cm, minimum height=0.9cm},
|
||||
port/.style={rectangle, draw=bankblue, fill=white, minimum size=0.32cm, inner sep=0pt, line width=0.8pt},
|
||||
arr/.style={-{Stealth[length=2.5mm]}, thick, gray!60!black}
|
||||
]
|
||||
\draw[line width=1pt, draw=bankblue, fill=bankblue!15]
|
||||
(30:2.3) -- (90:2.3) -- (150:2.3) -- (210:2.3) -- (270:2.3) -- (330:2.3) -- cycle;
|
||||
\node[font=\small\sffamily\bfseries, text=bankblue, align=center] at (0,0)
|
||||
{Domain core\\ \footnotesize (knows nothing of\\ \footnotesize the outside world)};
|
||||
\node[port] (p1) at (150:2.3) {};
|
||||
\node[port] (p2) at (210:2.3) {};
|
||||
\node[port] (p3) at (30:2.3) {};
|
||||
\node[port] (p4) at (330:2.3) {};
|
||||
\node[font=\scriptsize\sffamily, text=bankblue, above left=0.05cm of p1] {driving ports};
|
||||
\node[font=\scriptsize\sffamily, text=bankblue, above right=0.05cm of p3] {driven ports};
|
||||
\node[drivead] (rest) at (-5.4,1.4) {REST API\\adapter};
|
||||
\node[drivead] (test) at (-5.4,-1.4) {Test harness\\(fake driver)};
|
||||
\draw[arr] (rest) -- (p1);
|
||||
\draw[arr] (test) -- (p2);
|
||||
\node[drivenad] (db) at (5.4,1.8) {Database\\adapter};
|
||||
\node[drivenad] (mq) at (5.4,0) {Message-broker\\adapter};
|
||||
\node[aiad] (llm) at (5.4,-1.8) {LLM-provider\\adapter};
|
||||
\draw[arr] (p3) -- (db);
|
||||
\draw[arr] (p3) -- (mq);
|
||||
\draw[arr] (p4) -- (llm);
|
||||
\node[font=\footnotesize\sffamily, text=gray!60!black, align=center] at (0,-3.3)
|
||||
{runtime calls flow outwards; source-code dependencies point inwards:\\adapters depend on ports, the core depends on nothing outside itself};
|
||||
\end{tikzpicture}%
|
||||
}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.05cm}
|
||||
\small The \textcolor{aiviolet}{\textbf{LLM-provider adapter}} previews the pattern's role as the \emph{anti-corruption layer} for AI components.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{HX -- the problem it solves}
|
||||
\footnotesize
|
||||
\textbf{The pain that produced the pattern is testability.} Cockburn's 2005 diagnosis: business logic ends up \emph{welded} to its surroundings -- rules leak into UI event handlers on one side and into data-access code on the other, until the only way to check a discount computation is to start the whole application, click through screens, and inspect database rows. Such tests are slow, brittle, expensive -- \emph{and the logic most worth testing is precisely the logic hardest to reach}.
|
||||
|
||||
\vspace{0.2cm}
|
||||
The same weld causes a second, slower problem: \textbf{the system cannot follow its technology}. A new UI generation, a database migration, an additional channel -- each \emph{ought} to be peripheral, but while rules are smeared through UI and persistence code, every peripheral change is open-heart surgery.
|
||||
|
||||
\vspace{0.2cm}
|
||||
Cockburn's response \textbf{inverts the dependency}: the core defines technology-neutral interfaces in its own vocabulary, and every technology -- \emph{the test harness included} -- becomes an interchangeable plug. A fake replaces the database in milliseconds.
|
||||
|
||||
\vspace{0.15cm}
|
||||
\textcolor{codegray}{Standard core-isolation discipline of banking backends; house style of domain-driven design.}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{HX -- capability profile (a delta: $\diamond$ inherits the host)}
|
||||
\scriptsize
|
||||
\renewcommand{\arraystretch}{0.84}%
|
||||
\vspace{-0.1cm}
|
||||
\begin{center}
|
||||
\begin{tabular}{@{}p{2.9cm}cp{7.8cm}@{}}
|
||||
\toprule
|
||||
\textbf{Dimension} & \textbf{Rating} & \textbf{Structural reason} \\
|
||||
\midrule
|
||||
D1 Read scalability & $\diamond$ & inherited from the host pattern \\
|
||||
D2 Write scal.\ \& elasticity & $\diamond$ & inherited \\
|
||||
D3 Latency \& predictability & $\diamond$ & inherited \\
|
||||
D4 Consistency \& integrity & $\diamond$ & inherited \\
|
||||
D5 Availability \& isolation & $\diamond$ & inherited \\
|
||||
D6 Security \& auditability & $+$ & ports are natural audit and policy chokepoints \\
|
||||
D7 Evolvability & $++$ & technology migrations become \textbf{localised adapter tasks} \\
|
||||
D8 Simplicity \& TTM & $-$ & indirection that amortises only under change -- ceremony for pure CRUD \\
|
||||
D9 Testability \& deployability & $++$ & \textbf{hermetic domain tests}: fakes replace infrastructure, feedback in milliseconds \\
|
||||
D10 Operating cost & $\diamond$ & inherited \\
|
||||
D11 Team scaling & $\diamond$ & inherited \\
|
||||
D12 AI integrability & $++$ & an \textbf{imposed anti-corruption boundary} that an ML component cannot erode \\
|
||||
\midrule
|
||||
Native shape $S(p)$ & \multicolumn{2}{l}{(host's)} \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{HX -- the delta cells, measured}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item \textbf{D7 $= ++$ and D9 $= ++$ are the pattern's reason for existing} -- and both are directly measurable: the share of \emph{hermetic} tests rises sharply once domain logic sits behind ports; test feedback for that logic falls to milliseconds. Technology migrations -- database, broker, LLM provider -- become \emph{localised adapter tasks}: A1's cost-of-change criterion applied surgically at the anticipated seams.
|
||||
\item \textbf{The honest cost is D8 $= -$}: for pure CRUD pass-through with no domain logic, ports and adapters are ceremony -- waste, in lean terms.
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{examplebox}[Storage migrations behind a seam -- Discord]
|
||||
\footnotesize Discord's message store migrated \textbf{twice at trillion-row scale} -- MongoDB $\to$ Cassandra $\to$ ScyllaDB, hot paths re-implemented as Rust data services -- cutting p99 reads from 40--125\,ms to $\sim 15$\,ms. Survivable \emph{because} data access sat behind stable interfaces: \textbf{the storage technology churned, the callers did not}. The D7/D9 delta observed in production -- and a preview of why the same discipline turns an LLM-provider deprecation from a crisis into an adapter task.
|
||||
\end{examplebox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{HX -- software engineering implications}
|
||||
\small
|
||||
\begin{itemize}\setlength\itemsep{3pt}
|
||||
\item \textbf{Build and CI/CD:} the hexagon is invisible to the pipeline topology, but adds one gate: \emph{the dependency rule itself is a fitness function} -- ``the domain imports no framework, no vendor SDK'' -- enforceable with the same ArchUnit-class tooling as module boundaries
|
||||
\item \textbf{Test:} the pyramid gains a wide, fast base of hermetic domain tests; each port acquires \textbf{contract tests} that every adapter -- \emph{including every fake} -- must pass, so that fakes cannot drift from reality
|
||||
\item \textbf{Maintenance:} the payoff channel -- volatile peripheries (UIs, providers, AI services) churn in adapters while the core stays still
|
||||
\item \textbf{Teams:} neutral -- but the pattern demands \emph{design skill}: ports must be cut in domain vocabulary, which is a modelling task, not a refactoring
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{HX -- build it and study it}
|
||||
\begin{examplebox}[Build it and study it -- hexagonal]
|
||||
\footnotesize \textbf{Build.} The hexagon is a discipline, not a runtime -- its ``framework'' is a rule checker. ArchUnit (Java, Apache-2.0, active): its \texttt{onionArchitecture()} API encodes the inward-pointing arrows directly. Python: \texttt{import-linter} (BSD-2, active) enforces the same contracts between packages.
|
||||
|
||||
\textbf{Study.} \texttt{cosmicpython/code} ($\sim$2.7k stars): the example application of \emph{Architecture Patterns with Python} (Percival \& Gregory) -- the book's full text is freely readable online, the ideal companion for this module's Python-first audience. Look at \texttt{src/allocation/}: the split into \texttt{domain/}, \texttt{service\_layer/}, \texttt{adapters/}, \texttt{entrypoints/}, and the repository and unit-of-work \emph{ports} with swappable adapters. Runs via docker-compose $+$ pytest. \textbf{Licence caveat, as promised:} the repository is \textbf{CC-BY-ND} -- free to study, \emph{not} free to reuse in derived work.
|
||||
\end{examplebox}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\footnotesize \textbf{Selection signals} -- \textcolor{bankgreen}{\textbf{choose when}} long-lived domain logic meets volatile peripheries (many UIs, exchangeable providers, AI services) and testability is High; \textcolor{bankred}{\textbf{avoid when}} the component is pure CRUD pass-through -- then D8 $= -$ buys nothing, and the indirection never amortises.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{HX -- anti-pattern: hexagonal in name only}
|
||||
\small
|
||||
The folder structure says ports and adapters; the dependencies say otherwise. \textbf{Three measurable symptoms:}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{enumerate}\setlength\itemsep{3pt}
|
||||
\item \textbf{Ports leaking vendor types} -- a port signature mentions a provider SDK class. \emph{Alarm:} static rule ``no vendor or framework types in port signatures'', target zero violations.
|
||||
\item \textbf{Adapters containing business logic} -- decisions made where they cannot be hermetically tested. \emph{Alarm:} the share of hermetic tests \emph{stagnates} after the supposed hexagonal refactoring (if the cut were real, it would rise).
|
||||
\item \textbf{The anaemic domain behind perfect ports} -- all logic in application services, the core reduced to data bags. \emph{Alarm:} core modules with high afferent coupling but near-zero cyclomatic complexity (almost no decision logic inside).
|
||||
\end{enumerate}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{HX -- AI lens and key concept}
|
||||
\begin{ailinse}[The anti-corruption layer for AI components]
|
||||
\footnotesize D12 $= ++$ -- \textbf{the strongest cell in the D12 row}. ML components resist modularisation: ``changing anything changes everything'' (CACE), and they \emph{erode} abstraction boundaries unless a boundary is \textbf{imposed} on them. The port is that imposed boundary -- an \emph{anti-corruption layer} in the DDD sense. An LLM behind a port is \textbf{swappable} when the provider deprecates the model, \textbf{mockable} in every test, and \textbf{replaceable by a deterministic fake} -- so the deterministic $95\,\%$ of the system can be tested deterministically.
|
||||
\end{ailinse}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize HX is not a competitor of the other six patterns but a \textbf{discipline inside them}. Its profile is a delta: $++$ on evolvability, testability, and AI integrability, bought with $-$ on day-one simplicity. It purchases \textbf{options on change} -- and, like all options, it is worth exactly nothing where change never comes.
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% CLOSING
|
||||
% ============================================
|
||||
\section{The Three Side by Side}
|
||||
|
||||
\begin{frame}{The three side by side}
|
||||
\footnotesize
|
||||
\begin{center}
|
||||
\footnotesize
|
||||
\begin{tabular}{@{}lccc@{}}
|
||||
\toprule
|
||||
& \textbf{L} & \textbf{MM} & \textbf{HX (delta)} \\
|
||||
\midrule
|
||||
D4 Consistency & $++$ & $++$ & $\diamond$ \\
|
||||
D7 Evolvability & $-$ & $+$ & $++$ \\
|
||||
D8 Simplicity \& TTM & $++$ & $+$ & $-$ \\
|
||||
D9 Testability & $-$ & $+$ & $++$ \\
|
||||
D10 Operating cost & $++$ & $++$ & $\diamond$ \\
|
||||
D12 AI integrability & $\circ$ & $+$ & $++$ \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.25cm}
|
||||
Three readings:
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item L $\to$ MM isolates the \textbf{partitioning axis}: same quantum, same cost -- evolvability and testability bought by the \emph{domain cut}, not by distribution
|
||||
\item HX \textbf{composes}: a hexagonal modular monolith takes MM's column and lifts D7/D9/D12 towards $++$
|
||||
\item exactly this composition won the mini-match for C10 last week -- \textbf{your project architecture}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{This week's exercise: architecture study I}
|
||||
\begin{projektbox}
|
||||
\small
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item \textbf{Inspect} Apache Fineract (34 modules, one deployable) and \texttt{cosmicpython/code} (\texttt{domain/}, \texttt{service\_layer/}, \texttt{adapters/}, \texttt{entrypoints/}) -- find the boundaries, find the ports
|
||||
\item \textbf{Shortlist candidates for the platform core}: which of L / MM / MM$+$HX carries your requirements profile from A1?
|
||||
\item \textbf{Draw the C4 context and container diagrams} of your platform draft
|
||||
\end{itemize}
|
||||
\end{projektbox}
|
||||
|
||||
\vspace{0.3cm}
|
||||
\small While you study the repositories, apply the two-minute habit: \textbf{licence and maintenance status first} -- one of this week's study objects carries a no-derivatives licence, and finding that yourself is part of the exercise.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Summary}
|
||||
\small
|
||||
\begin{enumerate}\setlength\itemsep{2pt}
|
||||
\item Part II works \textbf{inductively}: problem $\to$ topology $\to$ twelve-dimension profile $\to$ engineering consequences $\to$ inspectable open source
|
||||
\item \textbf{L}: lowest entry cost in the catalogue ($++$ D4/D8/D10) -- pays on every axis of change and scale; a specific trade, not a defect
|
||||
\item \textbf{MM}: domain partitioning at constant quantum count -- D7/D9 rise from $-$ to $+$ while D4/D10 stay $++$; boundary conformance is a \textbf{CI subject}
|
||||
\item \textbf{HX}: a delta pattern -- $++$ on D7/D9/D12 for any host, at $-$ on D8; the \textbf{anti-corruption layer} for AI components
|
||||
\item Together: the \textbf{hexagonal modular monolith} -- the composition that won the C10 mini-match, and your project's architecture
|
||||
\end{enumerate}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Next week}
|
||||
\begin{columns}[T]
|
||||
\begin{column}{0.55\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Lecture 5 -- Patterns II}}
|
||||
\begin{itemize}\small
|
||||
\item \textbf{Microservices}: quanta, sagas vs.\ ACID, the operating premium
|
||||
\item \textbf{Event-driven architecture}: brokers, resilience patterns, eventual consistency
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\begin{column}{0.42\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Reading}}
|
||||
\begin{itemize}\small
|
||||
\item this week: Part II, sections L / MM / HX
|
||||
\item ahead: Part II, sections MS / EDA
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\textcolor{bankblue}{\textbf{Exercise}}
|
||||
\begin{itemize}\small
|
||||
\item architecture study I; C4 drafts
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% END
|
||||
% ============================================
|
||||
{
|
||||
\setbeamertemplate{footline}{}
|
||||
\begin{frame}[plain]
|
||||
\vfill
|
||||
\begin{center}
|
||||
\includegraphics[width=0.25\textwidth]{FHGR_Logo_Large}\\[1cm]
|
||||
{\LARGE\bfseries\textcolor{bankblue}{Thank you!}}\\[0.8cm]
|
||||
{\large Dr.\ Florian Herzog}\\[0.2cm]
|
||||
{\normalsize Fachhochschule Graub\"unden, Chur}\\[0.5cm]
|
||||
{\small\textcolor{codegray}{AISE502 -- AI in Software Engineering II}}
|
||||
\end{center}
|
||||
\vfill
|
||||
\end{frame}
|
||||
}
|
||||
|
||||
\end{document}
|
||||
BIN
Folien/original_default_theme/AISE502_Vorlesung_5_Folien.pdf
Normal file
707
Folien/original_default_theme/AISE502_Vorlesung_5_Folien.tex
Normal file
@ -0,0 +1,707 @@
|
||||
\documentclass[aspectratio=169,12pt]{beamer}
|
||||
|
||||
% ============================================
|
||||
% THEME AND APPEARANCE
|
||||
% ============================================
|
||||
\usetheme{default}
|
||||
\usecolortheme{default}
|
||||
\usefonttheme{professionalfonts}
|
||||
\setbeamertemplate{navigation symbols}{}
|
||||
\setbeamertemplate{footline}{}
|
||||
\setbeamertemplate{frametitle continuation}{}
|
||||
|
||||
% ============================================
|
||||
% PACKAGES
|
||||
% ============================================
|
||||
\usepackage[utf8]{inputenc}
|
||||
\usepackage[T1]{fontenc}
|
||||
\usepackage[british]{babel}
|
||||
\usepackage{graphicx}
|
||||
\usepackage{hyperref}
|
||||
\usepackage{xcolor}
|
||||
\usepackage{booktabs}
|
||||
\usepackage{tcolorbox}
|
||||
\usepackage{amsmath}
|
||||
\usepackage{amssymb}
|
||||
\usepackage{tikz}
|
||||
\usetikzlibrary{shapes.geometric, arrows.meta, positioning, fit, backgrounds, calc}
|
||||
|
||||
% ============================================
|
||||
% COLORS (same as script)
|
||||
% ============================================
|
||||
\definecolor{bankblue}{rgb}{0.0,0.28,0.67}
|
||||
\definecolor{bankgreen}{rgb}{0.13,0.55,0.13}
|
||||
\definecolor{bankred}{rgb}{0.7,0.13,0.13}
|
||||
\definecolor{aiviolet}{rgb}{0.42,0.19,0.58}
|
||||
\definecolor{backcolour}{rgb}{0.95,0.95,0.92}
|
||||
\definecolor{codegray}{rgb}{0.5,0.5,0.5}
|
||||
|
||||
% Beamer color setup
|
||||
\setbeamercolor{structure}{fg=bankblue}
|
||||
\setbeamercolor{frametitle}{fg=white,bg=bankblue}
|
||||
\setbeamercolor{title}{fg=white,bg=bankblue}
|
||||
\setbeamercolor{block title}{fg=white,bg=bankblue}
|
||||
\setbeamercolor{block body}{bg=blue!5!white}
|
||||
\setbeamercolor{block title alerted}{fg=white,bg=bankred}
|
||||
\setbeamercolor{block body alerted}{bg=red!5!white}
|
||||
\setbeamercolor{block title example}{fg=white,bg=bankgreen}
|
||||
\setbeamercolor{block body example}{bg=green!5!white}
|
||||
\setbeamercolor{item}{fg=bankblue}
|
||||
\setbeamercolor{subitem}{fg=bankblue!80}
|
||||
\setbeamercolor{itemize item}{fg=bankblue}
|
||||
\setbeamercolor{enumerate item}{fg=bankblue}
|
||||
|
||||
% Bullet style
|
||||
\setbeamertemplate{itemize item}{\raisebox{0.12ex}{$\blacktriangleright$}}
|
||||
\setbeamertemplate{itemize subitem}{\raisebox{0.12ex}{\small$\triangleright$}}
|
||||
\setbeamertemplate{enumerate items}[default]
|
||||
|
||||
% ============================================
|
||||
% CUSTOM TCOLORBOXES (same as script)
|
||||
% ============================================
|
||||
\newtcolorbox{keypoint}{
|
||||
colback=blue!5!white,
|
||||
colframe=bankblue,
|
||||
title=Key Concept,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{examplebox}[1][]{
|
||||
colback=green!5!white,
|
||||
colframe=bankgreen,
|
||||
title={Example: #1},
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{definitionbox}[1][]{
|
||||
colback=yellow!5!white,
|
||||
colframe=yellow!50!black,
|
||||
title={Definition: #1},
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{thinkbox}{
|
||||
colback=orange!5!white,
|
||||
colframe=orange!60!black,
|
||||
title=Discussion,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{hinweisbox}{
|
||||
colback=red!5!white,
|
||||
colframe=bankred,
|
||||
title=Important Note,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{ailinse}[1][]{
|
||||
colback=violet!5!white,
|
||||
colframe=aiviolet,
|
||||
title={AI Lens: #1},
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{projektbox}{
|
||||
colback=blue!3!white,
|
||||
colframe=bankblue!70,
|
||||
title=Project Link: Portfolio Intelligence Platform,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
% ============================================
|
||||
% FOOTER WITH LOGO
|
||||
% ============================================
|
||||
\setbeamertemplate{footline}{%
|
||||
\leavevmode%
|
||||
\hbox{%
|
||||
\begin{beamercolorbox}[wd=0.5\paperwidth,ht=2ex,dp=0.5ex,leftskip=0.5em]{footline}%
|
||||
\usebeamerfont{footline}\textcolor{codegray}{\tiny\insertframenumber{} / \inserttotalframenumber}%
|
||||
\end{beamercolorbox}%
|
||||
\begin{beamercolorbox}[wd=0.35\paperwidth,ht=2ex,dp=0.5ex,center]{footline}%
|
||||
\usebeamerfont{footline}\textcolor{codegray}{\tiny AISE502 -- AI in Software Engineering II}%
|
||||
\end{beamercolorbox}%
|
||||
\begin{beamercolorbox}[wd=0.15\paperwidth,ht=2ex,dp=0.5ex,rightskip=0.5em,right]{footline}%
|
||||
\includegraphics[height=1.5ex]{FHGR_Logo_small}%
|
||||
\end{beamercolorbox}%
|
||||
}%
|
||||
\vskip0pt%
|
||||
}
|
||||
|
||||
% ============================================
|
||||
% DOCUMENT
|
||||
% ============================================
|
||||
\begin{document}
|
||||
|
||||
% ============================================
|
||||
% TITLE SLIDE
|
||||
% ============================================
|
||||
{
|
||||
\setbeamertemplate{footline}{}
|
||||
\begin{frame}[plain]
|
||||
\vfill
|
||||
\begin{center}
|
||||
\includegraphics[width=0.3\textwidth]{FHGR_Logo_Large}\\[1cm]
|
||||
{\LARGE\bfseries\textcolor{bankblue}{AISE502: AI in Software Engineering II}}\\[0.6cm]
|
||||
{\large Lecture 5: Patterns II -- Microservices and Event-Driven Architecture}\\[0.3cm]
|
||||
{\small\textcolor{codegray}{Script: Part II, Sections MS / EDA}}\\[0.8cm]
|
||||
{\normalsize Dr.\ Florian Herzog}\\[0.2cm]
|
||||
{\small Fachhochschule Graub\"unden, Chur}\\[0.2cm]
|
||||
{\small Autumn Semester 2026}
|
||||
\end{center}
|
||||
\vfill
|
||||
\end{frame}
|
||||
}
|
||||
|
||||
% ============================================
|
||||
% AGENDA
|
||||
% ============================================
|
||||
\begin{frame}{Agenda}
|
||||
\small
|
||||
\begin{enumerate}\setlength\itemsep{1pt}
|
||||
\item Recap: one quantum, three cuts -- today: many quanta
|
||||
\item \textbf{MS} -- Microservices: what buys team independence, and what it costs
|
||||
\item Sagas vs.\ ACID: why compensation is not rollback
|
||||
\item \textbf{EDA} -- Event-driven architecture: what an intermediary gives and takes
|
||||
\item Resilience primitives for distributed edges
|
||||
\item This week's exercise: architecture study II
|
||||
\end{enumerate}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% RECAP
|
||||
% ============================================
|
||||
\section{Recap}
|
||||
|
||||
\begin{frame}{Recap: where we are in the catalogue}
|
||||
\footnotesize
|
||||
Last week -- three patterns, all \textbf{single-quantum}:
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item \textbf{L}: technical layers -- cheapest entry, pays on every change axis
|
||||
\item \textbf{MM}: the \emph{domain} cut at constant quantum count -- D7/D9 rise from $-$ to $+$
|
||||
\item \textbf{HX}: a delta discipline -- $++$ on D7/D9/D12 for any host
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\textbf{Today: the distributed half of the catalogue.} Both patterns multiply quanta, both buy their strengths with the same currency -- and both carry $--$ on D8:
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item \textbf{MS} distributes \emph{by domain}: one quantum per business capability
|
||||
\item \textbf{EDA} decouples \emph{in time}: an intermediary between producers and consumers
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize Keep last week's lens: every $++$ and $--$ below traces to a \textbf{tactic} the topology bundles or impedes -- and to the \textbf{quantum boundaries} in the figures.
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% MS -- MICROSERVICES
|
||||
% ============================================
|
||||
\section{MS -- Microservices}
|
||||
|
||||
\begin{frame}{MS -- Microservices}
|
||||
\emph{\textcolor{bankblue}{Thirty teams share one release train and step on each other with every deployment: what buys their independence -- and what does it cost?}}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\small This section derives both halves of the answer -- \textbf{and the cost half is the longer one.}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{definitionbox}[Microservices (MS)]
|
||||
\footnotesize A macro-structure of \textbf{independently deployable services}, each modelled around one business capability, each owning its persistent data exclusively (\emph{database per service}), communicating via lightweight protocols. \textbf{Every service is its own architecture quantum}: its own unit of deployment, scaling, and failure.
|
||||
\end{definitionbox}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\footnotesize In the taxonomy: \textbf{domain partitioning, many quanta} -- the highest aggregate star score of all styles, and one star on overall cost and simplicity. Newman's one-sentence definition names the two load-bearing properties: \emph{``independently deployable services modelled around a business domain.''}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{MS -- topology}
|
||||
\begin{center}
|
||||
\resizebox{0.82\textwidth}{!}{%
|
||||
\begin{tikzpicture}[
|
||||
sysbox/.style={rectangle, draw, rounded corners=4pt, align=center, font=\small\sffamily, line width=0.8pt},
|
||||
gateway/.style={sysbox, fill=bankblue!20, draw=bankblue, minimum width=4.6cm, minimum height=0.95cm, font=\small\sffamily\bfseries},
|
||||
svc/.style={sysbox, fill=bankgreen!15, draw=bankgreen, minimum width=2.9cm, minimum height=1.0cm},
|
||||
data/.style={sysbox, fill=gray!15, draw=gray!60!black, minimum width=2.9cm, minimum height=0.75cm, font=\footnotesize\sffamily},
|
||||
arr/.style={-{Stealth[length=2.5mm]}, thick, gray!60!black},
|
||||
saga/.style={-{Stealth[length=2.5mm]}, thick, bankred, dashed}
|
||||
]
|
||||
\node[gateway] (gw) at (0,2.6) {API gateway};
|
||||
\node[svc] (s1) at (-4.2,0.6) {Catalogue\\service};
|
||||
\node[svc] (s2) at (0,0.6) {Order\\service};
|
||||
\node[svc] (s3) at (4.2,0.6) {Payment\\service};
|
||||
\node[data, below=0.45cm of s1] (db1) {own database};
|
||||
\node[data, below=0.45cm of s2] (db2) {own database};
|
||||
\node[data, below=0.45cm of s3] (db3) {own database};
|
||||
\draw[arr] (gw) -- (s1);
|
||||
\draw[arr] (gw) -- (s2);
|
||||
\draw[arr] (gw) -- (s3);
|
||||
\draw[arr] (s1) -- (db1);
|
||||
\draw[arr] (s2) -- (db2);
|
||||
\draw[arr] (s3) -- (db3);
|
||||
\draw[saga] (s2) -- node[above, font=\footnotesize\sffamily, text=bankred] {saga, no ACID} (s3);
|
||||
\draw[dashed, gray!60!black, rounded corners=5pt] (-5.85,1.25) rectangle (-2.55,-1.75);
|
||||
\draw[dashed, gray!60!black, rounded corners=5pt] (-1.65,1.25) rectangle (1.65,-1.75);
|
||||
\draw[dashed, gray!60!black, rounded corners=5pt] (2.55,1.25) rectangle (5.85,-1.75);
|
||||
\node[font=\footnotesize\sffamily, text=gray!60!black, align=center] at (0,-2.3)
|
||||
{one quantum per service: own pipeline, own release, own blast radius, own database};
|
||||
\end{tikzpicture}%
|
||||
}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\small Cross-service consistency is bought with \textcolor{bankred}{\textbf{sagas instead of ACID transactions}} -- the structural reason for D4 $= --$.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{MS -- the problem it solves}
|
||||
\footnotesize
|
||||
\textbf{Organisational before technical.} By the mid-2000s, Amazon and Netflix had hundreds of teams contributing to shared deployables -- and a shared deployable means a shared \textbf{release train}: every team's change waits on every other team's; integration scope grows with the \emph{organisation}, not the change; one team's defect rolls back everyone's release. Past a certain size, \emph{the queue for the release train} -- not compute, not traffic -- binds how fast the company ships.
|
||||
|
||||
\vspace{0.1cm}
|
||||
The answer: \textbf{make the team's unit of ownership the system's unit of deployment.} Cut along business capabilities, give each service exclusive data ownership and its own pipeline -- ``you build it, you run it.''
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item strongest empirical support is organisational: in high performers, \textbf{deployment frequency scales linearly with team count} instead of collapsing under coordination (DORA)
|
||||
\item the documented \emph{upper} bound: Uber, at $\sim 2{,}200$ critical services, re-introduced a second structuring level -- $\sim 70$ domains with gateways (DOMA) -- a convergence back towards macro-modules
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{MS -- capability profile (column MS)}
|
||||
\scriptsize
|
||||
\renewcommand{\arraystretch}{0.84}%
|
||||
\vspace{-0.1cm}
|
||||
\begin{center}
|
||||
\begin{tabular}{@{}p{2.9cm}cp{7.8cm}@{}}
|
||||
\toprule
|
||||
\textbf{Dimension} & \textbf{Rating} & \textbf{Structural reason} \\
|
||||
\midrule
|
||||
D1 Read scalability & $++$ & independently replicated, cacheable read paths per service \\
|
||||
D2 Write scal.\ \& elasticity & $++$ & per-service horizontal scaling; fine-grained provisioning \\
|
||||
D3 Latency \& predictability & $-$ & network hops, serialisation, tail amplification along synchronous chains \\
|
||||
D4 Consistency \& integrity & $--$ & database-per-service: no ACID across a boundary \\
|
||||
D5 Availability \& isolation & $++$ & bulkheads: one failing service is not a failing product \\
|
||||
D6 Security \& auditability & $\circ$ & expanded attack surface, scattered audit trails vs.\ isolation \\
|
||||
D7 Evolvability & $++$ & domain partitioning: a change lands inside one deployable service \\
|
||||
D8 Simplicity \& TTM & $--$ & platform engineering before the first feature -- the premium \\
|
||||
D9 Testability \& deployability & $+$ & per-service excellent; system-level verification shifts towards production \\
|
||||
D10 Operating cost & $--$ & the premium is paid mostly as platform staffing \\
|
||||
D11 Team scaling & $++$ & independent deployability: teams release without queueing \\
|
||||
D12 AI integrability & $\circ$ & isolation helps, but synchronous chains multiply LLM latency and failure probability \\
|
||||
\midrule
|
||||
Native shape $S(p)$ & \multicolumn{2}{l}{interactive} \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{MS -- the catalogue's steepest trade, cell by cell}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{3pt}
|
||||
\item \textbf{D11 $= ++$ is the real payoff.} Deployments per developer per day scale \emph{linearly} with team count in high-performing organisations -- teams stop queueing. \textbf{This, not raw traffic, is the requirement that legitimately forces the pattern.}
|
||||
\item \textbf{D4 $= --$ is structural} (the method's negative example from week 3). A cross-service invariant (order $\to$ stock $\to$ ledger) becomes a saga -- and \emph{compensation is not rollback}: a rollback erases an intermediate state as if it never existed; a compensating action cannot, because \textbf{other services have already seen and acted on that state}. Every ``undo'' is a new business operation (cancel, restock, refund) with its own logic, tests, and failure modes. No implementation skill removes this cell -- it can only be \emph{relocated} by cutting boundaries so invariants live inside one service.
|
||||
\item \textbf{D8/D10 $= --$: the premium is staffing.} Self-managed Kubernetes TCO runs roughly $3\times$ managed offerings, dominated by personnel.
|
||||
\item \textbf{D9 $= +$ averages a genuine split}: per-service testing is excellent; \emph{system-level} verification shifts towards production -- consumer-driven contracts, canary releases, progressive delivery.
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{MS -- software engineering implications}
|
||||
\footnotesize
|
||||
Omitting these does not produce a leaner variant of the pattern -- it produces a \textbf{broken} one:
|
||||
|
||||
\vspace{0.05cm}
|
||||
\begin{columns}[T]
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Build, test, deploy}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item one pipeline and one contract-test suite \emph{per service}; \textbf{consumer-driven contracts}; canaries, \textbf{feature flags}, progressive delivery
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Operations, maintenance, teams}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item distributed tracing, per-service SLOs, \textbf{circuit breakers}, \textbf{bulkheads}
|
||||
\item \textbf{cross-cutting change multiplies by service count} -- the Segment mechanism
|
||||
\item stream-aligned teams $+$ a platform team: a \emph{precondition}
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{hinweisbox}
|
||||
\footnotesize \textbf{The distributed monolith} -- services that only build, test, and release together -- combines the costs of both worlds without the payoff. Measurable: \emph{lockstep release ratio}, cross-service change dispersion, synchronised version bumps.
|
||||
\end{hinweisbox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{MS -- Monzo and Segment: the homogeneity condition}
|
||||
\begin{examplebox}[two documented cases bracket the viability conditions]
|
||||
\footnotesize \textbf{Monzo} operates a licensed retail bank on $\sim 2{,}800$ microservices -- viable because the company enforces \textbf{extreme technological homogeneity}: one language (Go), one monorepo, shared infrastructure libraries, central migration automation that upgrades hundreds of services mechanically.
|
||||
|
||||
\vspace{0.1cm}
|
||||
\textbf{Segment} cut its pipeline into $> 140$ services -- one per analytics destination, i.e.\ along \emph{instances of configuration} rather than domain seams -- and publicly reversed course in 2018: one shared-library change required over a hundred deployments; test and operations load crushed a small team.
|
||||
\end{examplebox}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize Read jointly: viability at scale depends on \textbf{where the boundaries run} (Maxim 4) and on paying the platform premium \emph{centrally} -- not on service count.
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{MS -- build it and study it, signals, anti-patterns}
|
||||
\begin{examplebox}[Build it and study it -- microservices]
|
||||
\footnotesize \textbf{Build.} FastAPI (Python, MIT): one small HTTP service with a generated OpenAPI contract per capability; Kubernetes underneath. Java: Spring Cloud (Apache-2.0).
|
||||
|
||||
\textbf{Study.} Google's Online Boutique ($\sim$20.6k stars, Apache-2.0): twelve polyglot services under \texttt{src/}, gRPC contracts in \texttt{protos/}, one deployment per service. Runs on kind/minikube via \texttt{skaffold run}: moderate to hard -- \emph{instructively} so, because the platform effort you feel \textbf{is} D8 $= --$. Alternative: \texttt{dotnet/eShop}. (Sock Shop, cited by older literature, was archived in 2023 -- the maintenance check in action.)
|
||||
\end{examplebox}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\footnotesize
|
||||
\textbf{Anti-patterns:} \emph{entity services} (cut around nouns -- alarm: fan-out per business transaction); \emph{grains of sand} (too small to own an invariant -- alarm: service count outgrowing team count).
|
||||
|
||||
\vspace{0.1cm}
|
||||
\textcolor{bankgreen}{\textbf{Choose when}} many teams must deliver in parallel (D11 \emph{measurably} binding); subdomains have independent scaling/failure/compliance profiles; the organisation can staff a platform. \textcolor{bankred}{\textbf{Avoid when}} the premium exceeds the system's complexity; the domain is not yet stable enough to cut boundaries; or the motivation is fashion.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{MS -- AI lens and key concept}
|
||||
\begin{ailinse}[Microservices and AI: the synchronous-chain trap]
|
||||
\footnotesize D12 $= \circ$, and the ambivalence is precise. Per-service isolation is welcome for a fallible component -- an AI capability can be its own service with its own SLO. But an LLM call inside a \emph{synchronous} service chain multiplies seconds-scale latency and per-hop failure probability -- without constitutive stability patterns this is a \textbf{cascade design}. And token cost per request is a \emph{gateway} concern orthogonal to distribution: splitting a system into services does nothing to measure or cap it.
|
||||
\end{ailinse}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize Microservices are the \textbf{only pattern rated $++$ on team scaling (D11)} -- and everything else in the column is the bill: $--$ on consistency, simplicity, and cost are structural properties of many quanta, not implementation accidents. Adopt for \emph{measured organisational scale}, never for traffic alone -- traffic has cheaper answers.
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% EDA -- EVENT-DRIVEN
|
||||
% ============================================
|
||||
\section{EDA -- Event-Driven Architecture}
|
||||
|
||||
\begin{frame}{EDA -- Event-driven architecture}
|
||||
\emph{\textcolor{bankblue}{Tomorrow a new consumer needs every order event: can you attach it without touching the producer?}}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\small If the answer must be yes, an \textbf{intermediary} has to stand between the two -- and everything in this section follows from what that intermediary gives and takes.
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{definitionbox}[Event-driven architecture (EDA)]
|
||||
\footnotesize A macro-structure of \textbf{asynchronously decoupled} event producers and consumers connected through a messaging substrate. Processing is a reaction to \emph{events} -- immutable records of facts -- rather than a response to synchronous calls; producers and consumers share knowledge of \textbf{event schemas, never of each other}.
|
||||
\end{definitionbox}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\footnotesize Two topologies, and the distinction is load-bearing: the \textbf{broker topology} (decentralised event chains -- maximal scaling, no central workflow control, hard error recovery) and the \textbf{mediator topology} (central orchestrator dispatching via queues -- workflow visibility and recoverability, at the price of coupling and a potential bottleneck).
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{EDA -- the two topologies}
|
||||
\begin{center}
|
||||
\resizebox{0.86\textwidth}{!}{%
|
||||
\begin{tikzpicture}[
|
||||
sysbox/.style={rectangle, draw, rounded corners=4pt, align=center, font=\footnotesize\sffamily, line width=0.8pt},
|
||||
proc/.style={sysbox, fill=bankgreen!15, draw=bankgreen, minimum width=2.0cm, minimum height=0.8cm},
|
||||
med/.style={sysbox, fill=bankblue!20, draw=bankblue, minimum width=2.2cm, minimum height=0.9cm, font=\footnotesize\sffamily\bfseries},
|
||||
broker/.style={sysbox, fill=gray!15, draw=gray!60!black, minimum width=5.6cm, minimum height=0.7cm},
|
||||
queue/.style={sysbox, fill=gray!15, draw=gray!60!black, minimum width=1.7cm, minimum height=0.55cm, font=\scriptsize\sffamily},
|
||||
arr/.style={-{Stealth[length=2.5mm]}, thick, gray!60!black}
|
||||
]
|
||||
\node[proc] (prod) at (-4.2,2.2) {Producer};
|
||||
\node[broker] (bk) at (-4.2,0.7) {event broker (topics)};
|
||||
\node[proc] (c1) at (-5.9,-0.9) {Processor A};
|
||||
\node[proc] (c2) at (-2.5,-0.9) {Processor B};
|
||||
\node[proc] (c3) at (-4.2,-2.4) {Processor C};
|
||||
\draw[arr] (prod) -- node[right, font=\scriptsize\sffamily] {event} (bk);
|
||||
\draw[arr] (bk.south west)+(0.6,0) -- (c1.north);
|
||||
\draw[arr] (bk.south east)+(-0.6,0) -- (c2.north);
|
||||
\draw[arr] (c1.east) -- node[above, font=\scriptsize\sffamily] {derived event} (c3.west |- c1.east) -- (c3.north west);
|
||||
\draw[arr] (c2.south) -- (c3.north east);
|
||||
\node[font=\footnotesize\sffamily\bfseries, text=gray!60!black] at (-4.2,-3.3) {(a) broker topology};
|
||||
\node[proc] (src) at (4.2,2.2) {Initiating event};
|
||||
\node[med] (md) at (4.2,0.7) {Mediator};
|
||||
\node[queue] (q1) at (2.6,-0.7) {queue};
|
||||
\node[queue] (q2) at (5.8,-0.7) {queue};
|
||||
\node[proc] (w1) at (2.6,-2.0) {Processor A};
|
||||
\node[proc] (w2) at (5.8,-2.0) {Processor B};
|
||||
\draw[arr] (src) -- (md);
|
||||
\draw[arr] (md) -- (q1);
|
||||
\draw[arr] (md) -- (q2);
|
||||
\draw[arr] (q1) -- (w1);
|
||||
\draw[arr] (q2) -- (w2);
|
||||
\draw[arr, dashed] (w1.east) to[bend right=25] node[right, font=\scriptsize\sffamily] {status} (md.south);
|
||||
\node[font=\footnotesize\sffamily\bfseries, text=gray!60!black] at (4.2,-3.3) {(b) mediator topology};
|
||||
\end{tikzpicture}%
|
||||
}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.05cm}
|
||||
\footnotesize Four things commonly conflated under ``event-driven'' (Fowler): \textbf{event notification} $\cdot$ \textbf{event-carried state transfer} $\cdot$ \textbf{event sourcing} (the log \emph{is} the system of record -- LMAX: $6$M orders/s on one event-sourced JVM thread) $\cdot$ \textbf{CQRS} (separate write and read models).
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{EDA -- the problem it solves}
|
||||
\footnotesize
|
||||
\textbf{Integration at scale.} Around 2010, LinkedIn's activity data -- page views, profile edits, connections -- was wanted by an ever-growing set of consumers: search indexes, recommenders, metrics warehouses, security monitoring. Point-to-point wiring grows roughly \textbf{quadratically} with the number of systems and breaks with every schema change.
|
||||
|
||||
\vspace{0.1cm}
|
||||
LinkedIn's answer: put \textbf{one durable, partitioned, replayable log} in the middle and let every consumer read at its own pace -- the system that became \textbf{Apache Kafka}.
|
||||
|
||||
\vspace{0.1cm}
|
||||
The general form recurs wherever the consumer set is \emph{open-ended}: the producer of a fact -- an order placed, a sensor fired, a light switched on -- \textbf{cannot know today who will need that fact tomorrow}. Home Assistant faces the domestic version: thousands of device integrations, none depending on any other, coordinated by one event bus.
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{examplebox}[Kafka at LinkedIn; the Uber real-time stack]
|
||||
\footnotesize By 2019, LinkedIn's Kafka carried $> 7$ \emph{trillion} messages per day -- the existence proof for D1/D2 $= ++$. Uber composes Kafka $+$ Flink $+$ Pinot into an end-to-end event-driven stack -- the canonical EDA-plus-pipeline hybrid for the IoT class (C8).
|
||||
\end{examplebox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{EDA -- capability profile (column EDA)}
|
||||
\scriptsize
|
||||
\renewcommand{\arraystretch}{0.84}%
|
||||
\vspace{-0.1cm}
|
||||
\begin{center}
|
||||
\begin{tabular}{@{}p{2.9cm}cp{7.8cm}@{}}
|
||||
\toprule
|
||||
\textbf{Dimension} & \textbf{Rating} & \textbf{Structural reason} \\
|
||||
\midrule
|
||||
D1 Read scalability & $++$ & consumers replicate and cache independently behind the broker \\
|
||||
D2 Write scal.\ \& elasticity & $++$ & partitioned ingest with elastic, decoupled consumers \\
|
||||
D3 Latency \& predictability & $+$ & async throughput excellent; request/response through events is not the mode \\
|
||||
D4 Consistency \& integrity & $--$ & eventual consistency moves correctness into the design \\
|
||||
D5 Availability \& isolation & $++$ & a slow or dead consumer does not stall producers \\
|
||||
D6 Security \& auditability & $\circ$ & durable log supports audit; causal trails need correlation IDs \\
|
||||
D7 Evolvability & $++$ & new consumers attach without touching producers \\
|
||||
D8 Simplicity \& TTM & $--$ & eventuality and broker operations designed and staffed first \\
|
||||
D9 Testability \& deployability & $-$ & non-deterministic event flows resist end-to-end testing \\
|
||||
D10 Operating cost & $\circ$ & few quanta, no premium -- but the broker is a standing cost \\
|
||||
D11 Team scaling & $+$ & teams per processor decouple well; the broker needs an owner \\
|
||||
D12 AI integrability & $++$ & queues absorb LLM latency, limits, outages; log $=$ audit journal \\
|
||||
\midrule
|
||||
Native shape $S(p)$ & \multicolumn{2}{l}{stream / async} \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{EDA -- the same coin, two sides}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{3pt}
|
||||
\item \textbf{D7 $= ++$: the decoupling is threefold.} In \emph{topology} (producers know the event schema, never the audience), in \emph{time} (a consumer may be down, slow, or not yet written when the event is published), and in \emph{organisation} (the team attaching a fraud detector needs no meeting with the team owning the order flow).
|
||||
\item \textbf{D4 $= --$ is the same coin, seen from the other side.} Eventual consistency moves correctness \emph{out of the database and into the design}: read-your-writes anomalies, ordering across partitions, duplicate delivery are all \textbf{design obligations} -- and their testing bill is what keeps D8 at $--$ and D9 at $-$.
|
||||
\item \textbf{D3 $= +$ refines the five stars}: throughput and responsiveness are excellent, but synchronous round trips \emph{through} asynchronous flows are not the pattern's mode.
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize EDA packages ``use an intermediary'' and ``introduce concurrency'' by construction -- and \emph{impedes} ``transactions'' by the same construction. \textbf{No broker product removes the trade.}
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{EDA -- software engineering implications}
|
||||
\footnotesize
|
||||
\begin{columns}[T]
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Build and test}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item the hard artefact is the \textbf{event schema}: schema registry $+$ compatibility rules (backward/forward/full) as pipeline gates; AsyncAPI in OpenAPI's role
|
||||
\item contract tests per event type; consumer replays against recorded streams
|
||||
\item \textbf{idempotency tests}: processing an event twice must equal processing it once -- under deliberate duplicate delivery
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Operations and maintenance}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item the RED metrics of this world: \textbf{consumer lag}, \textbf{dead-letter queues}, duplicate rates
|
||||
\item debugging $=$ \textbf{correlation-ID tracing} across hops -- a core competency, not an advanced topic
|
||||
\item additive evolution is the glory (attach a consumer); \emph{changing} an established schema is the most expensive operation
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{EDA -- build it and study it, anti-patterns}
|
||||
\begin{examplebox}[Build it and study it -- event-driven]
|
||||
\footnotesize \textbf{Build.} Apache Kafka (durable, partitioned, replayable log); RabbitMQ (classic AMQP routing). Python-first layer: FastStream (Apache-2.0) -- FastAPI-style producers/consumers with the broker behind a decorator.
|
||||
|
||||
\textbf{Study.} Home Assistant (\texttt{home-assistant/core}, $\sim$89k stars, Apache-2.0): genuinely event-driven Python -- \texttt{homeassistant/core.py} defines \texttt{Event} and \texttt{EventBus} with \texttt{async\_fire}, and \emph{every} state change flows through that one bus. Runs via \texttt{pip install homeassistant}; the codebase is huge, so \textbf{read exactly that one file} -- the whole pattern is in it.
|
||||
\end{examplebox}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\footnotesize
|
||||
\textbf{Anti-patterns with alarms:} \emph{event soup} (no workflow visibility -- alarm: share of events without correlation IDs; time to reconstruct one causal trail); \emph{events as disguised RPCs} (a producer blocking for a reply event -- synchronous coupling with extra steps); \emph{missing idempotency} (at-least-once $+$ non-idempotent consumers $=$ silent corruption); \emph{event sourcing as default} (the burden of proof lies with the auditability requirement).
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Discussion}
|
||||
\begin{thinkbox}
|
||||
\small D4 $= --$, and yet Part IV will rate EDA the \emph{primary} pattern for three application classes.
|
||||
|
||||
\vspace{0.15cm}
|
||||
Which classes can afford to make correctness \emph{eventual} -- and what, precisely, is the \textbf{response measure} that would tell you your class cannot?
|
||||
|
||||
\vspace{0.15cm}
|
||||
Formulate it as a six-part quality attribute scenario before looking at Part III.
|
||||
\end{thinkbox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{EDA -- AI lens and key concept}
|
||||
\begin{ailinse}[Queues absorb what LLMs are worst at]
|
||||
\footnotesize D12 $= ++$. The three operational pathologies of LLM components -- seconds-scale latency, rate limits, provider outages -- are \textbf{exactly what a queue absorbs}; asynchronous integration is the default for non-interactive AI work. Queues also create natural \emph{batching points}: batch APIs price roughly $50\,\%$ below synchronous calls. And the durable event log \textbf{doubles as the audit journal} that logging obligations for AI systems demand -- every prompt, every response, every agent step, replayable. The one thing EDA does not give: a synchronous answer -- where the user is waiting, the latency budget must be engineered explicitly.
|
||||
\end{ailinse}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize For your project this cell is load-bearing: the \textbf{event-driven edges} around the hexagonal modular monolith carry the AI job spine -- analysis requests queue asynchronously, and the event journal is the audit trail.
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% RESILIENCE PRIMITIVES
|
||||
% ============================================
|
||||
\section{Resilience Primitives}
|
||||
|
||||
\begin{frame}{Resilience primitives for distributed edges}
|
||||
\footnotesize
|
||||
Distribution and asynchrony are bought with \textbf{explicit failure engineering} -- constitutive for MS, standard for EDA edges, and the toolkit of this week's exercise:
|
||||
|
||||
\vspace{0.05cm}
|
||||
\begin{center}
|
||||
\scriptsize
|
||||
\renewcommand{\arraystretch}{0.95}%
|
||||
\begin{tabular}{@{}p{2.6cm}p{5.6cm}p{4.6cm}@{}}
|
||||
\toprule
|
||||
\textbf{Primitive} & \textbf{What it does} & \textbf{Measured by} \\
|
||||
\midrule
|
||||
Timeout & bounds how long a caller waits -- no call may wait forever & timeout rate per dependency \\
|
||||
Retry with backoff & re-attempts transient failures with growing pauses -- safe only on \emph{idempotent} operations & retry rate; success-after-retry \\
|
||||
Circuit breaker & callers stop calling a dependency that keeps failing; probes recovery & breaker state transitions; open time \\
|
||||
Bulkhead & partitions resources so one failing component cannot drain the rest & saturation per pool \\
|
||||
Fallback / degradation & a defined degraded answer beats no answer & share of degraded responses \\
|
||||
Dead-letter queue & parks messages that repeatedly fail processing for inspection & DLQ depth and age \\
|
||||
Idempotent consumer & processing twice $=$ processing once -- makes retries safe & duplicate rate under replay \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.05cm}
|
||||
Each is a \textbf{tactic} in the week-3 sense -- and each becomes a \emph{fitness function} in your measurement contract.
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% CLOSING
|
||||
% ============================================
|
||||
\section{Closing}
|
||||
|
||||
\begin{frame}{MS and EDA side by side}
|
||||
\footnotesize
|
||||
\begin{center}
|
||||
\footnotesize
|
||||
\begin{tabular}{@{}lccl@{}}
|
||||
\toprule
|
||||
& \textbf{MS} & \textbf{EDA} & \\
|
||||
\midrule
|
||||
D4 Consistency & $--$ & $--$ & both trade ACID away -- differently: sagas vs.\ eventuality \\
|
||||
D5 Availability & $++$ & $++$ & bulkheads vs.\ temporal decoupling \\
|
||||
D7 Evolvability & $++$ & $++$ & domain cut vs.\ attach-a-consumer \\
|
||||
D8 Simplicity & $--$ & $--$ & platform premium vs.\ asynchrony bill \\
|
||||
D11 Team scaling & $++$ & $+$ & the release train vs.\ the broker owner \\
|
||||
D12 AI integrability & $\circ$ & $++$ & synchronous chains vs.\ absorbing queues \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item \textbf{MS distributes by domain}; \textbf{EDA decouples in time} -- and they compose: event-driven communication \emph{between} services is the standard hybrid
|
||||
\item both demand the resilience primitives -- and both pay D8 $= --$ \emph{before the first feature ships}
|
||||
\item for your project: neither carries the \emph{core} (the mini-match verdict stands) -- but \textbf{EDA carries the edges}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{This week's exercise: architecture study II}
|
||||
\begin{projektbox}
|
||||
\small
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item \textbf{Design the edges} of your platform: the ingestion queue for analysis requests, and \textbf{resilience against external-API failure} -- timeouts, retries with backoff, circuit breaker, fallback, DLQ on every external call
|
||||
\item \textbf{Sketch the service contracts}: which events exist, which schemas, who produces, who consumes
|
||||
\item \textbf{Matrix pre-filter}: hold your A1 requirements profile against all candidate patterns seen so far -- which survive stage 1 (shape gate) and stage 2 (vetoes)?
|
||||
\end{itemize}
|
||||
\end{projektbox}
|
||||
|
||||
\vspace{0.25cm}
|
||||
\small Next week you will run the \textbf{full three-stage match} and take the architecture decision -- the pre-filter is its preparation.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Summary}
|
||||
\footnotesize
|
||||
\begin{enumerate}\setlength\itemsep{2pt}
|
||||
\item \textbf{MS}: the only $++$ on team scaling -- adopt for \emph{measured organisational scale}, never for traffic; D4 $= --$ is structural (compensation $\neq$ rollback), D8/D10 $= --$ is staffing
|
||||
\item The \textbf{distributed monolith} is the most common failure outcome -- and it is measurable (lockstep release ratio)
|
||||
\item Monzo and Segment bracket the viability conditions: \emph{where the boundaries run} and \emph{central} platform investment -- not service count
|
||||
\item \textbf{EDA}: threefold decoupling (topology, time, organisation) -- and D4/D8/D9 are the same coin's other side; no broker removes the trade
|
||||
\item \textbf{Resilience primitives} (timeout, retry, circuit breaker, bulkhead, fallback, DLQ, idempotency) are constitutive, not hardening -- each one a fitness function
|
||||
\item For the project: MM$+$HX core unchanged; \textbf{EDA takes the edges} -- queues absorb what LLMs are worst at
|
||||
\end{enumerate}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Next week}
|
||||
\begin{columns}[T]
|
||||
\begin{column}{0.55\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Lecture 6 -- Patterns III and your class}}
|
||||
\begin{itemize}\small
|
||||
\item \textbf{Pipes-and-filters} and \textbf{Serverless}
|
||||
\item Stepping back: the quantum, partitioning beats distribution, the consolidated table
|
||||
\item Part III: \textbf{C10 in depth} $+$ the C1/C2 mirror pair
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\begin{column}{0.42\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Reading}}
|
||||
\begin{itemize}\small
|
||||
\item this week: Part II, MS / EDA
|
||||
\item ahead: Part II, PF / SL $+$ closing; Part III, C10
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\textcolor{bankblue}{\textbf{Exercise}}
|
||||
\begin{itemize}\small
|
||||
\item edges, resilience, contracts; matrix pre-filter
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% END
|
||||
% ============================================
|
||||
{
|
||||
\setbeamertemplate{footline}{}
|
||||
\begin{frame}[plain]
|
||||
\vfill
|
||||
\begin{center}
|
||||
\includegraphics[width=0.25\textwidth]{FHGR_Logo_Large}\\[1cm]
|
||||
{\LARGE\bfseries\textcolor{bankblue}{Thank you!}}\\[0.8cm]
|
||||
{\large Dr.\ Florian Herzog}\\[0.2cm]
|
||||
{\normalsize Fachhochschule Graub\"unden, Chur}\\[0.5cm]
|
||||
{\small\textcolor{codegray}{AISE502 -- AI in Software Engineering II}}
|
||||
\end{center}
|
||||
\vfill
|
||||
\end{frame}
|
||||
}
|
||||
|
||||
\end{document}
|
||||
BIN
Folien/original_default_theme/AISE502_Vorlesung_6_Folien.pdf
Normal file
765
Folien/original_default_theme/AISE502_Vorlesung_6_Folien.tex
Normal file
@ -0,0 +1,765 @@
|
||||
\documentclass[aspectratio=169,12pt]{beamer}
|
||||
|
||||
% ============================================
|
||||
% THEME AND APPEARANCE
|
||||
% ============================================
|
||||
\usetheme{default}
|
||||
\usecolortheme{default}
|
||||
\usefonttheme{professionalfonts}
|
||||
\setbeamertemplate{navigation symbols}{}
|
||||
\setbeamertemplate{footline}{}
|
||||
\setbeamertemplate{frametitle continuation}{}
|
||||
|
||||
% ============================================
|
||||
% PACKAGES
|
||||
% ============================================
|
||||
\usepackage[utf8]{inputenc}
|
||||
\usepackage[T1]{fontenc}
|
||||
\usepackage[british]{babel}
|
||||
\usepackage{graphicx}
|
||||
\usepackage{hyperref}
|
||||
\usepackage{xcolor}
|
||||
\usepackage{booktabs}
|
||||
\usepackage{tcolorbox}
|
||||
\usepackage{amsmath}
|
||||
\usepackage{amssymb}
|
||||
\usepackage{tikz}
|
||||
\usetikzlibrary{shapes.geometric, arrows.meta, positioning, fit, backgrounds, calc}
|
||||
|
||||
% ============================================
|
||||
% COLORS (same as script)
|
||||
% ============================================
|
||||
\definecolor{bankblue}{rgb}{0.0,0.28,0.67}
|
||||
\definecolor{bankgreen}{rgb}{0.13,0.55,0.13}
|
||||
\definecolor{bankred}{rgb}{0.7,0.13,0.13}
|
||||
\definecolor{aiviolet}{rgb}{0.42,0.19,0.58}
|
||||
\definecolor{backcolour}{rgb}{0.95,0.95,0.92}
|
||||
\definecolor{codegray}{rgb}{0.5,0.5,0.5}
|
||||
|
||||
% Beamer color setup
|
||||
\setbeamercolor{structure}{fg=bankblue}
|
||||
\setbeamercolor{frametitle}{fg=white,bg=bankblue}
|
||||
\setbeamercolor{title}{fg=white,bg=bankblue}
|
||||
\setbeamercolor{block title}{fg=white,bg=bankblue}
|
||||
\setbeamercolor{block body}{bg=blue!5!white}
|
||||
\setbeamercolor{block title alerted}{fg=white,bg=bankred}
|
||||
\setbeamercolor{block body alerted}{bg=red!5!white}
|
||||
\setbeamercolor{block title example}{fg=white,bg=bankgreen}
|
||||
\setbeamercolor{block body example}{bg=green!5!white}
|
||||
\setbeamercolor{item}{fg=bankblue}
|
||||
\setbeamercolor{subitem}{fg=bankblue!80}
|
||||
\setbeamercolor{itemize item}{fg=bankblue}
|
||||
\setbeamercolor{enumerate item}{fg=bankblue}
|
||||
|
||||
% Bullet style
|
||||
\setbeamertemplate{itemize item}{\raisebox{0.12ex}{$\blacktriangleright$}}
|
||||
\setbeamertemplate{itemize subitem}{\raisebox{0.12ex}{\small$\triangleright$}}
|
||||
\setbeamertemplate{enumerate items}[default]
|
||||
|
||||
% ============================================
|
||||
% CUSTOM TCOLORBOXES (same as script)
|
||||
% ============================================
|
||||
\newtcolorbox{keypoint}{
|
||||
colback=blue!5!white,
|
||||
colframe=bankblue,
|
||||
title=Key Concept,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{examplebox}[1][]{
|
||||
colback=green!5!white,
|
||||
colframe=bankgreen,
|
||||
title={Example: #1},
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{definitionbox}[1][]{
|
||||
colback=yellow!5!white,
|
||||
colframe=yellow!50!black,
|
||||
title={Definition: #1},
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{thinkbox}{
|
||||
colback=orange!5!white,
|
||||
colframe=orange!60!black,
|
||||
title=Discussion,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{hinweisbox}{
|
||||
colback=red!5!white,
|
||||
colframe=bankred,
|
||||
title=Important Note,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{ailinse}[1][]{
|
||||
colback=violet!5!white,
|
||||
colframe=aiviolet,
|
||||
title={AI Lens: #1},
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{projektbox}{
|
||||
colback=blue!3!white,
|
||||
colframe=bankblue!70,
|
||||
title=Project Link: Portfolio Intelligence Platform,
|
||||
fonttitle=\bfseries\small,
|
||||
boxrule=0.8pt,
|
||||
arc=2pt,
|
||||
top=2pt, bottom=2pt, left=4pt, right=4pt
|
||||
}
|
||||
|
||||
% ============================================
|
||||
% FOOTER WITH LOGO
|
||||
% ============================================
|
||||
\setbeamertemplate{footline}{%
|
||||
\leavevmode%
|
||||
\hbox{%
|
||||
\begin{beamercolorbox}[wd=0.5\paperwidth,ht=2ex,dp=0.5ex,leftskip=0.5em]{footline}%
|
||||
\usebeamerfont{footline}\textcolor{codegray}{\tiny\insertframenumber{} / \inserttotalframenumber}%
|
||||
\end{beamercolorbox}%
|
||||
\begin{beamercolorbox}[wd=0.35\paperwidth,ht=2ex,dp=0.5ex,center]{footline}%
|
||||
\usebeamerfont{footline}\textcolor{codegray}{\tiny AISE502 -- AI in Software Engineering II}%
|
||||
\end{beamercolorbox}%
|
||||
\begin{beamercolorbox}[wd=0.15\paperwidth,ht=2ex,dp=0.5ex,rightskip=0.5em,right]{footline}%
|
||||
\includegraphics[height=1.5ex]{FHGR_Logo_small}%
|
||||
\end{beamercolorbox}%
|
||||
}%
|
||||
\vskip0pt%
|
||||
}
|
||||
|
||||
% ============================================
|
||||
% DOCUMENT
|
||||
% ============================================
|
||||
\begin{document}
|
||||
|
||||
% ============================================
|
||||
% TITLE SLIDE
|
||||
% ============================================
|
||||
{
|
||||
\setbeamertemplate{footline}{}
|
||||
\begin{frame}[plain]
|
||||
\vfill
|
||||
\begin{center}
|
||||
\includegraphics[width=0.3\textwidth]{FHGR_Logo_Large}\\[1cm]
|
||||
{\LARGE\bfseries\textcolor{bankblue}{AISE502: AI in Software Engineering II}}\\[0.6cm]
|
||||
{\large Lecture 6: Pipelines, Serverless, the View Across -- and Your Class (C10)}\\[0.3cm]
|
||||
{\small\textcolor{codegray}{Script: Part II, Sections PF / SL $+$ closing; Part III, Section C10}}\\[0.8cm]
|
||||
{\normalsize Dr.\ Florian Herzog}\\[0.2cm]
|
||||
{\small Fachhochschule Graub\"unden, Chur}\\[0.2cm]
|
||||
{\small Autumn Semester 2026}
|
||||
\end{center}
|
||||
\vfill
|
||||
\end{frame}
|
||||
}
|
||||
|
||||
% ============================================
|
||||
% AGENDA
|
||||
% ============================================
|
||||
\begin{frame}{Agenda}
|
||||
\small
|
||||
\begin{enumerate}\setlength\itemsep{1pt}
|
||||
\item \textbf{PF} -- Pipes-and-filters: the throughput pattern
|
||||
\item \textbf{SL} -- Serverless: pay per execution, own no capacity
|
||||
\item Stepping back: the quantum, partitioning beats distribution
|
||||
\item The consolidated capability table -- all seven, side by side
|
||||
\item Outlook: agent orchestration as a composition pattern
|
||||
\item Part III opens: \textbf{C10 in depth} -- the class of your project
|
||||
\item The C1/C2 mirror pair
|
||||
\item This week's exercise: \textbf{the match}
|
||||
\end{enumerate}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% PF
|
||||
% ============================================
|
||||
\section{PF -- Pipes-and-Filters}
|
||||
|
||||
\begin{frame}{PF -- Pipes-and-filters / batch pipeline}
|
||||
\emph{\textcolor{bankblue}{The nightly risk run must process millions of rows, reproducibly, by 06:00: what structure is born for exactly that?}}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\small This one -- the \textbf{oldest pattern in the catalogue}, and the one most precisely matched to its workload shape.
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{definitionbox}[Pipes-and-filters / batch pipeline (PF)]
|
||||
\footnotesize A macro-structure of independent, composable transformation steps (\emph{filters}) connected by unidirectional data conduits (\emph{pipes}) into a chain or directed acyclic graph (DAG). Each filter is self-contained -- ideally \textbf{stateless and idempotent} -- and knows only its own data contracts, never its neighbours; the composition logic is explicit and \emph{external} to the filters.
|
||||
\end{definitionbox}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\footnotesize Historical root: the Unix pipe. Modern incarnations dominate the data world: ETL/ELT, DAG orchestration (Airflow), data-parallel engines (Spark), HPC job chains (Slurm), streaming pipelines (Flink -- the bridge to EDA), and \textbf{ML and retrieval pipelines} -- the current incarnation.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{PF -- topology and the problem it solves}
|
||||
\begin{center}
|
||||
\resizebox{0.8\textwidth}{!}{%
|
||||
\begin{tikzpicture}[
|
||||
sysbox/.style={rectangle, draw, rounded corners=4pt, align=center, font=\footnotesize\sffamily, line width=0.8pt},
|
||||
filter/.style={sysbox, fill=bankgreen!15, draw=bankgreen, minimum width=2.0cm, minimum height=0.9cm},
|
||||
extern/.style={sysbox, fill=gray!15, draw=gray!60!black, minimum width=2.0cm, minimum height=0.9cm},
|
||||
arr/.style={-{Stealth[length=2.5mm]}, thick, gray!60!black}
|
||||
]
|
||||
\node[extern] (src) at (-5.6,0) {Source\\(producer)};
|
||||
\node[filter] (f1) at (-2.9,0) {Filter 1\\(transform)};
|
||||
\node[filter] (f2a) at (0,1.1) {Filter 2a\\(transform)};
|
||||
\node[filter] (f2b) at (0,-1.1) {Filter 2b\\(transform)};
|
||||
\node[filter] (f3) at (2.9,0) {Filter 3\\(merge/test)};
|
||||
\node[extern] (sink) at (5.7,0) {Output store\\(consumer)};
|
||||
\draw[arr] (src) -- node[above, font=\scriptsize\sffamily] {pipe} (f1);
|
||||
\draw[arr] (f1) -- (f2a);
|
||||
\draw[arr] (f1) -- (f2b);
|
||||
\draw[arr] (f2a) -- (f3);
|
||||
\draw[arr] (f2b) -- (f3);
|
||||
\draw[arr] (f3) -- node[above, font=\scriptsize\sffamily] {pipe} (sink);
|
||||
\node[font=\footnotesize\sffamily, text=gray!60!black, align=center] at (0,-2.3)
|
||||
{every pipe is a versioned data contract; every filter is stateless, idempotent,\\and independently testable against golden datasets};
|
||||
\end{tikzpicture}%
|
||||
}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.05cm}
|
||||
\footnotesize \textbf{The problem is the oldest workload in commercial computing:} when the business day closes, the day's records must be collected, validated, transformed, aggregated -- reliably, repeatably, \emph{before the next day begins}. Payroll, end-of-day processing, warehouse loads, overnight risk runs: a finite body of data flows through fixed transformations, and nobody waits interactively. What matters: the run finishes \textbf{inside its window}, and the same inputs \textbf{provably produce the same outputs}.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{PF -- capability profile (column PF)}
|
||||
\scriptsize
|
||||
\renewcommand{\arraystretch}{0.8}%
|
||||
\vspace{-0.35cm}
|
||||
\begin{center}
|
||||
\begin{tabular}{@{}p{2.9cm}cp{7.8cm}@{}}
|
||||
\toprule
|
||||
\textbf{Dimension} & \textbf{Rating} & \textbf{Structural reason} \\
|
||||
\midrule
|
||||
D1 Read scalability & $\circ$ & the pipeline does not serve reads; precomputation \emph{delegates} to the output store \\
|
||||
D2 Write scal.\ \& elasticity & $+$ & data-parallel frameworks are the standard operating mode \\
|
||||
D3 Latency \& predictability & $--$ & answers arrive in makespans, not milliseconds -- by design \\
|
||||
D4 Consistency \& integrity & $+$ & immutable inputs $+$ idempotent stages: \emph{reproducibility}, ``as of last run'' \\
|
||||
D5 Availability \& isolation & $-$ & a failed stage stalls the run; recovery is re-execution \\
|
||||
D6 Security \& auditability & $+$ & versioned inputs, deterministic reruns: audit trail on demand \\
|
||||
D7 Evolvability & $+$ & filters individually replaceable behind explicit data contracts \\
|
||||
D8 Simplicity \& TTM & $++$ & explicit composition over self-contained filters -- shipping this week \\
|
||||
D9 Testability \& deployability & $+$ & golden datasets per filter; bit-level assertions \\
|
||||
D10 Operating cost & $++$ & compute in schedulable bursts, near-zero platform staff \\
|
||||
D11 Team scaling & $\circ$ & DAG/filter ownership parallelises data teams moderately \\
|
||||
D12 AI integrability & $++$ & ingestion, training, evals \emph{are} pipes-and-filters; non-determinism localised \\
|
||||
\midrule
|
||||
Native shape $S(p)$ & \multicolumn{2}{l}{scheduled batch} \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{PF -- the cells with a story}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item \textbf{D3 $= --$ is not a defect but the definition}: the pattern optimises \emph{makespan} (first filter starts $\to$ last finishes) and batch-window adherence, and delegates interactive serving to the stores it fills. The streaming incarnation escapes the cell.
|
||||
\item \textbf{D4 $= +$ is the subtlest cell in the table}: not ACID -- immutable inputs plus deterministic, \emph{idempotent} stages give \textbf{reproducibility}, a \emph{third} consistency semantics beside ACID and eventual (``as of last run''). For scientific and regulatory workloads, the one that matters.
|
||||
\item \textbf{The most deterministically testable pattern in the catalogue} -- as long as no AI filter sits inside.
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{examplebox}[a Monte-Carlo risk run -- reproducibility by construction]
|
||||
\footnotesize Immutable market-data snapshots and versioned parameters enter; embarrassingly parallel simulation stages fan out; deterministic aggregation produces versioned risk figures. Fixed seeds $+$ versioned inputs make the run \textbf{bit-level reproducible} -- not a nicety but a regulatory duty for risk models: ``the same inputs produce the same books, provably, on demand.''
|
||||
\end{examplebox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{PF -- engineering, build it and study it}
|
||||
\footnotesize
|
||||
\textbf{Engineering:} the pipeline versions \emph{three} things -- code, data, schemas; \textbf{backfills} (re-running history through changed logic) are their own deployment class with their own runbook. Test with \textbf{golden datasets} per filter. The on-call page: ``the 02:00 run missed its window'' -- standing measures: makespan trend, window adherence. Coupling risk hides in the \emph{pipes} (implicit schemas).
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{examplebox}[Build it and study it -- pipes-and-filters]
|
||||
\footnotesize \textbf{Build.} Apache Airflow (DAG-as-code; read its shipped example DAGs first). dbt Core: each filter as one SQL model. Dagster as an active alternative.
|
||||
|
||||
\textbf{Study.} \texttt{dbt-labs/jaffle\_shop\_duckdb} (Apache-2.0): every \texttt{.sql} model under \texttt{models/} is a filter, \texttt{ref()} wires the pipes, \texttt{dbt build} materialises the DAG. Runs fully locally on DuckDB: \emph{very easy}. (Status check again: the classic \texttt{jaffle\_shop} was archived in 2024; its successor ships \emph{no licence file} -- use the DuckDB variant.)
|
||||
\end{examplebox}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\textbf{Anti-patterns:} \emph{stateful filters with side effects} (alarm: non-zero \textbf{rerun-diff rate}); \emph{pipeline sprawl} (DAGs without owners or version control); \emph{implicit schema coupling} (alarm: downstream breakage per upstream schema change).
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{PF -- AI lens and key concept}
|
||||
\begin{ailinse}[Pipelines are where AI work naturally lives]
|
||||
\footnotesize D12 $= ++$. The AI-adjacent workloads are pipes-and-filters \emph{by construction}: retrieval ingestion (documents $\to$ chunking $\to$ embedding $\to$ index), model training and batch inference, and \textbf{the eval harness itself} -- a versioned pipeline from golden set to statistical verdict. One precise change when an AI filter enters a deterministic chain: \emph{that stage's} test regime switches from golden-dataset equality to \textbf{statistical acceptance thresholds} (pass rates, score distributions) -- the rest keeps its deterministic tests. \textbf{Few structures contain AI more cheaply.}
|
||||
\end{ailinse}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize PF is the most deterministically testable pattern in the catalogue and the natural home of batch, data, and ML workloads. Its $--$ latency cell is its \emph{definition}: makespan and reproducibility, with interactive serving delegated to the stores it fills.
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% SL
|
||||
% ============================================
|
||||
\section{SL -- Serverless / FaaS}
|
||||
|
||||
\begin{frame}{SL -- Serverless / Function-as-a-Service}
|
||||
\emph{\textcolor{bankblue}{Your load is zero at night and spikes at noon: why pay for idle servers at 03:00?}}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\small The serverless answer is radical -- \textbf{pay per execution, own no capacity} -- and the whole profile is the fine print of that offer.
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{definitionbox}[Serverless / FaaS (SL)]
|
||||
\footnotesize A macro-structure of \textbf{event-triggered, short-lived, stateless functions} on a managed platform that provides provisioning, elastic scaling \emph{from zero} to massive parallelism, and per-execution billing. State lives outside the functions, in managed backing services; \textbf{the function is simultaneously the unit of code, of deployment, of scaling, and of cost}.
|
||||
\end{definitionbox}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\footnotesize The scientific reference point is the Berkeley view: it predicted the dominance of simplified cloud programming \emph{while cataloguing the structural limits with unusual precision} -- cold starts, enforced statelessness, communication through storage, vendor lock-in. FaaS (your code, event-triggered) vs.\ BaaS (API-consumed third-party services).
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{SL -- topology}
|
||||
\begin{center}
|
||||
\resizebox{0.8\textwidth}{!}{%
|
||||
\begin{tikzpicture}[
|
||||
sysbox/.style={rectangle, draw, rounded corners=4pt, align=center, font=\footnotesize\sffamily, line width=0.8pt},
|
||||
evt/.style={sysbox, fill=bankgreen!15, draw=bankgreen, minimum width=2.2cm, minimum height=0.8cm},
|
||||
fn/.style={sysbox, fill=bankblue!20, draw=bankblue, minimum width=2.6cm, minimum height=0.85cm},
|
||||
mgd/.style={sysbox, fill=gray!15, draw=gray!60!black, minimum width=2.4cm, minimum height=0.8cm},
|
||||
arr/.style={-{Stealth[length=2.5mm]}, thick, gray!60!black}
|
||||
]
|
||||
\node[evt] (http) at (-5.6,1.6) {HTTP request};
|
||||
\node[evt] (q) at (-5.6,0) {queue event};
|
||||
\node[evt] (sched) at (-5.6,-1.6) {schedule};
|
||||
\draw[dashed, gray!60!black, rounded corners=6pt] (-2.6,2.6) rectangle (2.6,-2.6);
|
||||
\node[font=\footnotesize\sffamily, text=gray!60!black] at (0,2.25) {managed FaaS platform};
|
||||
\node[fn] (f1) at (0,1.2) {Function A\\ \scriptsize $0 \dots n$ instances};
|
||||
\node[fn] (f2) at (0,-0.3) {Function B\\ \scriptsize $0 \dots n$ instances};
|
||||
\node[font=\scriptsize\sffamily, text=bankred, align=center] at (0,-1.75)
|
||||
{scale-to-zero $\leftrightarrow$ burst parallelism\\per-invocation billing; cold starts};
|
||||
\node[mgd] (obj) at (5.4,1.6) {object storage};
|
||||
\node[mgd] (db) at (5.4,0) {managed database};
|
||||
\node[mgd] (api) at (5.4,-1.6) {third-party API\\(BaaS)};
|
||||
\draw[arr] (http) -- (f1.west);
|
||||
\draw[arr] (q) -- (f2.west);
|
||||
\draw[arr] (sched) -- ([yshift=-0.25cm]f2.west);
|
||||
\draw[arr] (f1.east) -- (obj.west);
|
||||
\draw[arr] (f1.east) -- (db.west);
|
||||
\draw[arr] (f2.east) -- (db.west);
|
||||
\draw[arr] (f2.east) -- (api.west);
|
||||
\end{tikzpicture}%
|
||||
}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.05cm}
|
||||
\footnotesize Functions are stateless: all state lives outside, and \textbf{inter-function communication runs through storage} -- the documented cost trap. The problem it solves: \textbf{idle capacity} -- much real work is spiky or rare (thumbnails, webhooks, reports), and provisioned machines force a bad choice between sizing for the peak and failing at it.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{SL -- capability profile (no star anchor: Berkeley/CNCF-derived)}
|
||||
\scriptsize
|
||||
\renewcommand{\arraystretch}{0.8}%
|
||||
\vspace{-0.35cm}
|
||||
\begin{center}
|
||||
\begin{tabular}{@{}p{2.9cm}cp{7.8cm}@{}}
|
||||
\toprule
|
||||
\textbf{Dimension} & \textbf{Rating} & \textbf{Structural reason} \\
|
||||
\midrule
|
||||
D1 Read scalability & $+$ & wide parallelism, tempered by concurrency limits and the DB-connection bottleneck \\
|
||||
D2 Write scal.\ \& elasticity & $++$ & scale-to-zero to mass parallelism, no capacity planning \\
|
||||
D3 Latency \& predictability & $-$ & cold starts make tail latency structurally unpredictable \\
|
||||
D4 Consistency \& integrity & $-$ & stateless functions push all state through external storage \\
|
||||
D5 Availability \& isolation & $+$ & platform-managed redundancy; small blast radius per function \\
|
||||
D6 Security \& auditability & $\circ$ & platform identity per function vs.\ a fragmented audit trail \\
|
||||
D7 Evolvability & $\circ$ & fine-grained deployability vs.\ vendor lock-in and sprawl \\
|
||||
D8 Simplicity \& TTM & $\circ$ & no server management vs.\ a large configuration surface \\
|
||||
D9 Testability \& deployability & $\circ$ & trivial unit tests vs.\ cloud wiring no laptop reproduces \\
|
||||
D10 Operating cost & $++$/$--$ & \textbf{split by load shape}: zero idle cost vs.\ billing $+$ storage round trips \\
|
||||
D11 Team scaling & $+$ & the smallest teams in the catalogue ship to production \\
|
||||
D12 AI integrability & $\circ$ & fine event glue; platform timeouts collide with minutes-long runs \\
|
||||
\midrule
|
||||
Native shape $S(p)$ & \multicolumn{2}{l}{event-triggered, short-lived} \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{SL -- the split cell, observed in production}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item \textbf{D10 $= ++/--$ is the most workload-sensitive cell in the table}: $++$ for spiky load (zero idle cost); $--$ for sustained, data-intensive load. \emph{It does not average to $\circ$ -- averaging would erase precisely the information an architect needs.}
|
||||
\item \textbf{D3 $= -$ has a mitigation with a sting}: provisioned concurrency removes cold starts -- at the price of exactly the idle cost the pattern exists to avoid.
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.05cm}
|
||||
\begin{examplebox}[Amazon Prime Video -- a measured cost inversion]
|
||||
\footnotesize The video-monitoring service: Step Functions coordinating Lambdas, S3 buffering frames between stages. A hard scaling limit at $\sim 5\,\%$ of expected load, and consolidation into one ECS process cut infrastructure cost by $> 90\,\%$. \textbf{The correct reading}: \emph{one} service with a data-intensive, tightly coupled flow -- PF pushed across expensive distributed boundaries -- not a verdict on serverless. \emph{(Widely reported as ``Amazon abandons microservices'' -- which measurement, taken before the first release, would have predicted the inversion?)}
|
||||
\end{examplebox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{SL -- engineering, build it and study it}
|
||||
\footnotesize
|
||||
\textbf{Engineering:} infrastructure-as-code becomes \emph{part of the test subject}; integration tests run against emulators or ephemeral environments. Above all: \textbf{cost monitoring becomes an engineering discipline (FinOps)} -- cost per request belongs on the same dashboards as latency.
|
||||
|
||||
\vspace{0.05cm}
|
||||
\begin{examplebox}[Build it and study it -- serverless]
|
||||
\footnotesize \textbf{Build.} Knative (Go, Apache-2.0): clean, self-hostable FaaS on Kubernetes, runs on a local kind cluster. Moto (Python, Apache-2.0) mocks AWS APIs in local tests. Deliberately \emph{off} this list: LocalStack (archived into a closed model, 2026) and Serverless Framework v4 (proprietary) -- \textbf{the licence check, twice over}.
|
||||
|
||||
\textbf{Study.} The Knative Bookstore sample: independent Knative Services wired by Brokers and Triggers in YAML -- the most involved setup of the seven boxes, but self-hostable end to end.
|
||||
\end{examplebox}
|
||||
|
||||
\vspace{0.05cm}
|
||||
\textbf{Anti-patterns:} \emph{Lambda pinball} (alarm: function hops per request); \emph{cost inversion under load growth} (alarm: cost-per-request trend vs.\ load trend, break-even utilisation as a standing fitness function); \emph{cold-start denial} (alarm: cold-start rate on p99 routes).
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{SL -- AI lens and key concept}
|
||||
\begin{ailinse}[Serverless and AI: excellent glue -- conditional runtime]
|
||||
\footnotesize D12 $= \circ$, and the split mirrors the D10 cell. Event glue around \emph{batch} AI APIs fits beautifully: a function that submits, polls, and stores an asynchronous AI job is serverless at its best. But \textbf{platform timeout ceilings collide with minutes-long LLM and solver runs} -- a hard constraint, not a tuning issue -- and per-call cost stacking across functions \emph{plus} tokens is opaque without a single gateway measurement point. \textbf{A fine chauffeur for AI jobs, and a poor place for them to live.}
|
||||
\end{ailinse}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize The serverless profile is dominated by one variable more than any other pattern's: \textbf{load shape}. Unmatched elasticity and scale-to-zero economics for spiky workloads -- inverting into the catalogue's worst cost cell under sustained, data-intensive load. The split D10 rating is the table being honest where an average would lie.
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% STEPPING BACK
|
||||
% ============================================
|
||||
\section{Stepping Back}
|
||||
|
||||
\begin{frame}{Stepping back: the architecture quantum}
|
||||
\small
|
||||
Seven times the same movement: problem $\to$ topology $\to$ profile $\to$ engineering $\to$ runnable code. What no single section could deliver is the view \emph{across} -- and it starts with the unit you met in every topology figure: \textbf{the dashed boundary}.
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{definitionbox}[Architecture quantum]
|
||||
\footnotesize An \emph{independently deployable} unit that can be deployed, scaled, and can fail independently of the rest -- the joint unit of deployment, scaling, and failure. L, MM, and PF form exactly \textbf{one} quantum; EDA one or more; MS \textbf{many}; SL many small, short-lived ones.
|
||||
\end{definitionbox}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize \textbf{Maxim 3.} One quantum $\to$ cheap, simple, consistent, rigid. Many quanta $\to$ expensive, complex, eventually consistent, elastic. \emph{The quantum count explains most of the capability table.}
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Partitioning beats distribution}
|
||||
\footnotesize
|
||||
The second axis is orthogonal: \emph{how} the units are cut. \textbf{Technical partitioning} groups by technical role (layers, filter stages); \textbf{domain partitioning} by business capability (modules, services). Change requests arrive in the \emph{domain's} vocabulary -- so a feature cuts across every technical unit, but lands \emph{inside one} domain unit. \textcolor{codegray}{(Parnas's criterion, six decades on.)}
|
||||
|
||||
\vspace{0.1cm}
|
||||
You watched the axis operate \textbf{in isolation}:
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item \textbf{L $\to$ MM}: quantum count constant, only the cut flips -- D7/D9 rise from $-$ to $+$
|
||||
\item \textbf{MM $\to$ MS}: domain cut constant, quanta multiply -- evolvability stays, the bill arrives on D8/D10
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize \textbf{Maxim 4.} The partitioning axis beats the distribution axis: \emph{domain-oriented partitioning, not the number of deployment units, is the strongest single predictor of evolvability.}
|
||||
\end{keypoint}
|
||||
|
||||
\vspace{0.05cm}
|
||||
The $2 \times 2$ logic: L, PF $=$ technical/single quantum $\cdot$ MM $=$ domain/single $\cdot$ MS $=$ domain/many $\cdot$ EDA, SL multiply quanta along technical seams $\cdot$ HX orthogonal to both.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{The evidence base -- and its honest gaps}
|
||||
\footnotesize
|
||||
The most systematic public rating: the star scheme of Richards \& Ford -- eleven characteristics, one to five stars, calibrated here via the fixed mapping ($5\star \to ++$ \dots\ $1\star \to --$). Its own headline result proves a matching problem exists: \textbf{no style dominates} -- microservices lead the aggregate yet one star on cost and simplicity; layered is the exact mirror.
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{hinweisbox}
|
||||
\footnotesize Four caveats before comparative use: (i) star ratings are structured \textbf{expert judgement}, not measurements -- transcribed from the first edition, to be reconciled against the second before print; (ii) \textbf{HX carries no star profile at all} -- correctly, as a dependency-organisation pattern; its column is a flagged delta; (iii) \textbf{SL} likewise -- its column derives from Berkeley $+$ CNCF; (iv) \textbf{MM} is a rated style only since the second edition. Compensation: \emph{triangulation} -- expert ratings $\times$ documented production cases $\times$ defined response measures -- plus the measurement contract, which converts every adopted claim into a testable one.
|
||||
\end{hinweisbox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{The consolidated capability table}
|
||||
\scriptsize
|
||||
\renewcommand{\arraystretch}{0.85}%
|
||||
\begin{center}
|
||||
\begin{tabular}{@{}p{3.6cm}ccccccc@{}}
|
||||
\toprule
|
||||
\textbf{Dimension} & \textbf{L} & \textbf{MM} & \textbf{HX} & \textbf{MS} & \textbf{EDA} & \textbf{PF} & \textbf{SL} \\
|
||||
\midrule
|
||||
D1 Read scalability & $\circ$ & $\circ$ & $\diamond$ & $++$ & $++$ & $\circ$ & $+$ \\
|
||||
D2 Write scalability \& elasticity & $--$ & $-$ & $\diamond$ & $++$ & $++$ & $+$ & $++$ \\
|
||||
D3 Latency \& predictability & $+$ & $+$ & $\diamond$ & $-$ & $+$ & $--$ & $-$ \\
|
||||
D4 Consistency \& integrity & $++$ & $++$ & $\diamond$ & $--$ & $--$ & $+$ & $-$ \\
|
||||
D5 Availability \& fault isolation & $-$ & $-$ & $\diamond$ & $++$ & $++$ & $-$ & $+$ \\
|
||||
D6 Security \& auditability & $+$ & $+$ & $+$ & $\circ$ & $\circ$ & $+$ & $\circ$ \\
|
||||
D7 Evolvability \& maintainability & $-$ & $+$ & $++$ & $++$ & $++$ & $+$ & $\circ$ \\
|
||||
D8 Simplicity \& time-to-market & $++$ & $+$ & $-$ & $--$ & $--$ & $++$ & $\circ$ \\
|
||||
D9 Testability \& deployability & $-$ & $+$ & $++$ & $+$ & $-$ & $+$ & $\circ$ \\
|
||||
D10 Operating cost efficiency & $++$ & $++$ & $\diamond$ & $--$ & $\circ$ & $++$ & $++$/$--$ \\
|
||||
D11 Team scaling (Conway) & $-$ & $\circ$ & $\diamond$ & $++$ & $+$ & $\circ$ & $+$ \\
|
||||
D12 AI integrability & $\circ$ & $+$ & $++$ & $\circ$ & $++$ & $++$ & $\circ$ \\
|
||||
\midrule
|
||||
Native shape $S(p)$ & interact. & interact. & (host's) & interact. & stream & batch & event-trig. \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.05cm}
|
||||
\footnotesize The 21 table notes (every deviation, with evidence) are in the script.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Four reading rules -- and the table's status}
|
||||
\small
|
||||
\begin{enumerate}\setlength\itemsep{2pt}
|
||||
\item \textbf{HX is a delta pattern}: $\diamond$ inherits the host; its own cells are what the cut adds
|
||||
\item \textbf{Every deviation is footnoted} -- an unexplained deviation would violate the theory's own rigour standard
|
||||
\item \textbf{One cell is split}: SL's D10 genuinely inverts with load shape -- a standing sensitivity point, not a $\circ$
|
||||
\item \textbf{The last row feeds the shape gate}: $S(p)$ vs.\ $S(a)$ in stage-1 knock-out screening
|
||||
\end{enumerate}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize \emph{Ordinal} reading only: rankings and exclusions, never weighted sums. Every cell is a \textbf{default hypothesis} -- replaced by measurement once the system exists. Two cells documented to invert with context: SL cost (Prime Video), L read scalability (Stack Overflow). \emph{The matrix predicts the default, not the exception.}
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Reading the catalogue as a whole}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{2pt}
|
||||
\item \textbf{No column dominates -- so a matching problem exists.} A2 made visible in data; two variables -- quantum count (Maxim 3) and partitioning axis (Maxim 4) -- explain most of 84 cells.
|
||||
\item \textbf{The cost curves cross.} Single quanta: low fixed cost, superlinear maintenance growth unless governance holds. Many quanta: high fixed cost (platform staffing) or load-proportional cost. The five case studies are where fit and misfit were \emph{measured in money}.
|
||||
\item \textbf{Conway is a decision filter, not a footnote.} Every column presupposes a team topology: L one team $\cdot$ MM 3--5 coordinated $\cdot$ MS stream-aligned $+$ platform. Loosely coupled architectures \emph{and teams} predict continuous delivery.
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.05cm}
|
||||
\begin{thinkbox}
|
||||
\footnotesize Stack Overflow: $\sim 1.3$bn page views/month from \emph{one} quantum. Monzo: a licensed bank on $\sim 2{,}800$. What exactly does this pair falsify about ``microservices scale better than monoliths'' -- and what does it \emph{not} falsify?
|
||||
\end{thinkbox}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Outlook: agent orchestration -- an emergent composition pattern}
|
||||
\footnotesize
|
||||
One candidate for an ``eighth pattern'', filed correctly: agent orchestration is \textbf{not a new style} -- it is a \emph{composition pattern} for non-deterministic components that \textbf{reuses this catalogue's topologies}:
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{center}
|
||||
\scriptsize
|
||||
\begin{tabular}{@{}ll@{}}
|
||||
\toprule
|
||||
\textbf{Agent construct} & \textbf{Classical topology} \\
|
||||
\midrule
|
||||
prompt chaining & pipes-and-filters \\
|
||||
routing & dispatch layer \\
|
||||
parallelisation with voting & broker-style fan-out \\
|
||||
orchestrator--workers & mediator EDA \\
|
||||
evaluator--optimizer loop & feedback control loop \\
|
||||
multi-agent systems & broker fan-out of autonomous quanta \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\vspace{0.1cm}
|
||||
Load-bearing distinction: \textbf{workflows} (predefined code paths) vs.\ \textbf{agents} (the model steers its own process). The rigour case for restraint is quantified: a multi-agent research system beat a single agent by $90.2\,\%$ -- at roughly \textbf{fifteen times} the token consumption, with token use alone explaining $80\,\%$ of the variance. The module's default rule: \emph{workflows before agents}; every escalation is an ADR with a measurement contract.
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% PART III: C10
|
||||
% ============================================
|
||||
\section{C10 -- Your Class}
|
||||
|
||||
\begin{frame}{Part III opens: C10 -- AI-native advisory platforms}
|
||||
\emph{\textcolor{bankblue}{The component your product is built around is non-deterministic, priced per call, and deprecated within months: what structure contains it?}}
|
||||
|
||||
\vspace{0.15cm}
|
||||
\small The youngest class in the catalogue, \textbf{the profile of the course project}, and the reason this course exists in its present form. The architecture must \emph{contain} the AI component: deterministic services for everything deterministic, LLM calls only where determinism cannot reach, every generated statement grounded in retrievable sources.
|
||||
|
||||
\vspace{0.15cm}
|
||||
\footnotesize \textbf{Three challenges define the class:}
|
||||
\begin{enumerate}\setlength\itemsep{1pt}
|
||||
\item \textbf{Accountability for probabilistic output} -- provenance per claim, a log per agent step: observability is \emph{domain functionality}, with EU AI Act force behind it (potentially high-risk classification)
|
||||
\item \textbf{A genuinely new cost model} -- requests rare but heavy: cost \emph{per request} (tokens, GPU), not per user; batch APIs $\sim 50\,\%$ cheaper; model cascades up to $98\,\%$ cost reduction; learned routers halve cost
|
||||
\item \textbf{Churn at the core's edge} -- models, prompts, frameworks turn over in months: the most extreme change rate in the catalogue, and the strongest argument for ports and adapters
|
||||
\end{enumerate}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{C10 -- the binding scenarios}
|
||||
\footnotesize
|
||||
\begin{itemize}\setlength\itemsep{3pt}
|
||||
\item \textbf{S1 (grounded answer).} A client asks for a recommendation; \textbf{every factual claim carries a resolvable provenance reference}, failing answers are blocked and escalated -- \textbf{detection rate $\geq 99\,\%$ at $< 2$\,s added latency}. \textcolor{codegray}{(The D6 scenario.)}
|
||||
\item \textbf{S2 (cost per request).} A session triggers a multi-step agent workflow; it completes \textbf{within a per-request token-cost budget (e.g.\ CHF~0.40 at p95) and a p95 latency budget (e.g.\ 20\,s)} -- both CI-gated fitness functions. \textcolor{codegray}{(The D10 scenario.)}
|
||||
\item \textbf{S3 (model migration).} The provider deprecates the production model; the platform migrates with \textbf{eval-harness pass rate $\geq$ threshold on the golden set before rollout, rollback available}. \textcolor{codegray}{(The D7/D9 scenario.)}
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\textbf{Knock-out reading of $K$:} an architecture in which agent steps are not loggable, tool privileges not boundable, or provenance not reconstructable is \textbf{excluded before scoring} -- C1's ACID veto logic, transposed to accountability. Prompt injection cannot be fully solved in the model $\to$ system-level defence in depth is \emph{constitutive}.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{C10 -- requirements profile (the only column with an H on D12)}
|
||||
\scriptsize
|
||||
\renewcommand{\arraystretch}{0.8}%
|
||||
\vspace{-0.35cm}
|
||||
\begin{center}
|
||||
\begin{tabular}{@{}p{3.0cm}cp{7.7cm}@{}}
|
||||
\toprule
|
||||
\textbf{Dimension} & \textbf{Weight} & \textbf{Why} \\
|
||||
\midrule
|
||||
D1 Read scalability & M & retrieval reads; user concurrency modest \\
|
||||
D2 Write scal.\ \& elasticity & L & requests rare; batch pipelines scheduled, not elastic \\
|
||||
D3 Latency & M & users accept seconds-to-minutes for advisory answers \\
|
||||
D4 Consistency \& integrity & M & hybrid: knowledge index eventual, audit path ACID \\
|
||||
D5 Availability \& isolation & M & degraded answers beat no answers \\
|
||||
D6 Security \& auditability & \textbf{H} & provenance per claim, a log per agent step -- AI Act force (S1) \\
|
||||
D7 Evolvability & \textbf{H} & models, prompts, frameworks turn over in months (S3) \\
|
||||
D8 Simplicity \& TTM & M & start simplest -- but never simpler than the audit path \\
|
||||
D9 Testability \& deployability & \textbf{H} & \textbf{evals are the operative meaning of testability} (S3) \\
|
||||
D10 Operating cost & \textbf{H} & cost per \emph{request} -- a run-cost class no classical profile contains (S2) \\
|
||||
D11 Team scaling & L & small product teams; the platform premium is unaffordable \\
|
||||
D12 AI integrability & \textbf{H} & definitional: the class exists to contain the probabilistic component \\
|
||||
\midrule
|
||||
Shape $S(a)$ & \multicolumn{2}{l}{hybrid: interactive $+$ batch/async} \\
|
||||
Constraints $K(a)$ & \multicolumn{2}{l}{EU AI Act 2024/1689 (logging, oversight; potentially high-risk); GDPR} \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{C10 -- what real systems chose, and why}
|
||||
\footnotesize
|
||||
Three documented building blocks define the reference shape:
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item \textbf{Retrieval-augmented generation}: ingestion $\to$ vector index $\to$ retrieval $\to$ context $\to$ generation with citations -- structurally a \textbf{PF pipeline plus a serving layer}
|
||||
\item \textbf{Agent orchestration}: \emph{workflows before agents} -- the restraint case is quantified ($90.2\,\%$ better at $15\times$ the tokens)
|
||||
\item \textbf{Compound AI systems}: results come from systems of retrievers, models, tools, verifiers -- \emph{the system architecture becomes the differentiator}
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.05cm}
|
||||
The capability tables explain the host choice:
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item \textbf{MM} hosts the deterministic majority in one ACID quantum \emph{and} gives the AI subsystem a hard, CI-verifiable boundary
|
||||
\item \textbf{HX} answers the two hardest Highs: the LLM as a swappable adapter behind a port (D7); the port is where the \textbf{eval harness and cost gateway dock} (D9, D10)
|
||||
\item where A2 bites: synchronous chains multiply LLM latency -- what keeps \textbf{MS at $\circ$}; the monolith's weak cells are mitigated by \textbf{asynchronous edges}
|
||||
\end{itemize}
|
||||
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{The C1/C2 mirror pair -- weights, not dimensions, define a class}
|
||||
\footnotesize
|
||||
\begin{columns}[T]
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankblue}{\textbf{C1 core banking}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item a lost or double-posted booking \emph{creates or destroys money}: D4/D5/D6/D7/D9 High
|
||||
\item verdict: \textbf{MM$+$HX core}, EDA edges, PF batch runs; MS only at the Monzo condition (D11 forced High)
|
||||
\item LMAX vs.\ Monzo: \emph{same profile, opposite structures} -- $R(a)$ defines the feasible set, $K(a)$ decides within it
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\begin{column}{0.48\textwidth}
|
||||
\textcolor{bankblue}{\textbf{C2 social/content platforms}}
|
||||
\begin{itemize}\setlength\itemsep{1pt}
|
||||
\item $\sim 50{:}1$ read/write ratio; a \emph{stale} feed is invisible, an \emph{unavailable} feed is the defect: D1/D3/D5/D7/D9/D11 High, \textbf{D4 Low}
|
||||
\item verdict: \textbf{EDA$+$MS hybrid} at organisational scale; MM secondary until that scale is \emph{measured} (Instagram: a Django monolith at 100 deployments/day)
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize C1 and C2 are \textbf{mirror images} across the consistency/availability trade: same twelve dimensions, inverted weights on D1 and D4. \emph{Weights, not dimensions, define a class.}
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{C10 -- your project as an inheritance diagram}
|
||||
\begin{projektbox}
|
||||
\footnotesize The Portfolio Intelligence Platform \emph{is} a C10 instance. \textbf{Inherited:} ingestion and eval pipelines are C6 (reproducible batch); analytics are C7 (refresh contracts, lineage); the deterministic services are C3 (ACID, boring on purpose). \textbf{New:} the cost model -- \emph{expensive per request}: a token-cost budget, enforced in CI. \textbf{Also new:} D12 $=$ H, and D9 $=$ H in its eval reading -- a versioned golden set gates every prompt change and model migration. \emph{Spend your design budget on the new elements -- the inherited disciplines are solved problems.}
|
||||
\end{projektbox}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\begin{keypoint}
|
||||
\footnotesize C10 \textbf{stress-tests} the method rather than overthrowing it: one new High dimension, one new cost semantics, one new test-artefact class -- otherwise \emph{inherited} (A6 made concrete). In one sentence: a \emph{hexagonal modular monolith} -- AI adapters at ports, an LLM gateway as the single measurement point -- plus PF for ingestion and evals, EDA for the job and audit spine.
|
||||
\end{keypoint}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% CLOSING
|
||||
% ============================================
|
||||
\section{Closing}
|
||||
|
||||
\begin{frame}{This week's exercise: the match}
|
||||
\begin{projektbox}
|
||||
\footnotesize Run the \textbf{full three-stage procedure} for your platform, against your A1 requirements profile:
|
||||
\begin{enumerate}\setlength\itemsep{1pt}
|
||||
\item \textbf{Knock-out}: constraints and the workload-shape gate -- which candidates cannot carry the core?
|
||||
\item \textbf{Veto}: hold every High weight against the capability columns -- which vetoes fire, which have \emph{documented} mitigations?
|
||||
\item \textbf{Ordinal reading}: rank the survivors on the High set; run the sensitivity check
|
||||
\end{enumerate}
|
||||
\textbf{Take the decision -- and begin the ADR} (MADR: drivers, options, consequences, confirmation).
|
||||
\end{projektbox}
|
||||
|
||||
\vspace{0.1cm}
|
||||
\small Next week's lecture shows the same procedure formally -- you will recognise every step.
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Summary}
|
||||
\footnotesize
|
||||
\begin{enumerate}\setlength\itemsep{2pt}
|
||||
\item \textbf{PF}: makespan and reproducibility -- a \emph{third} consistency semantics (``as of last run''); the most deterministically testable pattern; the natural home of ingestion, training, and evals
|
||||
\item \textbf{SL}: the profile is dominated by load shape; the split D10 cell is the table being honest -- Prime Video is note 18 observed in production, with a price tag
|
||||
\item \textbf{Maxims 3 and 4}: quantum count and partitioning axis explain most of the 84 cells
|
||||
\item The \textbf{consolidated table} supports ordinal reading only -- every cell a default hypothesis, two cells documented to invert with context
|
||||
\item \textbf{Agent orchestration} reuses this catalogue's topologies -- workflows before agents ($15\times$ token finding)
|
||||
\item \textbf{C10}: Highs on D6/D7/D9/D10/D12 -- accountability, churn, evals, cost per request, containment; inherits C6/C7/C3, adds the eval harness and the token budget
|
||||
\item \textbf{C1/C2}: mirror images across the consistency/availability axis -- weights, not dimensions, define a class
|
||||
\end{enumerate}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Next week}
|
||||
\begin{columns}[T]
|
||||
\begin{column}{0.55\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Lecture 7 -- Part IV: the match, formally}}
|
||||
\begin{itemize}\small
|
||||
\item three cases, three stages
|
||||
\item the procedure in general; reading the $7 \times 10$ matrix
|
||||
\item the measurement contract, introduced
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\begin{column}{0.42\textwidth}
|
||||
\textcolor{bankblue}{\textbf{Reading}}
|
||||
\begin{itemize}\small
|
||||
\item this week: Part II close; Part III, C10
|
||||
\item ahead: Part IV, sections 1--3
|
||||
\end{itemize}
|
||||
|
||||
\vspace{0.2cm}
|
||||
\textcolor{bankblue}{\textbf{Exercise / deliverable}}
|
||||
\begin{itemize}\small
|
||||
\item the match; decision; ADR begun
|
||||
\item \textbf{A2 $+$ design gate: next week}
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
\end{frame}
|
||||
|
||||
% ============================================
|
||||
% END
|
||||
% ============================================
|
||||
{
|
||||
\setbeamertemplate{footline}{}
|
||||
\begin{frame}[plain]
|
||||
\vfill
|
||||
\begin{center}
|
||||
\includegraphics[width=0.25\textwidth]{FHGR_Logo_Large}\\[1cm]
|
||||
{\LARGE\bfseries\textcolor{bankblue}{Thank you!}}\\[0.8cm]
|
||||
{\large Dr.\ Florian Herzog}\\[0.2cm]
|
||||
{\normalsize Fachhochschule Graub\"unden, Chur}\\[0.5cm]
|
||||
{\small\textcolor{codegray}{AISE502 -- AI in Software Engineering II}}
|
||||
\end{center}
|
||||
\vfill
|
||||
\end{frame}
|
||||
}
|
||||
|
||||
\end{document}
|
||||
BIN
Folien/pics/theme_pics/bak/graubuenden.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
Folien/pics/theme_pics/bak/graubuenden_black.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
Folien/pics/theme_pics/bak/logo_black.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
Folien/pics/theme_pics/bak/logo_small.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
Folien/pics/theme_pics/graubuenden.png
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
BIN
Folien/pics/theme_pics/graubuenden_black.png
Normal file
|
After Width: | Height: | Size: 6.9 KiB |
BIN
Folien/pics/theme_pics/logo_black.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
Folien/pics/theme_pics/logo_green.png
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
Folien/pics/theme_pics/logo_green_small.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
Folien/pics/theme_pics/logo_small.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
Folien/pics/theme_pics/logo_white.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
Folien/pics/theme_pics/logo_white_small.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
Folien/pics/theme_pics/titlefade_dark.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
Folien/pics/theme_pics/titlefade_light.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
Folien/pics/theme_pics/titlepage.png
Normal file
|
After Width: | Height: | Size: 2.7 MiB |
BIN
HP0h9jEWwAAuEhM.jpeg
Normal file
|
After Width: | Height: | Size: 571 KiB |
BIN
Modulbeschreibung_ AISE502 - AI in SE II-v12-20241208_155917.pdf
Normal file
296
Modulbeschreibung_AISE502_v2_2026.md
Normal file
@ -0,0 +1,296 @@
|
||||
# Modulbeschreibung: AISE502 – AI in SE II
|
||||
|
||||
| Feld | Wert |
|
||||
|---|---|
|
||||
| **Autor/in** | Herzog Florian |
|
||||
| **Ausgabestelle** | Institute for Data Analysis, Artificial Intelligence, Visualization, and Simulation (DAViS) |
|
||||
| **Geltungsbereich** | Departement |
|
||||
| **Klassifizierung** | Nicht klassifiziert |
|
||||
| **Version** | 2.0.0 |
|
||||
| **Ausgabedatum** | 2026 (Neufassung) |
|
||||
|
||||
---
|
||||
|
||||
## Modul
|
||||
|
||||
| Feld | Wert |
|
||||
|---|---|
|
||||
| **Name** | AI in Software Engineering II |
|
||||
| **Kürzel** | AISE502 |
|
||||
| **ECTS-Punkte** | 4 |
|
||||
| **Typ** | Pflichtmodul |
|
||||
| **Verantwortliche/r** | Herzog Florian |
|
||||
| **Semester** | 5. Semester |
|
||||
|
||||
### Leitidee
|
||||
|
||||
Das Modul "AI in Software Engineering II" stellt das **Software Engineering grosser, langlebiger
|
||||
Systeme** in den Mittelpunkt und behandelt Künstliche Intelligenz als integralen Bestandteil
|
||||
moderner Softwarearchitekturen. Aufbauend auf den Grundlagen aus "AI in Software
|
||||
Engineering I" (LLMs, Prompting, RAG, Clean Code, erste Agenten-Konzepte) verschiebt sich
|
||||
der Fokus von der *einzelnen AI-Funktion* hin zum *Entwurf vollständiger, verteilter
|
||||
Software-Systeme*, in denen AI-Komponenten zur Laufzeit mitarbeiten.
|
||||
|
||||
Der Kurs ist **architektur-zentriert** (verankert in Sommerville, *Modernes Software-Engineering*)
|
||||
und folgt der Leitfrage: *Wie entwerfe, begründe und betreibe ich die Struktur eines
|
||||
Software-Systems so, dass es seine Qualitätsattribute erfüllt und über Jahre wartbar bleibt –
|
||||
auch dann, wenn einzelne Komponenten nicht-deterministisch, fehlbar und kostenintensiv sind?*
|
||||
|
||||
Künstliche Intelligenz erscheint dabei in **zwei gleichwertigen Rollen**, die durchgängig
|
||||
miteinander verwoben werden:
|
||||
|
||||
- **AI als Werkzeug zum Bauen (Achse A):** Studierende setzen moderne agentische
|
||||
Entwicklungswerkzeuge (z.B. Claude Code, Cursor, Agent-SDKs, MCP) produktiv, aber
|
||||
kritisch-reflektiert ein, um Architektur zu entwerfen, Code zu generieren, zu refactoren
|
||||
und zu reviewen.
|
||||
- **AI als Komponente im System (Achse B):** Studierende entwerfen Architekturen, in denen
|
||||
ein oder mehrere AI-Agenten als Laufzeit-Bausteine wirken, und lernen, diese
|
||||
nicht-deterministischen Komponenten *engineering-tauglich* zu machen – also testbar,
|
||||
beobachtbar, robust, skalierbar und bezahlbar.
|
||||
|
||||
Den verbindenden roten Faden bildet die Erkenntnis, dass die ingenieurmässige Disziplin, die
|
||||
man zum **Bauen mit** AI benötigt, dieselbe ist wie jene, die man zum **Einbetten von** AI
|
||||
benötigt. Durch ein durchgehendes Gruppenprojekt – eine verteilte, AI-gestützte
|
||||
Portfolio-Analyse-Plattform – wenden die Studierenden den gesamten Architektur- und
|
||||
Engineering-Bogen praktisch an und erleben unmittelbar, wo der Umgang mit
|
||||
nicht-deterministischer AI das System-Engineering herausfordert.
|
||||
|
||||
Das Verhältnis von klassischem Software Engineering zu AI-spezifischen Techniken beträgt
|
||||
etwa **60 % zu 40 %**.
|
||||
|
||||
### Voraussetzungen
|
||||
|
||||
1. AI in Software Engineering I (AISE501)
|
||||
2. Software Technik I und II
|
||||
3. Maschinelles Lernen, Deep Learning
|
||||
4. Mathematik-Grundlagen, Informatik-Grundlagen
|
||||
|
||||
### Lernergebnisse
|
||||
|
||||
Nach erfolgreichem Abschluss dieses Moduls sind die Studierenden in der Lage:
|
||||
|
||||
1. **Software-Architektur entwerfen und begründen:**
|
||||
- Architektur als Summe schwer umkehrbarer Entscheidungen verstehen und diese
|
||||
dokumentieren (Architecture Decision Records, C4-Sichten).
|
||||
- Qualitätsattribute (Wartbarkeit, Skalierbarkeit, Zuverlässigkeit, Performance,
|
||||
Sicherheit) als Treiber von Architekturentscheidungen einsetzen und Trade-offs
|
||||
analysieren.
|
||||
- Architekturstile (modularer Monolith, Microservices, Event-Driven, Hexagonal/Ports &
|
||||
Adapters) kennen, vergleichen und situationsgerecht auswählen.
|
||||
|
||||
2. **Verteilte Systeme robust gestalten:**
|
||||
- Schnittstellen und Kontrakte zwischen Services entwerfen, versionieren und absichern.
|
||||
- Synchrone und asynchrone Kommunikationsmuster anwenden.
|
||||
- Resilienz-Patterns (Timeout, Retry, Circuit-Breaker, Bulkhead, Fallback) gegen
|
||||
unzuverlässige externe Abhängigkeiten einsetzen.
|
||||
|
||||
3. **AI als Systemkomponente integrieren:**
|
||||
- AI-Komponenten hinter stabilen Schnittstellen kapseln (Anti-Corruption-Layer) und
|
||||
deterministische von nicht-deterministischen Systemteilen sauber trennen.
|
||||
- Multi-Agenten-Systeme als Architekturentscheidung konzipieren (Orchestrierungs-
|
||||
Topologien: Chain, Tree, Graph, Multi-Agent) und implementieren.
|
||||
- Domänenwissen (Ontologie) zugleich als Architektur-Vertrag und als Schutzmechanismus
|
||||
gegen Halluzinationen einsetzen.
|
||||
|
||||
4. **Qualität nicht-deterministischer Software sichern:**
|
||||
- Teststrategien (Testpyramide, TDD, Contract-Tests) für die deterministischen
|
||||
Systemteile anwenden.
|
||||
- Eigene Evaluations-Harnesses für nicht-deterministische AI-Ausgaben aufbauen
|
||||
(LLM-as-Judge, Regression gegen Domänen-Axiome, gelabelte Referenzdaten).
|
||||
|
||||
5. **AI-gestützte Software professionell bauen (Achse A):**
|
||||
- Moderne agentische Entwicklungswerkzeuge produktiv einsetzen und deren Ausgaben
|
||||
kritisch bewerten und verantworten.
|
||||
|
||||
6. **Betreiben, skalieren und absichern:**
|
||||
- CI/CD, Deployment-Strategien und Observability (Logging, Metriken, Tracing) anwenden.
|
||||
- Token-Kosten, Latenz und Ressourcennutzung von AI-Komponenten messen und optimieren
|
||||
(Caching, Batching, Model-Routing).
|
||||
- Sicherheitsaspekte berücksichtigen, insbesondere Threat-Modeling und neue
|
||||
Bedrohungsklassen wie Prompt-Injection.
|
||||
|
||||
7. **Evolution und Wartbarkeit gewährleisten:**
|
||||
- Strategien zur Weiterentwicklung und Migration (z.B. Strangler-Fig) sowie evolutionäre
|
||||
Architektur mit Fitness Functions anwenden.
|
||||
|
||||
8. **Ethik und Verantwortung reflektieren:**
|
||||
- Gesellschaftliche und ethische Implikationen AI-gestützter Systeme im sensiblen
|
||||
Anwendungskontext (z.B. Finanzdaten) bewerten und verantwortungsbewusste Lösungen
|
||||
entwickeln.
|
||||
|
||||
### Leistungsnachweis
|
||||
|
||||
| Anteil | Komponente |
|
||||
|---|---|
|
||||
| 40 % | Praxisprojekt (verteilte AI-gestützte Plattform, Gruppenarbeit) |
|
||||
| 20 % | Präsentation und Architektur-Verteidigung des Projekts |
|
||||
| 10 % | Assignments (Lese- und Mini-Aufgaben begleitend) |
|
||||
| 30 % | Schriftliche Prüfung (Schwerpunkt: Architektur-Reasoning und Trade-off-Analyse, keine reine Faktenabfrage) |
|
||||
|
||||
### Unterrichtssprache
|
||||
|
||||
Deutsch mit englischen Unterlagen und Papern.
|
||||
|
||||
### Eingangskompetenzen
|
||||
|
||||
Sicherer Umgang mit Python, Versionsverwaltung (Git) und grundlegenden Software-Engineering-
|
||||
Prinzipien (Clean Code, SOLID). Grundverständnis von LLMs, Prompting und RAG aus AISE501.
|
||||
Grundlagen in Statistik und maschinellem Lernen.
|
||||
|
||||
---
|
||||
|
||||
## Inhalte
|
||||
|
||||
Der Kurs umfasst 14 Sitzungen. Das klassische, architektur-zentrierte Software Engineering
|
||||
bildet die Substanz (~60 %). AI wird in zwei Rollen eingewoben: als kurze **AI-Linse** an jedem
|
||||
SE-Thema (AI illustriert das jeweilige SE-Konzept) sowie in zwei **eigenen Fokus-Einheiten** für
|
||||
genuin neue Themen (Agenten-Architektur, Evaluation). Ein durchgehendes Projekt verschränkt
|
||||
beide Achsen.
|
||||
|
||||
**1. Was ist Software-Architektur?**
|
||||
- Inhalte: Architektur vs. Design vs. Implementierung; Architektur als begründete
|
||||
Entscheidungen; Architecture Decision Records (ADR); C4-Sichten; Stakeholder.
|
||||
- AI-Linse (A): Ein Agent erstellt ADR-Entwürfe – der Mensch verantwortet die Entscheidung.
|
||||
- Projekt: Domäne und Vision; Setup der Entwicklungswerkzeuge.
|
||||
|
||||
**2. Qualitätsattribute als Architektur-Treiber**
|
||||
- Inhalte: Funktionale vs. nicht-funktionale Anforderungen; Wartbarkeit, Skalierbarkeit,
|
||||
Zuverlässigkeit, Performance, Sicherheit; NFRs messbar machen (Szenarien, Fitness Functions).
|
||||
- AI-Linse (B): Nicht-Determinismus, Latenz und Kosten als neue Qualitätsattribute von
|
||||
AI-Komponenten.
|
||||
- Projekt: Qualitätsszenarien definieren.
|
||||
|
||||
**3. Strukturieren im Kleinen: Kopplung & Kohäsion**
|
||||
- Inhalte: Kopplung und Kohäsion als zentrale Metriken; Modularität; Richtung von
|
||||
Abhängigkeiten.
|
||||
- AI-Linse (B): Adapter/Facade um ein LLM als Anti-Corruption-Layer.
|
||||
- Projekt: Domänenmodell (Vertiefung des Stoffs aus AISE501).
|
||||
|
||||
**4. Design Patterns als Architektur-Vokabular**
|
||||
- Inhalte: Relevante GoF-Patterns (Strategy, Adapter, Observer, Factory, Facade) im
|
||||
Architekturkontext; Abgrenzung Prinzip vs. Struktur.
|
||||
- AI-Linse (A): Ein Agent schlägt Patterns/Refactorings vor; Studierende prüfen die
|
||||
resultierende Kopplung.
|
||||
- Projekt: Ontologie als Vertrag formalisieren.
|
||||
|
||||
**5. Architekturstile**
|
||||
- Inhalte: Modularer Monolith, Microservices, Event-Driven Architecture, Hexagonal/Ports &
|
||||
Adapters; Auswahlkriterien; Conway's Law und Team-Topologien.
|
||||
- AI-Linse (B): Welcher Stil eignet sich, wenn eine Komponente ein Agent ist?
|
||||
- Projekt: Architektur aus der Ontologie ableiten (Bounded Contexts → Services).
|
||||
|
||||
**6. Verteilte Systeme I: Schnittstellen und Kontrakte**
|
||||
- Inhalte: API-Design, Kontrakte, Versionierung; synchrone vs. asynchrone Kommunikation.
|
||||
- AI-Linse (B): Ein LLM-Aufruf als unzuverlässiger Remote-Call.
|
||||
- Projekt: Walking Skeleton – Services und ein minimaler Agent laufen.
|
||||
|
||||
**7. Verteilte Systeme II: Resilienz**
|
||||
- Inhalte: Resilienz-Patterns (Timeout, Retry, Circuit-Breaker, Bulkhead, Fallback);
|
||||
asynchrone Architektur, Queues, Backpressure.
|
||||
- AI-Linse (B): Guards und Fallbacks gegen Halluzination und API-Ausfälle.
|
||||
- Projekt: Resilienz gegen Ausfall externer Datenquellen einbauen.
|
||||
|
||||
**8. Fokus-Einheit: AI-Agenten als Architektur-Baustein**
|
||||
- Inhalte: Agent = Loop + Tools + State; Orchestrierungs-Topologien (Chain, Tree, Graph,
|
||||
Multi-Agent) als Architekturentscheidung; Tool-Use; Inter-Service-Kommunikation der Agenten.
|
||||
- Projekt: Orchestrierter Multi-Agent (2–3 Sub-Agenten über klare Kontrakte) – Pflichtteil.
|
||||
|
||||
**9. Qualität & Test I**
|
||||
- Inhalte: Teststrategie, Testpyramide, TDD, Contract-Tests; technische Schuld; Code Reviews.
|
||||
- AI-Linse (A): Ein Agent generiert Tests; Studierende bewerten Abdeckung und Qualität.
|
||||
- Projekt: Testabdeckung der deterministischen Services.
|
||||
|
||||
**10. Fokus-Einheit: Evaluation nicht-deterministischer Ausgaben**
|
||||
- Inhalte: Testen nicht-deterministischer Software; LLM-as-Judge; Regression gegen
|
||||
Domänen-Axiome und gelabelte Referenzdaten; Eval-Harness als Software-Engineering-Artefakt.
|
||||
- Projekt: Eval-Harness gegen Domänenregeln aufbauen.
|
||||
|
||||
**11. DevOps und Betrieb**
|
||||
- Inhalte: CI/CD, Build-Reproduzierbarkeit, Deployment-Strategien (Blue/Green, Canary);
|
||||
Observability (Logging, Metriken, Tracing); Grundgedanke SRE.
|
||||
- AI-Linse (B): Token-Kosten und Latenz im Monitoring; Versionierung von Prompts und Modellen.
|
||||
- Projekt: CI/CD-Pipeline und Observability.
|
||||
|
||||
**12. Skalierung und Evolution**
|
||||
- Inhalte: Caching, Lasttests, Skalierungs-Patterns; Strangler-Fig-Migration; evolutionäre
|
||||
Architektur und Fitness Functions.
|
||||
- AI-Linse (B): Model-Routing, Caching und Batching als Skalierungs-Patterns.
|
||||
- Projekt: Lasttest und Optimierung; Kür: autonome Agenten / Self-Repair-Loops.
|
||||
|
||||
**13. Sicherheit**
|
||||
- Inhalte: Threat-Modeling, Secure-by-Design, Least Privilege, Defense in Depth.
|
||||
- AI-Linse (A/B): Prompt-Injection als neue Bedrohungsklasse; Security-Review mit AI-Unterstützung.
|
||||
- Projekt: Hardening des Systems.
|
||||
|
||||
**14. Synthese, Präsentation und Architektur-Kritik**
|
||||
- Inhalte: Trade-offs verteidigen; kritische Bewertung der Architektur; Feedback.
|
||||
- Reflexion: Wo half und wo schadete die AI – im Bauen (A) und im System (B)?
|
||||
- Projekt: Präsentationen und Peer-Reviews der Abschlussprojekte.
|
||||
|
||||
---
|
||||
|
||||
## Praxisprojekt: AI-Augmented Portfolio Intelligence Platform
|
||||
|
||||
Als durchgehendes Gruppenprojekt entwickeln die Studierenden eine verteilte Analyse- und
|
||||
Advisory-Plattform für Aktienportfolios (**kein Trading, kein echtes Geld** – ausschliesslich
|
||||
Analyse und Empfehlung). Die Plattform:
|
||||
|
||||
- bezieht **strukturierte externe Daten** (Börsenkurse / Preisdaten, z.B. via Yahoo Finance) –
|
||||
mit Live-API und verpflichtendem Cache-/Snapshot-Fallback;
|
||||
- bezieht **unstrukturierte externe Daten** (Firmen-News, Web-Berichte) und wandelt sie über
|
||||
eine AI-Komponente in strukturierte Insights um;
|
||||
- berechnet **Risikomanagement-, Performance- und Portfolio-Optimierungs-Kennzahlen**
|
||||
(Formeln und Testvektoren werden vorgegeben; die Lernleistung ist das Engineering darum
|
||||
herum, nicht die Herleitung der Finanzmathematik);
|
||||
- stellt die Funktionalität **API-first** bereit, mit einem dünnen Dashboard (z.B. Streamlit)
|
||||
nur zur Demonstration.
|
||||
|
||||
**Zentrale Architekturregel:** Die AI-Agenten dürfen quantitative Werte ausschliesslich über
|
||||
die deterministischen Services beziehen und interpretieren – niemals selbst berechnen. Diese
|
||||
Trennung von deterministischen und nicht-deterministischen Systemteilen ist die prüfbare
|
||||
Manifestation von "AI engineering-tauglich machen".
|
||||
|
||||
**Beispielhafte Service-Landschaft (Bounded Contexts):** MarketData-Service, News-Ingestion,
|
||||
Risk-Service, Performance-Service, Optimization-Service, Portfolio-Service sowie ein
|
||||
orchestrierender Advisor-Agent mit spezialisierten Sub-Agenten (Research-, Risk-,
|
||||
Optimization-Agent). Eine Ontologie der Anlagedomäne (Asset-Klassen, Sektoren, Regeln) dient
|
||||
als Architektur-Vertrag und als Halluzinations-Guard.
|
||||
|
||||
**Abstufung Pflicht / Kür:**
|
||||
|
||||
- *Pflicht (bestehensrelevant):* orchestrierter Advisor-Agent mit 2–3 Sub-Agenten über klare
|
||||
Service-Kontrakte; Ontologie-Guard; Sentiment-Evaluation der News; vollständig getestete
|
||||
deterministische Services; Resilienz gegen Ausfall externer Datenquellen; Observability für
|
||||
Kosten und Latenz.
|
||||
- *Kür (für Spitzennoten):* autonomes Planning (der Agent entscheidet selbst über
|
||||
Tool-/Sub-Agent-Aufrufe), Self-Repair-Loops, Model-Routing.
|
||||
|
||||
---
|
||||
|
||||
## Lehr- und Lernmethoden
|
||||
|
||||
**Lehrtechniken:** Vorlesungen, Übungen, Gruppenarbeit, Online-Lehre, Workshops.
|
||||
|
||||
**Lernaktivitäten:** Studium von Literatur, Übungsaufgaben, Bearbeiten von Problemen und deren
|
||||
Lösungsfindung, Zusammenarbeit mit anderen Studierenden, projektbegleitendes Selbststudium.
|
||||
|
||||
**Lehrmethode:** Präsentation; Einzel-, Partner- und Gruppenarbeit; E-Learning.
|
||||
|
||||
---
|
||||
|
||||
## Struktur
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Online-, Hybrid- oder Präsenzunterricht | 42 h |
|
||||
| Selbststudium (Lektüre und Projekt) | 78 h |
|
||||
| **Total** | **120 h (4 ECTS)** |
|
||||
|
||||
## Literatur
|
||||
|
||||
- *Modernes Software-Engineering: Entwurf und Entwicklung von Softwareprodukten* – Ian
|
||||
Sommerville (Hauptanker).
|
||||
- Ergänzend: *Fundamentals of Software Architecture* (Richards & Ford), *Building
|
||||
Microservices* (Newman), *Refactoring* (Fowler) – nach Bedarf als Reader.
|
||||
- Aktuelle wissenschaftliche Artikel und Branchenforschung im Bereich AI-Agenten,
|
||||
agentische Entwicklungswerkzeuge und Evaluation von AI-Systemen.
|
||||
347
Modulbeschreibung_AISE502_v3_2026.md
Normal file
@ -0,0 +1,347 @@
|
||||
# Modulbeschreibung: AISE502 – AI in SE II
|
||||
|
||||
| Feld | Wert |
|
||||
|---|---|
|
||||
| **Autor/in** | Herzog Florian |
|
||||
| **Ausgabestelle** | Institute for Data Analysis, Artificial Intelligence, Visualization, and Simulation (DAViS) |
|
||||
| **Geltungsbereich** | Departement |
|
||||
| **Klassifizierung** | Nicht klassifiziert |
|
||||
| **Version** | 3.0.0 |
|
||||
| **Ausgabedatum** | 2026 (Neufassung entlang des Vorlesungsskripts) |
|
||||
|
||||
---
|
||||
|
||||
## Modul
|
||||
|
||||
| Feld | Wert |
|
||||
|---|---|
|
||||
| **Name** | AI in Software Engineering II |
|
||||
| **Kürzel** | AISE502 |
|
||||
| **ECTS-Punkte** | 4 |
|
||||
| **Typ** | Pflichtmodul |
|
||||
| **Verantwortliche/r** | Herzog Florian |
|
||||
| **Semester** | 5. Semester |
|
||||
|
||||
### Leitidee
|
||||
|
||||
Das Modul "AI in Software Engineering II" stellt das **Software Engineering grosser, langlebiger
|
||||
Systeme** in den Mittelpunkt. Sein roter Faden ist das englischsprachige Vorlesungsskript
|
||||
*"A Theory of Architecture--Application Fit"*, das eine durchgängige, messbare
|
||||
Entscheidungstheorie der Softwarearchitektur entwickelt: Architektur wird verstanden als die
|
||||
Menge der signifikanten, schwer umkehrbaren Entscheidungen, die durch **messbare
|
||||
Qualitätsattribute** getrieben, durch systematischen Abgleich von **Anforderungsprofilen**
|
||||
(zehn Anwendungsklassen) und **Fähigkeitsprofilen** (sieben Architektur-Patterns) über
|
||||
**zwölf gemeinsame Profildimensionen** getroffen und über den gesamten Lebenszyklus
|
||||
empirisch überprüft werden (Fitness Functions, DORA-Metriken).
|
||||
|
||||
Die Leitfrage lautet: *Wie entwerfe, begründe und betreibe ich die Struktur eines
|
||||
Software-Systems so, dass es seine Qualitätsattribute erfüllt und über Jahre wartbar bleibt --
|
||||
auch dann, wenn einzelne Komponenten nicht-deterministisch, fehlbar und kostenintensiv sind?*
|
||||
|
||||
Künstliche Intelligenz erscheint in **zwei gleichwertigen, strikt getrennten Achsen**:
|
||||
|
||||
- **Achse A -- AI als Werkzeug zum Bauen:** Studierende setzen agentische
|
||||
Entwicklungswerkzeuge produktiv, aber kritisch-reflektiert ein -- auf Basis der empirischen
|
||||
Evidenz (randomisierte Studien mit positiven wie negativen Befunden) und mit
|
||||
Architektur-Dokumentation und Fitness Functions als Leitplanken.
|
||||
- **Achse B -- AI als Komponente im System:** Studierende entwerfen Architekturen, in denen
|
||||
LLM-, ML- und Optimierungskomponenten als Laufzeit-Bausteine wirken, und machen diese
|
||||
nicht-deterministischen Komponenten *engineering-tauglich*: gekapselt (Gateway, Ports),
|
||||
asynchron integriert, beobachtbar (Kosten, Latenz), getestet (Eval-Harness) und abgesichert
|
||||
(Ontologie-Guard, Prompt-Injection-Abwehr).
|
||||
|
||||
Die zentrale Erkenntnis des Moduls (Annahme A6 der Theorie): **AI erweitert den
|
||||
Qualitätsattributraum, ändert aber die Methode nicht.** Die Disziplin, die man zum Bauen
|
||||
*mit* AI braucht, ist dieselbe wie jene zum Einbetten *von* AI.
|
||||
|
||||
**Didaktisches Prinzip:** Das Modul arbeitet durchgängig **induktiv** -- Fallstudien und
|
||||
Beispiele zuerst, Verallgemeinerung danach. Jedes Pattern wird aus dem realen Problem
|
||||
entwickelt, das es hervorbrachte; jede Anwendungsklasse aus ihren realen Herausforderungen;
|
||||
das Matching-Verfahren aus drei durchgerechneten Fällen. Zu jedem Pattern gehören
|
||||
Open-Source-Frameworks zum Bauen und klonbare Open-Source-Referenzsysteme zum Inspizieren
|
||||
("Build it and study it"). Ein durchgehendes Gruppenprojekt -- eine verteilte, AI-gestützte
|
||||
Portfolio-Analyse-Plattform -- wendet den gesamten Bogen praktisch an.
|
||||
|
||||
Das Verhältnis von klassischem Software Engineering zu AI-spezifischen Techniken beträgt
|
||||
etwa **60 % zu 40 %**.
|
||||
|
||||
### Voraussetzungen
|
||||
|
||||
1. AI in Software Engineering I (AISE501)
|
||||
2. Software Technik I und II
|
||||
3. Maschinelles Lernen, Deep Learning
|
||||
4. Mathematik-Grundlagen, Informatik-Grundlagen
|
||||
|
||||
### Lernergebnisse
|
||||
|
||||
Nach erfolgreichem Abschluss dieses Moduls sind die Studierenden in der Lage:
|
||||
|
||||
1. **Architektur als Entscheidungsproblem behandeln (Skript Teil I):**
|
||||
- Architektur als Menge schwer umkehrbarer, qualitätsgetriebener Entscheidungen verstehen
|
||||
(tragende Annahmen A1--A6) und Entscheidungen mit Rationale dokumentieren
|
||||
(Architecture Decision Records, C4-Sichten, ISO/IEC/IEEE 42010).
|
||||
- Die zwölf Profildimensionen (ISO/IEC 25010:2023-verankert, je mit Antwortmass und
|
||||
Messinstrument) als gemeinsames Koordinatensystem von Anforderung und Fähigkeit
|
||||
anwenden.
|
||||
|
||||
2. **Anforderungsprofile konstruieren (Teil I und III):**
|
||||
- Architektur-relevante Anforderungen elizitieren und als sechsteilige
|
||||
Qualitätsszenarien mit Antwortmass formulieren; Gewichte über Utility Trees ableiten.
|
||||
- Anwendungsklassen als Anforderungsprofile R(a) charakterisieren: Gewichte,
|
||||
Workload-Shape und regulatorische Knock-out-Constraints (u. a. BCBS 239, FINMA 2023/1,
|
||||
PCI DSS, EU AI Act).
|
||||
|
||||
3. **Fähigkeitsprofile herleiten und Architektur-Patterns beherrschen (Teil II):**
|
||||
- Die sieben Patterns (Schichtenarchitektur, modularer Monolith, Hexagonal,
|
||||
Microservices, Event-Driven, Pipes-and-Filters, Serverless) mit Topologie, realem
|
||||
Ursprungsproblem, Taktiken und dimensionsweisem Fähigkeitsprofil C(p) erklären.
|
||||
- Pro Pattern Open-Source-Frameworks einsetzen und Referenzsysteme im Quellcode
|
||||
inspizieren; Engineering-Konsequenzen (Build, Test, CI/CD, Deployment, Betrieb,
|
||||
Teamstruktur) ableiten.
|
||||
|
||||
4. **Passung berechnen, begründen und verteidigen (Teil IV):**
|
||||
- Das dreistufige, nicht-kompensatorische Matching-Verfahren anwenden (Knock-out und
|
||||
Workload-Shape-Gate, Veto auf hochgewichteten Dimensionen mit dokumentierten
|
||||
Mitigationen, ordinale Rangbildung mit Sensitivitätsanalyse) und die 7×10-Matrix als
|
||||
Explikations- statt Rechenmodell nutzen.
|
||||
- Hybride als Normalfall erkennen (z. B. ACID-Kern mit Event-getriebenen Rändern) und
|
||||
Evolutionspfade planen (Strangler Fig, dokumentierte Rückbau-Fallstudien).
|
||||
|
||||
5. **Entscheidungen messbar machen und betreiben (Teil IV):**
|
||||
- Jede Architekturentscheidung mit einem Messvertrag abschliessen: Fitness Functions in
|
||||
CI/CD (z. B. Modulgrenzen-Checks, Performance- und Token-Budgets), DORA-Metriken und
|
||||
Observability (Logging, Metriken, Tracing) im Betrieb.
|
||||
|
||||
6. **AI als Werkzeug professionell und kritisch einsetzen (Achse A, Teil V):**
|
||||
- Die empirische Evidenz zu AI-Coding-Werkzeugen differenziert bewerten (u. a.
|
||||
Copilot-RCT, METR-Studie, DORA-Reports) und daraus Konsequenzen für Spezifikation,
|
||||
Verifikation und Architektur ziehen.
|
||||
- Agentische Werkzeuge mit Architektur-Dokumentation als Kontext und Tests/Fitness
|
||||
Functions als Leitplanken einsetzen; Ausgaben kritisch bewerten und verantworten.
|
||||
|
||||
7. **AI als Systemkomponente engineering-tauglich machen (Achse B, Teil V):**
|
||||
- LLM-, ML- und Optimierungskomponenten hinter stabilen Schnittstellen kapseln
|
||||
(Gateway, Anti-Corruption-Layer), asynchron integrieren, deterministische von
|
||||
nicht-deterministischen Systemteilen strikt trennen.
|
||||
- Eigene Eval-Harnesses aufbauen (Golden Sets, LLM-as-Judge mit Kalibrierung,
|
||||
Domänen-Axiome) und als CI-Gate betreiben; Token-Kosten und Latenz messen und
|
||||
optimieren (Caching, Batching, Model-Routing).
|
||||
- Multi-Agenten-Systeme als Komposition klassischer Topologien konzipieren
|
||||
(Chain/Router/Orchestrator/Multi-Agent) und deren Ökonomie bewerten.
|
||||
|
||||
8. **Ethik und Verantwortung reflektieren:**
|
||||
- Gesellschaftliche, regulatorische (EU AI Act) und ethische Implikationen AI-gestützter
|
||||
Systeme im sensiblen Anwendungskontext (Finanzdaten) bewerten; neue Bedrohungsklassen
|
||||
(Prompt Injection, OWASP LLM Top 10) im Threat-Modeling berücksichtigen.
|
||||
|
||||
### Leistungsnachweis
|
||||
|
||||
| Anteil | Komponente |
|
||||
|---|---|
|
||||
| 50 % | Praxisprojekt (verteilte AI-gestützte Plattform, Gruppenarbeit) -- inklusive Requirements-Dossier (A1), Architektur-Dossier mit ADR und Messvertrag (A2), Implementierung sowie Abschlusspräsentation mit Architektur-Verteidigung |
|
||||
| 50 % | Schriftliche Modulschlussprüfung, 60 Minuten, open book (Skript und eigene Unterlagen in Papierform), closed internet -- Schwerpunkt: Architektur-Reasoning und Trade-off-Analyse entlang der Passungstheorie, keine reine Faktenabfrage |
|
||||
|
||||
### Nachprüfung
|
||||
|
||||
Gemäss Rahmenprüfungsordnung.
|
||||
|
||||
### Unterrichtssprache
|
||||
|
||||
Deutsch. Sämtliche Unterlagen (Vorlesungsskript, Übungen, Paper) in Englisch.
|
||||
|
||||
### Eingangskompetenzen
|
||||
|
||||
Sicherer Umgang mit Python, Versionsverwaltung (Git) und grundlegenden Software-Engineering-
|
||||
Prinzipien (Clean Code, SOLID). Grundverständnis von LLMs, Prompting und RAG aus AISE501.
|
||||
Grundlagen in Statistik und maschinellem Lernen.
|
||||
|
||||
---
|
||||
|
||||
## Inhalte
|
||||
|
||||
Der Kurs umfasst 14 Sitzungen. Der rote Faden ist das Vorlesungsskript *"A Theory of
|
||||
Architecture--Application Fit"* (Teile I--V); jede Sitzung verbindet einen Skript-Abschnitt
|
||||
mit einer AI-Linse und einem Projektschritt. Didaktik durchgängig induktiv: Fallstudien und
|
||||
Beispiele vor der Verallgemeinerung.
|
||||
|
||||
**1. Das Entscheidungsproblem und das Framework** *(Skript Teil I)*
|
||||
- Inhalte: Vier Produktionssysteme, eine Lektion (LMAX, Monzo, Stack Overflow, Prime Video);
|
||||
Architektur als schwer umkehrbare Entscheidungen; die fünf Framework-Elemente (R(a), C(p),
|
||||
fit, ADR, Messvertrag); die tragenden Annahmen A1--A6; ADR/MADR und C4.
|
||||
- Praktische Anwendung: Projektstart (Domäne, Vision, Werkzeug-Setup); ein Agent erstellt
|
||||
ADR-Entwürfe -- der Mensch entscheidet und verantwortet (Achse A).
|
||||
|
||||
**2. Das Koordinatensystem: zwölf Profildimensionen** *(Teil I)*
|
||||
- Inhalte: Von Alltagsfragen zu messbaren Dimensionen; die zwölf Dimensionen einzeln
|
||||
motiviert (Last, Korrektheit/Vertrauen, Wandel/Delivery, Ökonomie/Organisation, AI);
|
||||
ISO/IEC 25010:2023 als Vokabular; Antwortmasse und Messinstrumente.
|
||||
- Praktische Anwendung: Dimensionsprofil einer täglich genutzten App erstellen und
|
||||
diskutieren; erste Qualitätsszenarien für die Projektplattform formulieren.
|
||||
|
||||
**3. Nachfrage, Angebot, Passung: das formale Modell** *(Teil I)*
|
||||
- Inhalte: Konstruktion von R(a) (ASR → Szenarien → Utility Tree → Gewichte; Workload-Shape;
|
||||
Knock-out-Constraints); Herleitung von C(p) über Taktiken; das dreistufige
|
||||
Matching-Verfahren am Mini-Match des Kursprojekts (C10 gegen drei Kandidaten); warum keine
|
||||
gewichtete Summe (MCDM-Kritik).
|
||||
- Praktische Anwendung: R(Projektplattform) im Team konstruieren und als Utility Tree
|
||||
begründen; Qualitätsszenarien mit Antwortmass fixieren.
|
||||
|
||||
**4. Patterns I: Ein Deployable** *(Teil II)*
|
||||
- Inhalte: Schichtenarchitektur, modularer Monolith, Hexagonal/Ports-and-Adapters -- je:
|
||||
reales Ursprungsproblem, Topologie, dimensionsweises Fähigkeitsprofil,
|
||||
Engineering-Konsequenzen, Anti-Patterns; Modulgrenzen als CI-Gegenstand (Spring Modulith,
|
||||
import-linter, ArchUnit).
|
||||
- Praktische Anwendung: "Build it and study it" -- healthchecks (Django), Apache Fineract
|
||||
und das Cosmic-Python-Repo klonen und die Architektur im Code nachweisen; AI-Linse: der
|
||||
LLM-Provider hinter einem Port.
|
||||
|
||||
**5. Patterns II: Verteilte Topologien** *(Teil II)*
|
||||
- Inhalte: Microservices und Event-Driven Architecture -- Ursprungsprobleme (Release-Zug,
|
||||
Ingest), Profile, Sagas vs. ACID, Resilienz-Grundmuster (Timeout, Retry, Circuit-Breaker),
|
||||
Schema-Governance; dokumentierte Fallstudien (Netflix, Uber DOMA, Segment-Rückbau).
|
||||
- Praktische Anwendung: Online Boutique (Kubernetes) und der Home-Assistant-EventBus im
|
||||
Quellcode; AI-Linse: ein LLM-Aufruf als unzuverlässiger Remote-Call.
|
||||
|
||||
**6. Patterns III: Batch und Serverless; Verallgemeinerung** *(Teil II)*
|
||||
- Inhalte: Pipes-and-Filters/Batch und Serverless/FaaS; danach die Verallgemeinerung:
|
||||
Architecture Quantum, "Partitioning beats distribution", Evidenzbasis (Sterne-Ratings)
|
||||
und die konsolidierte Fähigkeitstabelle als Vergleichssicht.
|
||||
- Praktische Anwendung: dbt-Pipeline (jaffle_shop_duckdb) lokal bauen; Knative-Bookstore
|
||||
inspizieren; Projekt: Bounded Contexts aus der Ontologie ableiten (Vertiefung AISE501).
|
||||
|
||||
**7. Anwendungsklassen I: Transaktion, Content, Verwaltung** *(Teil III)*
|
||||
- Inhalte: C1 Kernbanking, C2 Social/Content, C3 Back-Office, C4 ERP, C5 E-Commerce -- je:
|
||||
reale Herausforderungen mit Zahlen und Regulatorik, Anforderungsprofil über die zwölf
|
||||
Dimensionen, und *welche Architektur reale Systeme wählten und warum* (LMAX vs. Monzo,
|
||||
Instagram, Shopify, Odoo/Fineract).
|
||||
- Praktische Anwendung: Walking Skeleton des Projekts -- deterministische Services und ein
|
||||
minimaler Agent laufen End-to-End.
|
||||
|
||||
**8. Anwendungsklassen II: Daten, Echtzeit, AI-nativ** *(Teil III)*
|
||||
- Inhalte: C6 Simulation/Batch, C7 DSS/BI, C8 IoT-Streaming, C9 Collaboration/Messaging,
|
||||
C10 AI-native Advisory-Plattform (das Kursprojekt als zehnte Klasse); Verallgemeinerung:
|
||||
zehn Profile nebeneinander, Spiegelpaare, Übergabe an das Matching.
|
||||
- Praktische Anwendung: Anforderungsprofil des Projekts gegen C10 abgleichen; Resilienz
|
||||
gegen Ausfall externer Datenquellen einbauen.
|
||||
|
||||
**9. Die Passung: drei Fälle, drei Stufen, die Matrix** *(Teil IV)*
|
||||
- Inhalte: Drei durchgerechnete Matches (C6: Shape-Gate; C1: Veto und Mitigationen; C2:
|
||||
ordinale Rangbildung und Tradeoff-Points); das Verfahren im Allgemeinen; die 7×10-Matrix
|
||||
mit Zeilen-Begründungen.
|
||||
- Praktische Anwendung: Matching der eigenen Plattform-Architektur nachvollziehen und als
|
||||
ADR mit Rationale dokumentieren (Pflicht-Artefakt).
|
||||
|
||||
**10. Hybride, Evolution und das achtstufige Entscheidungsverfahren** *(Teil IV)*
|
||||
- Inhalte: Hybride als Normalfall; Evolutionspfade und Migrationsstrategien (Strangler Fig;
|
||||
Fallstudien Segment, Prime Video, Shopify); das achtstufige Entscheidungsverfahren von den
|
||||
ASRs bis zum Messvertrag, durchgespielt am Kursprojekt (ADR-007).
|
||||
- Praktische Anwendung: Orchestrierter Multi-Agent (2--3 Sub-Agenten über klare Kontrakte)
|
||||
-- Pflichtteil des Projekts.
|
||||
|
||||
**11. Der Messvertrag: Fitness Functions, DORA, Betrieb** *(Teil IV)*
|
||||
- Inhalte: Fitness Functions (atomar/holistisch, triggered/continual) in CI/CD; die vier
|
||||
DORA-Metriken und der Kopplungs-Befund; Observability; Kostenverlauf von
|
||||
Architekturänderungen (Boehm vs. Menzies); Conway's Law und Team Topologies als dritte
|
||||
Passungsdimension.
|
||||
- Praktische Anwendung: CI/CD-Pipeline mit Architektur-Fitness-Functions (Modulgrenzen,
|
||||
Budgets) und Observability für Kosten und Latenz aufsetzen.
|
||||
|
||||
**12. Achse A: AI als Werkzeug -- Evidenz und Konsequenzen** *(Teil V)*
|
||||
- Inhalte: Zwei widersprüchliche Experimente (Copilot-RCT +55.8 % vs. METR −19 % inkl.
|
||||
Wahrnehmungslücke) und ihre Auflösung; der Verifikations-Engpass; Architektur-Dokumente
|
||||
als Agenten-Kontext; Guardrails als Voraussetzung; Werkzeuglandschaft und Risiken.
|
||||
- Praktische Anwendung: Ein Agent generiert Tests/Refactorings gegen die eigene Codebasis;
|
||||
Studierende bewerten Abdeckung, Qualität und Review-Last.
|
||||
|
||||
**13. Achse B: AI als Komponente -- Kapselung, Evaluation, Orchestrierung** *(Teil V)*
|
||||
- Inhalte: Der Sentiment-Call falsch und richtig verdrahtet; drei Komponententypen (LLM,
|
||||
ML, Solver); LLM-Gateway-Referenzarchitektur (Routing, Caching, Budgets, Fallbacks);
|
||||
Eval-Harness (Golden Sets, LLM-as-Judge, Domänen-Axiome) als CI-Gate; Prompt Injection
|
||||
und EU AI Act; Agenten-Orchestrierung als emergentes Kompositionsmuster und ihre Ökonomie.
|
||||
- Praktische Anwendung: Eval-Harness gegen Domänenregeln aufbauen (Pflicht); Ontologie-Guard
|
||||
und Kosten-Dashboard; Kür: autonomes Planning, Self-Repair-Loops, Model-Routing.
|
||||
|
||||
**14. Synthese, Präsentation und Architektur-Kritik**
|
||||
- Inhalte: Die Theorie-Pipeline in einem Satz; Grenzen der Theorie (auf sich selbst
|
||||
angewandt); Trade-offs verteidigen; Reflexion: Wo half und wo schadete AI -- im Bauen
|
||||
(Achse A) und im System (Achse B)?
|
||||
- Praktische Anwendung: Präsentationen, Architektur-Verteidigung und Peer-Reviews der
|
||||
Abschlussprojekte.
|
||||
|
||||
---
|
||||
|
||||
## Praxisprojekt: AI-Augmented Portfolio Intelligence Platform
|
||||
|
||||
Als durchgehendes Gruppenprojekt entwickeln die Studierenden eine verteilte Analyse- und
|
||||
Advisory-Plattform für Aktienportfolios (**kein Trading, kein echtes Geld** -- ausschliesslich
|
||||
Analyse und Empfehlung). Die Plattform ist im Skript als zehnte Anwendungsklasse (C10)
|
||||
durchmodelliert; ihre Architektur folgt dem im Modul berechneten Verdikt: **hexagonaler
|
||||
modularer Monolith als deterministischer Kern, Event-getriebene Ränder, Pipelines für
|
||||
Ingestion und Evaluation, orchestrierter Advisor-Agent hinter einem LLM-Gateway.**
|
||||
|
||||
- bezieht **strukturierte externe Daten** (Börsenkurse, z. B. via Yahoo Finance) -- mit
|
||||
Live-API und verpflichtendem Cache-/Snapshot-Fallback;
|
||||
- bezieht **unstrukturierte externe Daten** (Firmen-News) und wandelt sie über eine
|
||||
AI-Komponente in strukturierte Insights um;
|
||||
- berechnet **Risiko-, Performance- und Portfolio-Optimierungs-Kennzahlen** (Formeln und
|
||||
Testvektoren werden vorgegeben; die Lernleistung ist das Engineering darum herum);
|
||||
- stellt die Funktionalität **API-first** bereit, mit dünnem Dashboard zur Demonstration.
|
||||
|
||||
**Zentrale Architekturregel:** *Agents propose; deterministic services decide and book.*
|
||||
Die AI-Agenten beziehen und interpretieren quantitative Werte ausschliesslich über die
|
||||
deterministischen Services -- sie berechnen nie selbst. Diese Trennung ist die prüfbare
|
||||
Manifestation von "AI engineering-tauglich machen".
|
||||
|
||||
**Abstufung Pflicht / Kür:**
|
||||
|
||||
- *Pflicht (bestehensrelevant):* orchestrierter Advisor-Agent mit 2--3 Sub-Agenten über
|
||||
klare Service-Kontrakte; LLM-Gateway mit Kosten-Observability; Ontologie-Guard;
|
||||
Eval-Harness als CI-Gate; vollständig getestete deterministische Services; Resilienz
|
||||
gegen Ausfall externer Datenquellen; ein ADR mit Messvertrag (Token-Budget,
|
||||
Eval-Schwelle, Modulgrenzen-Check).
|
||||
- *Kür (für Spitzennoten):* autonomes Planning, Self-Repair-Loops, Model-Routing.
|
||||
|
||||
---
|
||||
|
||||
## Lehr- und Lernmethoden
|
||||
|
||||
**Lehrtechniken:** Vorlesungen, Übungen, Gruppenarbeit, Online-Lehre, Workshops.
|
||||
|
||||
**Lernaktivitäten:** Studium des Skripts und der Literatur, Inspektion realer
|
||||
Open-Source-Systeme, Übungsaufgaben, Bearbeiten von Problemen und deren Lösungsfindung,
|
||||
Zusammenarbeit mit anderen Studierenden, projektbegleitendes Selbststudium.
|
||||
|
||||
**Lehrmethode:** Präsentation; Einzel-, Partner- und Gruppenarbeit; E-Learning.
|
||||
|
||||
---
|
||||
|
||||
## Struktur
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Online-, Hybrid- oder Präsenzunterricht | 42 h |
|
||||
| Selbststudium (Skript, Lektüre und Projekt) | 78 h |
|
||||
| **Total** | **120 h (4 ECTS)** |
|
||||
|
||||
## Literatur
|
||||
|
||||
**Leitmedium (roter Faden):**
|
||||
- *AISE502 Lecture Notes -- A Theory of Architecture--Application Fit*, F. Herzog,
|
||||
Fachhochschule Graubünden, 2026 (englisch; wird abgegeben).
|
||||
|
||||
**Die vier methodischen Hauptquellen der Theorie (im Skript gewürdigt):**
|
||||
- L. Bass, P. Clements, R. Kazman: *Software Architecture in Practice*, 4. Aufl.,
|
||||
Addison-Wesley/SEI, 2021 (Qualitätsszenarien, Taktiken, Utility Tree/ATAM).
|
||||
- M. Richards, N. Ford: *Fundamentals of Software Architecture -- A Modern Engineering
|
||||
Approach*, 2. Aufl., O'Reilly, 2025 (Architecture Characteristics, Trade-off-Gesetze).
|
||||
- N. Ford, R. Parsons, P. Kua, P. Sadalage: *Building Evolutionary Architectures*, 2. Aufl.,
|
||||
O'Reilly, 2022 (Fitness Functions, Messvertrag).
|
||||
- N. Forsgren, J. Humble, G. Kim: *Accelerate -- The Science of Lean Software and DevOps*,
|
||||
IT Revolution, 2018 (DORA-Metriken, Kopplungs-Befund).
|
||||
|
||||
**Begleitend:**
|
||||
- I. Sommerville: *Modernes Software-Engineering*, Pearson, 2020 (deutschsprachiger Anker).
|
||||
- S. Newman: *Building Microservices*, 2. Aufl., O'Reilly, 2021 (nach Bedarf als Reader).
|
||||
- Aktuelle wissenschaftliche Artikel und Branchenforschung zu AI-Agenten, agentischen
|
||||
Entwicklungswerkzeugen und Evaluation von AI-Systemen (u. a. DORA-Reports, METR,
|
||||
Anthropic Engineering).
|
||||
196
Modulbeschreibung_AISE502_v3_2026_confluence.txt
Normal file
@ -0,0 +1,196 @@
|
||||
h1. Modulbeschreibung: AISE502 – AI in SE II
|
||||
|
||||
||Feld||Wert||
|
||||
|*Autor/in*|Herzog Florian|
|
||||
|*Ausgabestelle*|Institute for Data Analysis, Artificial Intelligence, Visualization, and Simulation (DAViS)|
|
||||
|*Geltungsbereich*|Departement|
|
||||
|*Klassifizierung*|Nicht klassifiziert|
|
||||
|*Version*|3.0.0|
|
||||
|*Ausgabedatum*|2026 (Neufassung entlang des Vorlesungsskripts)|
|
||||
|
||||
----
|
||||
|
||||
h2. Modul
|
||||
|
||||
||Feld||Wert||
|
||||
|*Name*|AI in Software Engineering II|
|
||||
|*Kürzel*|AISE502|
|
||||
|*ECTS-Punkte*|4|
|
||||
|*Typ*|Pflichtmodul|
|
||||
|*Verantwortliche/r*|Herzog Florian|
|
||||
|*Semester*|5. Semester|
|
||||
|
||||
h3. Leitidee
|
||||
|
||||
Das Modul "AI in Software Engineering II" stellt das *Software Engineering grosser, langlebiger Systeme* in den Mittelpunkt. Sein roter Faden ist das englischsprachige Vorlesungsskript _A Theory of Architecture–Application Fit_, das eine durchgängige, messbare Entscheidungstheorie der Softwarearchitektur entwickelt: Architektur wird verstanden als die Menge der signifikanten, schwer umkehrbaren Entscheidungen, die durch *messbare Qualitätsattribute* getrieben, durch systematischen Abgleich von *Anforderungsprofilen* (zehn Anwendungsklassen) und *Fähigkeitsprofilen* (sieben Architektur-Patterns) über *zwölf gemeinsame Profildimensionen* getroffen und über den gesamten Lebenszyklus empirisch überprüft werden (Fitness Functions, DORA-Metriken).
|
||||
|
||||
Die Leitfrage lautet: _Wie entwerfe, begründe und betreibe ich die Struktur eines Software-Systems so, dass es seine Qualitätsattribute erfüllt und über Jahre wartbar bleibt – auch dann, wenn einzelne Komponenten nicht-deterministisch, fehlbar und kostenintensiv sind?_
|
||||
|
||||
Künstliche Intelligenz erscheint in *zwei gleichwertigen, strikt getrennten Achsen*:
|
||||
|
||||
* *Achse A – AI als Werkzeug zum Bauen:* Studierende setzen agentische Entwicklungswerkzeuge produktiv, aber kritisch-reflektiert ein – auf Basis der empirischen Evidenz (randomisierte Studien mit positiven wie negativen Befunden) und mit Architektur-Dokumentation und Fitness Functions als Leitplanken.
|
||||
* *Achse B – AI als Komponente im System:* Studierende entwerfen Architekturen, in denen LLM-, ML- und Optimierungskomponenten als Laufzeit-Bausteine wirken, und machen diese nicht-deterministischen Komponenten _engineering-tauglich_: gekapselt (Gateway, Ports), asynchron integriert, beobachtbar (Kosten, Latenz), getestet (Eval-Harness) und abgesichert (Ontologie-Guard, Prompt-Injection-Abwehr).
|
||||
|
||||
Die zentrale Erkenntnis des Moduls (Annahme A6 der Theorie): *AI erweitert den Qualitätsattributraum, ändert aber die Methode nicht.* Die Disziplin, die man zum Bauen _mit_ AI braucht, ist dieselbe wie jene zum Einbetten _von_ AI.
|
||||
|
||||
*Didaktisches Prinzip:* Das Modul arbeitet durchgängig *induktiv* – Fallstudien und Beispiele zuerst, Verallgemeinerung danach. Jedes Pattern wird aus dem realen Problem entwickelt, das es hervorbrachte; jede Anwendungsklasse aus ihren realen Herausforderungen; das Matching-Verfahren aus drei durchgerechneten Fällen. Zu jedem Pattern gehören Open-Source-Frameworks zum Bauen und klonbare Open-Source-Referenzsysteme zum Inspizieren ("Build it and study it"). Ein durchgehendes Gruppenprojekt – eine verteilte, AI-gestützte Portfolio-Analyse-Plattform – wendet den gesamten Bogen praktisch an.
|
||||
|
||||
Das Verhältnis von klassischem Software Engineering zu AI-spezifischen Techniken beträgt etwa *60 % zu 40 %*.
|
||||
|
||||
h3. Voraussetzungen
|
||||
|
||||
# AI in Software Engineering I (AISE501)
|
||||
# Software Technik I und II
|
||||
# Maschinelles Lernen, Deep Learning
|
||||
# Mathematik-Grundlagen, Informatik-Grundlagen
|
||||
|
||||
h3. Lernergebnisse
|
||||
|
||||
Nach erfolgreichem Abschluss dieses Moduls sind die Studierenden in der Lage:
|
||||
|
||||
# *Architektur als Entscheidungsproblem behandeln (Skript Teil I):*
|
||||
#* Architektur als Menge schwer umkehrbarer, qualitätsgetriebener Entscheidungen verstehen (tragende Annahmen A1–A6) und Entscheidungen mit Rationale dokumentieren (Architecture Decision Records, C4-Sichten, ISO/IEC/IEEE 42010).
|
||||
#* Die zwölf Profildimensionen (ISO/IEC 25010:2023-verankert, je mit Antwortmass und Messinstrument) als gemeinsames Koordinatensystem von Anforderung und Fähigkeit anwenden.
|
||||
# *Anforderungsprofile konstruieren (Teil I und III):*
|
||||
#* Architektur-relevante Anforderungen elizitieren und als sechsteilige Qualitätsszenarien mit Antwortmass formulieren; Gewichte über Utility Trees ableiten.
|
||||
#* Anwendungsklassen als Anforderungsprofile R(a) charakterisieren: Gewichte, Workload-Shape und regulatorische Knock-out-Constraints (u. a. BCBS 239, FINMA 2023/1, PCI DSS, EU AI Act).
|
||||
# *Fähigkeitsprofile herleiten und Architektur-Patterns beherrschen (Teil II):*
|
||||
#* Die sieben Patterns (Schichtenarchitektur, modularer Monolith, Hexagonal, Microservices, Event-Driven, Pipes-and-Filters, Serverless) mit Topologie, realem Ursprungsproblem, Taktiken und dimensionsweisem Fähigkeitsprofil C(p) erklären.
|
||||
#* Pro Pattern Open-Source-Frameworks einsetzen und Referenzsysteme im Quellcode inspizieren; Engineering-Konsequenzen (Build, Test, CI/CD, Deployment, Betrieb, Teamstruktur) ableiten.
|
||||
# *Passung berechnen, begründen und verteidigen (Teil IV):*
|
||||
#* Das dreistufige, nicht-kompensatorische Matching-Verfahren anwenden (Knock-out und Workload-Shape-Gate, Veto auf hochgewichteten Dimensionen mit dokumentierten Mitigationen, ordinale Rangbildung mit Sensitivitätsanalyse) und die 7×10-Matrix als Explikations- statt Rechenmodell nutzen.
|
||||
#* Hybride als Normalfall erkennen (z. B. ACID-Kern mit Event-getriebenen Rändern) und Evolutionspfade planen (Strangler Fig, dokumentierte Rückbau-Fallstudien).
|
||||
# *Entscheidungen messbar machen und betreiben (Teil IV):*
|
||||
#* Jede Architekturentscheidung mit einem Messvertrag abschliessen: Fitness Functions in CI/CD (z. B. Modulgrenzen-Checks, Performance- und Token-Budgets), DORA-Metriken und Observability (Logging, Metriken, Tracing) im Betrieb.
|
||||
# *AI als Werkzeug professionell und kritisch einsetzen (Achse A, Teil V):*
|
||||
#* Die empirische Evidenz zu AI-Coding-Werkzeugen differenziert bewerten (u. a. Copilot-RCT, METR-Studie, DORA-Reports) und daraus Konsequenzen für Spezifikation, Verifikation und Architektur ziehen.
|
||||
#* Agentische Werkzeuge mit Architektur-Dokumentation als Kontext und Tests/Fitness Functions als Leitplanken einsetzen; Ausgaben kritisch bewerten und verantworten.
|
||||
# *AI als Systemkomponente engineering-tauglich machen (Achse B, Teil V):*
|
||||
#* LLM-, ML- und Optimierungskomponenten hinter stabilen Schnittstellen kapseln (Gateway, Anti-Corruption-Layer), asynchron integrieren, deterministische von nicht-deterministischen Systemteilen strikt trennen.
|
||||
#* Eigene Eval-Harnesses aufbauen (Golden Sets, LLM-as-Judge mit Kalibrierung, Domänen-Axiome) und als CI-Gate betreiben; Token-Kosten und Latenz messen und optimieren (Caching, Batching, Model-Routing).
|
||||
#* Multi-Agenten-Systeme als Komposition klassischer Topologien konzipieren (Chain/Router/Orchestrator/Multi-Agent) und deren Ökonomie bewerten.
|
||||
# *Ethik und Verantwortung reflektieren:*
|
||||
#* Gesellschaftliche, regulatorische (EU AI Act) und ethische Implikationen AI-gestützter Systeme im sensiblen Anwendungskontext (Finanzdaten) bewerten; neue Bedrohungsklassen (Prompt Injection, OWASP LLM Top 10) im Threat-Modeling berücksichtigen.
|
||||
|
||||
h3. Leistungsnachweis
|
||||
|
||||
||Anteil||Komponente||
|
||||
|50 %|Praxisprojekt (verteilte AI-gestützte Plattform, Gruppenarbeit) – inklusive Requirements-Dossier (A1), Architektur-Dossier mit ADR und Messvertrag (A2), Implementierung sowie Abschlusspräsentation mit Architektur-Verteidigung|
|
||||
|50 %|Schriftliche Modulschlussprüfung, 60 Minuten, open book (Skript und eigene Unterlagen in Papierform), closed internet – Schwerpunkt: Architektur-Reasoning und Trade-off-Analyse entlang der Passungstheorie, keine reine Faktenabfrage|
|
||||
|
||||
h3. Nachprüfung
|
||||
|
||||
Gemäss Rahmenprüfungsordnung.
|
||||
|
||||
h3. Unterrichtssprache
|
||||
|
||||
Deutsch. Sämtliche Unterlagen (Vorlesungsskript, Übungen, Paper) in Englisch.
|
||||
|
||||
h3. Eingangskompetenzen
|
||||
|
||||
Sicherer Umgang mit Python, Versionsverwaltung (Git) und grundlegenden Software-Engineering-Prinzipien (Clean Code, SOLID). Grundverständnis von LLMs, Prompting und RAG aus AISE501. Grundlagen in Statistik und maschinellem Lernen.
|
||||
|
||||
----
|
||||
|
||||
h2. Inhalte
|
||||
|
||||
Der Kurs umfasst 14 Sitzungen. Der rote Faden ist das Vorlesungsskript _A Theory of Architecture–Application Fit_ (Teile I–V); jede Sitzung verbindet einen Skript-Abschnitt mit einer AI-Linse und einem Projektschritt. Didaktik durchgängig induktiv: Fallstudien und Beispiele vor der Verallgemeinerung.
|
||||
|
||||
# *Das Entscheidungsproblem und das Framework* _(Skript Teil I)_
|
||||
#* Inhalte: Vier Produktionssysteme, eine Lektion (LMAX, Monzo, Stack Overflow, Prime Video); Architektur als schwer umkehrbare Entscheidungen; die fünf Framework-Elemente (R(a), C(p), fit, ADR, Messvertrag); die tragenden Annahmen A1–A6; ADR/MADR und C4.
|
||||
#* Praktische Anwendung: Projektstart (Domäne, Vision, Werkzeug-Setup); ein Agent erstellt ADR-Entwürfe – der Mensch entscheidet und verantwortet (Achse A).
|
||||
# *Das Koordinatensystem: zwölf Profildimensionen* _(Teil I)_
|
||||
#* Inhalte: Von Alltagsfragen zu messbaren Dimensionen; die zwölf Dimensionen einzeln motiviert (Last, Korrektheit/Vertrauen, Wandel/Delivery, Ökonomie/Organisation, AI); ISO/IEC 25010:2023 als Vokabular; Antwortmasse und Messinstrumente.
|
||||
#* Praktische Anwendung: Dimensionsprofil einer täglich genutzten App erstellen und diskutieren; erste Qualitätsszenarien für die Projektplattform formulieren.
|
||||
# *Nachfrage, Angebot, Passung: das formale Modell* _(Teil I)_
|
||||
#* Inhalte: Konstruktion von R(a) (ASR → Szenarien → Utility Tree → Gewichte; Workload-Shape; Knock-out-Constraints); Herleitung von C(p) über Taktiken; das dreistufige Matching-Verfahren am Mini-Match des Kursprojekts (C10 gegen drei Kandidaten); warum keine gewichtete Summe (MCDM-Kritik).
|
||||
#* Praktische Anwendung: R(Projektplattform) im Team konstruieren und als Utility Tree begründen; Qualitätsszenarien mit Antwortmass fixieren.
|
||||
# *Patterns I: Ein Deployable* _(Teil II)_
|
||||
#* Inhalte: Schichtenarchitektur, modularer Monolith, Hexagonal/Ports-and-Adapters – je: reales Ursprungsproblem, Topologie, dimensionsweises Fähigkeitsprofil, Engineering-Konsequenzen, Anti-Patterns; Modulgrenzen als CI-Gegenstand (Spring Modulith, import-linter, ArchUnit).
|
||||
#* Praktische Anwendung: "Build it and study it" – healthchecks (Django), Apache Fineract und das Cosmic-Python-Repo klonen und die Architektur im Code nachweisen; AI-Linse: der LLM-Provider hinter einem Port.
|
||||
# *Patterns II: Verteilte Topologien* _(Teil II)_
|
||||
#* Inhalte: Microservices und Event-Driven Architecture – Ursprungsprobleme (Release-Zug, Ingest), Profile, Sagas vs. ACID, Resilienz-Grundmuster (Timeout, Retry, Circuit-Breaker), Schema-Governance; dokumentierte Fallstudien (Netflix, Uber DOMA, Segment-Rückbau).
|
||||
#* Praktische Anwendung: Online Boutique (Kubernetes) und der Home-Assistant-EventBus im Quellcode; AI-Linse: ein LLM-Aufruf als unzuverlässiger Remote-Call.
|
||||
# *Patterns III: Batch und Serverless; Verallgemeinerung* _(Teil II)_
|
||||
#* Inhalte: Pipes-and-Filters/Batch und Serverless/FaaS; danach die Verallgemeinerung: Architecture Quantum, "Partitioning beats distribution", Evidenzbasis (Sterne-Ratings) und die konsolidierte Fähigkeitstabelle als Vergleichssicht.
|
||||
#* Praktische Anwendung: dbt-Pipeline (jaffle_shop_duckdb) lokal bauen; Knative-Bookstore inspizieren; Projekt: Bounded Contexts aus der Ontologie ableiten (Vertiefung AISE501).
|
||||
# *Anwendungsklassen I: Transaktion, Content, Verwaltung* _(Teil III)_
|
||||
#* Inhalte: C1 Kernbanking, C2 Social/Content, C3 Back-Office, C4 ERP, C5 E-Commerce – je: reale Herausforderungen mit Zahlen und Regulatorik, Anforderungsprofil über die zwölf Dimensionen, und _welche Architektur reale Systeme wählten und warum_ (LMAX vs. Monzo, Instagram, Shopify, Odoo/Fineract).
|
||||
#* Praktische Anwendung: Walking Skeleton des Projekts – deterministische Services und ein minimaler Agent laufen End-to-End.
|
||||
# *Anwendungsklassen II: Daten, Echtzeit, AI-nativ* _(Teil III)_
|
||||
#* Inhalte: C6 Simulation/Batch, C7 DSS/BI, C8 IoT-Streaming, C9 Collaboration/Messaging, C10 AI-native Advisory-Plattform (das Kursprojekt als zehnte Klasse); Verallgemeinerung: zehn Profile nebeneinander, Spiegelpaare, Übergabe an das Matching.
|
||||
#* Praktische Anwendung: Anforderungsprofil des Projekts gegen C10 abgleichen; Resilienz gegen Ausfall externer Datenquellen einbauen.
|
||||
# *Die Passung: drei Fälle, drei Stufen, die Matrix* _(Teil IV)_
|
||||
#* Inhalte: Drei durchgerechnete Matches (C6: Shape-Gate; C1: Veto und Mitigationen; C2: ordinale Rangbildung und Tradeoff-Points); das Verfahren im Allgemeinen; die 7×10-Matrix mit Zeilen-Begründungen.
|
||||
#* Praktische Anwendung: Matching der eigenen Plattform-Architektur nachvollziehen und als ADR mit Rationale dokumentieren (Pflicht-Artefakt).
|
||||
# *Hybride, Evolution und das achtstufige Entscheidungsverfahren* _(Teil IV)_
|
||||
#* Inhalte: Hybride als Normalfall; Evolutionspfade und Migrationsstrategien (Strangler Fig; Fallstudien Segment, Prime Video, Shopify); das achtstufige Entscheidungsverfahren von den ASRs bis zum Messvertrag, durchgespielt am Kursprojekt (ADR-007).
|
||||
#* Praktische Anwendung: Orchestrierter Multi-Agent (2–3 Sub-Agenten über klare Kontrakte) – Pflichtteil des Projekts.
|
||||
# *Der Messvertrag: Fitness Functions, DORA, Betrieb* _(Teil IV)_
|
||||
#* Inhalte: Fitness Functions (atomar/holistisch, triggered/continual) in CI/CD; die vier DORA-Metriken und der Kopplungs-Befund; Observability; Kostenverlauf von Architekturänderungen (Boehm vs. Menzies); Conway's Law und Team Topologies als dritte Passungsdimension.
|
||||
#* Praktische Anwendung: CI/CD-Pipeline mit Architektur-Fitness-Functions (Modulgrenzen, Budgets) und Observability für Kosten und Latenz aufsetzen.
|
||||
# *Achse A: AI als Werkzeug – Evidenz und Konsequenzen* _(Teil V)_
|
||||
#* Inhalte: Zwei widersprüchliche Experimente (Copilot-RCT +55.8 % vs. METR −19 % inkl. Wahrnehmungslücke) und ihre Auflösung; der Verifikations-Engpass; Architektur-Dokumente als Agenten-Kontext; Guardrails als Voraussetzung; Werkzeuglandschaft und Risiken.
|
||||
#* Praktische Anwendung: Ein Agent generiert Tests/Refactorings gegen die eigene Codebasis; Studierende bewerten Abdeckung, Qualität und Review-Last.
|
||||
# *Achse B: AI als Komponente – Kapselung, Evaluation, Orchestrierung* _(Teil V)_
|
||||
#* Inhalte: Der Sentiment-Call falsch und richtig verdrahtet; drei Komponententypen (LLM, ML, Solver); LLM-Gateway-Referenzarchitektur (Routing, Caching, Budgets, Fallbacks); Eval-Harness (Golden Sets, LLM-as-Judge, Domänen-Axiome) als CI-Gate; Prompt Injection und EU AI Act; Agenten-Orchestrierung als emergentes Kompositionsmuster und ihre Ökonomie.
|
||||
#* Praktische Anwendung: Eval-Harness gegen Domänenregeln aufbauen (Pflicht); Ontologie-Guard und Kosten-Dashboard; Kür: autonomes Planning, Self-Repair-Loops, Model-Routing.
|
||||
# *Synthese, Präsentation und Architektur-Kritik*
|
||||
#* Inhalte: Die Theorie-Pipeline in einem Satz; Grenzen der Theorie (auf sich selbst angewandt); Trade-offs verteidigen; Reflexion: Wo half und wo schadete AI – im Bauen (Achse A) und im System (Achse B)?
|
||||
#* Praktische Anwendung: Präsentationen, Architektur-Verteidigung und Peer-Reviews der Abschlussprojekte.
|
||||
|
||||
----
|
||||
|
||||
h2. Praxisprojekt: AI-Augmented Portfolio Intelligence Platform
|
||||
|
||||
Als durchgehendes Gruppenprojekt entwickeln die Studierenden eine verteilte Analyse- und Advisory-Plattform für Aktienportfolios (*kein Trading, kein echtes Geld* – ausschliesslich Analyse und Empfehlung). Die Plattform ist im Skript als zehnte Anwendungsklasse (C10) durchmodelliert; ihre Architektur folgt dem im Modul berechneten Verdikt: *hexagonaler modularer Monolith als deterministischer Kern, Event-getriebene Ränder, Pipelines für Ingestion und Evaluation, orchestrierter Advisor-Agent hinter einem LLM-Gateway.*
|
||||
|
||||
* bezieht *strukturierte externe Daten* (Börsenkurse, z. B. via Yahoo Finance) – mit Live-API und verpflichtendem Cache-/Snapshot-Fallback;
|
||||
* bezieht *unstrukturierte externe Daten* (Firmen-News) und wandelt sie über eine AI-Komponente in strukturierte Insights um;
|
||||
* berechnet *Risiko-, Performance- und Portfolio-Optimierungs-Kennzahlen* (Formeln und Testvektoren werden vorgegeben; die Lernleistung ist das Engineering darum herum);
|
||||
* stellt die Funktionalität *API-first* bereit, mit dünnem Dashboard zur Demonstration.
|
||||
|
||||
*Zentrale Architekturregel:* _Agents propose; deterministic services decide and book._ Die AI-Agenten beziehen und interpretieren quantitative Werte ausschliesslich über die deterministischen Services – sie berechnen nie selbst. Diese Trennung ist die prüfbare Manifestation von "AI engineering-tauglich machen".
|
||||
|
||||
*Abstufung Pflicht / Kür:*
|
||||
|
||||
* _Pflicht (bestehensrelevant):_ orchestrierter Advisor-Agent mit 2–3 Sub-Agenten über klare Service-Kontrakte; LLM-Gateway mit Kosten-Observability; Ontologie-Guard; Eval-Harness als CI-Gate; vollständig getestete deterministische Services; Resilienz gegen Ausfall externer Datenquellen; ein ADR mit Messvertrag (Token-Budget, Eval-Schwelle, Modulgrenzen-Check).
|
||||
* _Kür (für Spitzennoten):_ autonomes Planning, Self-Repair-Loops, Model-Routing.
|
||||
|
||||
----
|
||||
|
||||
h2. Lehr- und Lernmethoden
|
||||
|
||||
*Lehrtechniken:* Vorlesungen, Übungen, Gruppenarbeit, Online-Lehre, Workshops.
|
||||
|
||||
*Lernaktivitäten:* Studium des Skripts und der Literatur, Inspektion realer Open-Source-Systeme, Übungsaufgaben, Bearbeiten von Problemen und deren Lösungsfindung, Zusammenarbeit mit anderen Studierenden, projektbegleitendes Selbststudium.
|
||||
|
||||
*Lehrmethode:* Präsentation; Einzel-, Partner- und Gruppenarbeit; E-Learning.
|
||||
|
||||
----
|
||||
|
||||
h2. Struktur
|
||||
|
||||
||Element||Stunden||
|
||||
|Online-, Hybrid- oder Präsenzunterricht|42 h|
|
||||
|Selbststudium (Skript, Lektüre und Projekt)|78 h|
|
||||
|*Total*|*120 h (4 ECTS)*|
|
||||
|
||||
h2. Literatur
|
||||
|
||||
*Leitmedium (roter Faden):*
|
||||
|
||||
* _AISE502 Lecture Notes – A Theory of Architecture–Application Fit_, F. Herzog, Fachhochschule Graubünden, 2026 (englisch; wird abgegeben).
|
||||
|
||||
*Die vier methodischen Hauptquellen der Theorie (im Skript gewürdigt):*
|
||||
|
||||
* L. Bass, P. Clements, R. Kazman: _Software Architecture in Practice_, 4. Aufl., Addison-Wesley/SEI, 2021 (Qualitätsszenarien, Taktiken, Utility Tree/ATAM).
|
||||
* M. Richards, N. Ford: _Fundamentals of Software Architecture – A Modern Engineering Approach_, 2. Aufl., O'Reilly, 2025 (Architecture Characteristics, Trade-off-Gesetze).
|
||||
* N. Ford, R. Parsons, P. Kua, P. Sadalage: _Building Evolutionary Architectures_, 2. Aufl., O'Reilly, 2022 (Fitness Functions, Messvertrag).
|
||||
* N. Forsgren, J. Humble, G. Kim: _Accelerate – The Science of Lean Software and DevOps_, IT Revolution, 2018 (DORA-Metriken, Kopplungs-Befund).
|
||||
|
||||
*Begleitend:*
|
||||
|
||||
* I. Sommerville: _Modernes Software-Engineering_, Pearson, 2020 (deutschsprachiger Anker).
|
||||
* S. Newman: _Building Microservices_, 2. Aufl., O'Reilly, 2021 (nach Bedarf als Reader).
|
||||
* Aktuelle wissenschaftliche Artikel und Branchenforschung zu AI-Agenten, agentischen Entwicklungswerkzeugen und Evaluation von AI-Systemen (u. a. DORA-Reports, METR, Anthropic Engineering).
|
||||
48
Semesterplan_AISE502_HS26.md
Normal file
@ -0,0 +1,48 @@
|
||||
# AISE502 – Semesterplan HS 2026 (14 Wochen, 4 Lektionen/Woche)
|
||||
|
||||
**Phasenlogik:**
|
||||
- **Wochen 1–7 (Designphase): 2 L Vorlesung + 2 L Übung.** Die Übung erarbeitet Requirements → Architekturstudium → Architekturentscheid + Lösungsdesign. Die Vorlesung liefert just-in-time genau das Handwerkszeug, das die Übung in derselben oder der Folgewoche braucht.
|
||||
- **Wochen 8–13 (Implementierungsphase): 3 L Vorlesung + 1 L Übung** (Standup/Coaching). Die Implementierung läuft primär im Selbststudium (78 h); die Vorlesung holt die Inhalte nach, die das Design nicht blockieren (Anwendungsklassen-Katalog, Messvertrag-Vertiefung, AI-Dimension).
|
||||
- **Woche 14: 1 L Synthese + 3 L Präsentationen/Architektur-Verteidigung.**
|
||||
|
||||
**Kernprinzip der Abstimmung:** Alles, was die Übung zum Entwerfen braucht (R(a)-Methode, die sieben Patterns, das Matching-Verfahren), ist bis Ende Woche 7 gelesen. Alles, was nicht design-blockierend ist (Klassen C1–C9, Hybride/Evolution, Achse A/B), liegt in der Implementierungsphase — dort stört es nicht und passt inhaltlich (Eval-Harness-Vorlesung in der Woche, in der der Eval-Harness gebaut wird).
|
||||
|
||||
| Wo | V/Ü | Vorlesung (Skript-Referenz) | Übung / Projekt | Meilenstein / Abgabe |
|
||||
|----|-----|------------------------------|-----------------|----------------------|
|
||||
| 1 | 2+2 | **Teil I §1–2:** Das Entscheidungsproblem; die fünf Framework-Elemente; Annahmen A1–A6; Einstieg Dimensionen (Fragen → Gruppen) | Kickoff: Teams, Repo/Tooling (agentische Werkzeuge), Domänenverständnis, Ontologie-Skizze, rohe Stakeholder-Wünsche sammeln | — |
|
||||
| 2 | 2+2 | **Teil I §2–3:** Die 12 Dimensionen komplett; Qualitätsszenarien (6 Teile), ASR, QAW, Utility Tree → Gewichte | Requirements-Workshop I: Qualitätsszenarien mit Antwortmass für die Plattform; Utility Tree beginnen | — |
|
||||
| 3 | 2+2 | **Teil I §4–6:** C(p) über Taktiken; das dreistufige fit-Verfahren am Mini-Match (C10!); ADR/MADR | Requirements-Workshop II: R(Plattform) finalisieren (Gewichte, Workload-Shape, Knock-out-Constraints); Ontologie als Vertrag | **A1: Requirements-Dossier** (Szenarien + Utility Tree + R(a)) |
|
||||
| 4 | 2+2 | **Teil II:** Layered, Modularer Monolith, Hexagonal — Problem → Profil → Engineering → „Build it and study it" | Architekturstudium I: Fineract + Cosmic-Python-Repo inspizieren; Kandidaten für den Plattform-Kern; C4-Kontext/Container-Entwurf | — |
|
||||
| 5 | 2+2 | **Teil II:** Microservices, Event-Driven (inkl. Resilienz-Grundmuster, Sagas vs. ACID) | Architekturstudium II: Ränder entwerfen (Ingestion-Queue, Resilienz gegen API-Ausfall); Service-Kontrakte skizzieren; Matrix-Vorfilter der Kandidaten | — |
|
||||
| 6 | 2+2 | **Teil II:** Pipes-and-Filters, Serverless; „Stepping Back" (Quantum, Partitionierung, Vergleichstabelle). **Teil III:** Klasse C10 vertieft (+ Spiegelpaar C1/C2 kurz) | Der Match: dreistufiges Verfahren für die Plattform durchführen (Knock-out → Veto → ordinale Lesung); Entscheid; ADR beginnen | — |
|
||||
| 7 | 2+2 | **Teil IV:** Drei Fälle, drei Stufen; das Verfahren im Allgemeinen; die 7×10-Matrix lesen; Messvertrag-Einführung | Lösungsdesign finalisieren: Service-Schnitt + Kontrakte, Walking-Skeleton-Plan, Messvertrag (Token-Budget, Eval-Schwelle, Modulgrenzen-Check); **Design-Review-Gate** | **A2: Architektur-Dossier** (ADR + C4 + Messvertrag) → Implementierung frei |
|
||||
| 8 | 3+1 | **Teil III:** Klassen C1–C5 (Herausforderungen → Profile → reale Architekturwahl) | Sprint 1: Walking Skeleton (MarketDataService + minimaler ResearchAgent + stabile API) | — |
|
||||
| 9 | 3+1 | **Teil III:** Klassen C6–C9 + „Stepping Back" (zehn Profile nebeneinander) | Coaching; Skeleton fertigstellen | **M: Walking Skeleton läuft End-to-End** |
|
||||
| 10 | 3+1 | **Teil IV II:** Hybride & Evolutionspfade (Segment, Prime Video, Shopify); das 8-Schritte-Verfahren mit ADR-007; Zeilen-Begründungen der Matrix vertieft | Coaching; deterministische Services (Performance/Risk/Optimization) mit exakten Tests gegen Referenzvektoren | — |
|
||||
| 11 | 3+1 | **Teil IV III:** Der Messvertrag vertieft — Fitness-Function-Taxonomie in CI/CD, die vier DORA-Metriken und der Kopplungs-Befund, Boehm vs. Menzies, Conway/Team Topologies als dritte Passungsdimension, Grenzen der Theorie | Coaching; Resilienz auf allen externen Aufrufen (Timeout, Retry, Circuit-Breaker, Fallback); Graceful Degradation | **M: Deterministischer Kern vollständig getestet + resilient** |
|
||||
| 12 | 3+1 | **Teil V, Achse A + B I:** Zwei widersprüchliche RCTs (Copilot vs. METR) und ihre Auflösung, Verifikations-Engpass, Guardrails (kompakt); der Sentiment-Call falsch/richtig verdrahtet; drei Komponententypen; LLM-Gateway; Eval-Harness-Grundlagen | Coaching; AdvisorAgent + 2–3 Sub-Agenten hinter dem Gateway (Pflichtteil); Ontologie-Guard aktiv | — |
|
||||
| 13 | 3+1 | **Teil V, Achse B II:** OWASP/Prompt Injection, EU AI Act; Matrix-Verschiebungen; Agenten-Orchestrierung als 8. Muster + Ökonomie (15×-Befund); Synthese der Theorie; Prüfungsorientierung | Coaching; Eval-Harness als CI-Gate, Kosten-Dashboard; Hardening; Kür (autonomes Planning, Self-Repair, Model-Routing) | **M: Eval-Harness im CI + Guard + Kosten-Observability** |
|
||||
| 14 | 1+3 | Synthese und Grenzen der Theorie; Reflexion beider Achsen; Prüfungshinweise | **Präsentationen + Architektur-Verteidigung + Peer-Reviews** | **A3: Abschlusspräsentation (M6)** |
|
||||
|
||||
## Abstimmungs-Kontrollpunkte (warum der Plan aufgeht)
|
||||
|
||||
1. **Requirements-Methode vor Requirements-Arbeit:** Szenarien/Utility-Tree (V Woche 2) → Requirements-Workshops (Ü Wochen 2–3). Abgabe A1 Ende Woche 3.
|
||||
2. **Patterns vor Architekturwahl:** Die sieben Patterns sind bis Woche 6 gelesen — exakt wenn die Übung den Match durchführt. Der Mini-Match in Woche 3 zeigt das Verfahren früh am eigenen Projekt (C10), sodass das Architekturstudium der Wochen 4–6 zielgerichtet ist.
|
||||
3. **Matching-Maschinerie in der Entscheidungswoche:** Teil IV (drei Fälle + Verfahren) liegt in Woche 7 — die Studierenden sehen formal, was sie in Woche 6 selbst getan haben, und schliessen mit dem Design-Review-Gate ab.
|
||||
4. **Nichts Blockierendes zu spät:** C1–C9 (Prüfungsstoff, aber nicht design-relevant) sowie Achse A/B kommen in den Wochen 8–13 — Gateway- und Eval-Harness-Grundlagen (V Woche 12) genau dann, wenn Gateway/Agenten gebaut werden (Ü Woche 12) und der Eval-Harness ins CI geht (Ü Woche 13). Teil IV erhält drei Vorlesungen (Wochen 7, 10, 11) — als Herz des Moduls und Prüfungsschwerpunkt; Teil V kompakt in zwei (Wochen 12–13).
|
||||
5. **Belastung:** Ab Woche 8 nur 3 L Vorlesung (nie 4); die 1-L-Übung ist Standup/Coaching, die Implementierung läuft im Selbststudium (78 h-Budget).
|
||||
|
||||
## Notwendige Anpassungen an project_exercise.tex
|
||||
|
||||
Die Meilenstein-Wochen im Aufgabenblatt stammen aus dem alten Ablauf und müssen auf die neue Phasenlogik gezogen werden:
|
||||
|
||||
| Meilenstein | Bisher | Neu |
|
||||
|---|---|---|
|
||||
| M1 Domain, Ontologie, Architektur | Wochen 1–5 | **Wochen 1–7** (inkl. Requirements-Dossier W3, Architektur-Dossier + Design-Gate W7) |
|
||||
| M2 Walking Skeleton | Woche 6 | **Wochen 8–9** |
|
||||
| M3 Resilienz + deterministischer Kern | Wochen 7–9 | **Wochen 10–11** |
|
||||
| M4 Multi-Agent + Evaluation | Wochen 8–10 | **Wochen 12–13** |
|
||||
| M5 Operate/Scale/Harden | Wochen 11–13 | **Woche 13** (Kür parallel) |
|
||||
| M6 Präsentation | Woche 14 | Woche 14 (unverändert) |
|
||||
|
||||
Zudem: Titelseite sagt „Spring Semester" — das Modul läuft im Herbstsemester (5. Semester); bei der Anpassung korrigieren.
|
||||
BIN
project_exercise/project_exercise.pdf
Normal file
490
project_exercise/project_exercise.tex
Normal file
@ -0,0 +1,490 @@
|
||||
\documentclass[12pt,a4paper]{article}
|
||||
\usepackage[utf8]{inputenc}
|
||||
\usepackage[T1]{fontenc}
|
||||
\usepackage[english]{babel}
|
||||
\usepackage{geometry}
|
||||
\geometry{margin=2.5cm, headheight=14.5pt, footskip=1.8cm}
|
||||
\usepackage{graphicx}
|
||||
\usepackage{hyperref}
|
||||
\usepackage{xcolor}
|
||||
\usepackage{listings}
|
||||
\usepackage{fancyhdr}
|
||||
\usepackage{tcolorbox}
|
||||
\tcbuselibrary{breakable}
|
||||
\usepackage{enumitem}
|
||||
\usepackage{microtype}
|
||||
\usepackage{booktabs}
|
||||
|
||||
\setlength{\emergencystretch}{3em}
|
||||
\renewcommand{\texttt}[1]{{\ttfamily\hyphenchar\font=`\-\relax #1}}
|
||||
|
||||
\definecolor{codegreen}{rgb}{0,0.6,0}
|
||||
\definecolor{codegray}{rgb}{0.5,0.5,0.5}
|
||||
\definecolor{codepurple}{rgb}{0.58,0,0.82}
|
||||
\definecolor{backcolour}{rgb}{0.95,0.95,0.92}
|
||||
|
||||
\lstdefinestyle{pythonstyle}{
|
||||
backgroundcolor=\color{backcolour},
|
||||
commentstyle=\color{codegreen},
|
||||
keywordstyle=\color{blue},
|
||||
numberstyle=\tiny\color{codegray},
|
||||
stringstyle=\color{codepurple},
|
||||
basicstyle=\ttfamily\footnotesize,
|
||||
breaklines=true, keepspaces=true,
|
||||
numbers=left, numbersep=5pt, tabsize=4, language=Python
|
||||
}
|
||||
\lstdefinestyle{promptstyle}{
|
||||
backgroundcolor=\color{backcolour},
|
||||
basicstyle=\ttfamily\footnotesize,
|
||||
breaklines=true, keepspaces=true,
|
||||
frame=single, rulecolor=\color{codegray}, tabsize=4
|
||||
}
|
||||
\lstset{style=pythonstyle}
|
||||
|
||||
\newtcolorbox{taskbox}[1][]{colback=blue!5!white, colframe=blue!75!black,
|
||||
title={#1}, fonttitle=\bfseries, breakable, before upper=\raggedright}
|
||||
\newtcolorbox{hintbox}{colback=yellow!5!white, colframe=yellow!50!black,
|
||||
title=Hints \& Tips, fonttitle=\bfseries, breakable, before upper=\raggedright}
|
||||
\newtcolorbox{warningbox}{colback=red!5!white, colframe=red!60!black,
|
||||
title=Common Mistakes \& Pitfalls, fonttitle=\bfseries, breakable, before upper=\raggedright}
|
||||
\newtcolorbox{conceptbox}[1][]{colback=green!5!white, colframe=green!50!black,
|
||||
title={#1}, fonttitle=\bfseries, breakable, before upper=\raggedright}
|
||||
\newtcolorbox{contextbox}[1][]{colback=gray!5!white, colframe=gray!60!black,
|
||||
title={#1}, fonttitle=\bfseries, breakable}
|
||||
|
||||
\pagestyle{fancy}
|
||||
\fancyhf{}
|
||||
\fancyhead[L]{AISE502 -- AI in Software Engineering II}
|
||||
\fancyhead[R]{Project: Portfolio Intelligence Platform}
|
||||
\fancyfoot[L]{\thepage}
|
||||
\fancyfoot[R]{\includegraphics[height=0.9cm]{../FHGR_Logo_small}}
|
||||
\renewcommand{\headrulewidth}{0.4pt}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\begin{titlepage}
|
||||
\centering
|
||||
\includegraphics[width=0.5\textwidth]{../FHGR_Logo_Large}\\[1cm]
|
||||
{\Huge\bfseries AI-Augmented Portfolio\\[0.3cm] Intelligence Platform\par}
|
||||
\vspace{0.8cm}
|
||||
{\Large AISE502 -- AI in Software Engineering II\par}
|
||||
\vspace{0.5cm}
|
||||
{\large Autumn Semester (5th Semester)\par}
|
||||
\vspace{1.2cm}
|
||||
{\large Semester Group Project\par}
|
||||
\vspace{0.4cm}
|
||||
{\normalsize Language: Python 3.11+ \quad$\cdot$\quad Architecture-first \quad$\cdot$\quad Distributed services + AI agents\par}
|
||||
\vfill
|
||||
{\small Analysis \& advisory only --- no trading, no real money.\par}
|
||||
\end{titlepage}
|
||||
|
||||
%====================================================================
|
||||
\section{Overview and Goals}
|
||||
|
||||
The goal of this project is to design, build, and operate a \textbf{distributed,
|
||||
AI-augmented analysis platform for stock portfolios}. The platform ingests
|
||||
\emph{structured} external data (market prices) and \emph{unstructured} external data
|
||||
(company news and web reports), turns both into decision-relevant information, computes
|
||||
quantitative risk, performance, and optimisation figures, and exposes the results through
|
||||
a small set of cooperating services driven by an orchestrated multi-agent layer.
|
||||
|
||||
This is a \textbf{Software Engineering II} project: the centre of gravity is
|
||||
\emph{architecture}---how you structure a system so that it meets its quality attributes
|
||||
and stays maintainable while one part of it (the news understanding) is non-deterministic,
|
||||
fallible, and costly. AI appears in two roles throughout the project: as a \emph{tool} you
|
||||
build the system \emph{with}, and as a \emph{component} that lives \emph{inside} the system.
|
||||
|
||||
\begin{conceptbox}[The single most important rule]
|
||||
The AI agents may only \textbf{obtain and interpret} quantitative values \emph{through the
|
||||
deterministic services} --- they must \textbf{never compute} a risk number, a return, or an
|
||||
allocation themselves. An agent that ``estimates'' a volatility is an architecture defect.
|
||||
This separation of deterministic from non-deterministic system parts is the core engineering
|
||||
lesson of the course, and it is graded.
|
||||
\end{conceptbox}
|
||||
|
||||
\subsection{What the platform does}
|
||||
\begin{enumerate}[nosep]
|
||||
\item Ingest \textbf{market prices} from a live API (e.g.\ Yahoo Finance) with a
|
||||
mandatory cache/snapshot fallback.
|
||||
\item Ingest \textbf{company news / web reports} (unstructured text).
|
||||
\item Use an \textbf{AI component} to turn news into structured insights (e.g.\ sentiment,
|
||||
affected tickers, event type) --- validated against a domain ontology.
|
||||
\item Compute \textbf{risk, performance, and optimisation} figures in deterministic
|
||||
services (formulae and test vectors are provided to you).
|
||||
\item Provide an \textbf{orchestrated multi-agent advisor} that combines the above into
|
||||
portfolio insights and explanations.
|
||||
\item Expose everything \textbf{API-first}, with a thin dashboard (e.g.\ Streamlit) only
|
||||
for demonstration.
|
||||
\end{enumerate}
|
||||
|
||||
\begin{contextbox}[Why build this?]
|
||||
This project forces the full architecture-and-engineering arc: you derive a service
|
||||
architecture from a domain ontology, design contracts between services, harden the system
|
||||
against unreliable external data, integrate non-deterministic AI behind stable interfaces,
|
||||
and evaluate, observe, and scale it. You will \emph{experience} first-hand why
|
||||
non-deterministic components demand discipline --- and you will use modern agentic
|
||||
development tools to build it, while keeping a critical eye on what they produce.
|
||||
\end{contextbox}
|
||||
|
||||
%====================================================================
|
||||
\section{Functional Requirements}
|
||||
|
||||
Each requirement names example \textbf{services} and their responsibilities. The exact
|
||||
class and module decomposition is part of \emph{your} architectural work --- the names below
|
||||
are guidance, not a prescription.
|
||||
|
||||
\subsection{Market Data (deterministic)}
|
||||
\begin{taskbox}[Features]
|
||||
\begin{itemize}[nosep]
|
||||
\item Fetch historical and recent prices for a configurable set of tickers.
|
||||
\item Use a live API with a \textbf{mandatory} cache/snapshot fallback when the API is
|
||||
unavailable or rate-limited.
|
||||
\item Provide a clean, versioned interface to downstream services.
|
||||
\end{itemize}
|
||||
\end{taskbox}
|
||||
\begin{taskbox}[Services / Responsibilities]
|
||||
\begin{itemize}[nosep]
|
||||
\item \texttt{MarketDataService}: retrieval, caching, normalisation of price series.
|
||||
\item Must expose a stable contract independent of the upstream provider's format.
|
||||
\end{itemize}
|
||||
\end{taskbox}
|
||||
|
||||
\subsection{News Ingestion \& AI Insight Extraction (non-deterministic)}
|
||||
\begin{taskbox}[Features]
|
||||
\begin{itemize}[nosep]
|
||||
\item Ingest unstructured company news / reports for the portfolio's tickers.
|
||||
\item Use an LLM to extract \textbf{structured insights}: sentiment, affected tickers,
|
||||
event type, short summary.
|
||||
\item Validate every extracted insight against the domain ontology (valid ticker?
|
||||
valid sector? plausible event type?).
|
||||
\end{itemize}
|
||||
\end{taskbox}
|
||||
\begin{taskbox}[Services / Responsibilities]
|
||||
\begin{itemize}[nosep]
|
||||
\item \texttt{NewsIngestionService}: fetch and store raw news with provenance.
|
||||
\item \texttt{ResearchAgent}: LLM-based extraction returning a strict, schema-validated
|
||||
\texttt{Insight} object. This is an \textbf{Anti-Corruption Layer}: the rest of the
|
||||
system never sees raw LLM text, only validated \texttt{Insight}s.
|
||||
\end{itemize}
|
||||
\end{taskbox}
|
||||
|
||||
\subsection{Quantitative Analysis (deterministic)}
|
||||
\begin{taskbox}[Features]
|
||||
\begin{itemize}[nosep]
|
||||
\item Compute portfolio \textbf{performance} (returns, cumulative return, Sharpe ratio).
|
||||
\item Compute \textbf{risk} (volatility, Value-at-Risk).
|
||||
\item Compute a \textbf{portfolio optimisation} (mean--variance / Markowitz).
|
||||
\item Formulae and reference test vectors are provided --- you implement the
|
||||
\emph{services and tests}, not the financial theory.
|
||||
\end{itemize}
|
||||
\end{taskbox}
|
||||
\begin{taskbox}[Services / Responsibilities]
|
||||
\begin{itemize}[nosep]
|
||||
\item \texttt{PerformanceService}, \texttt{RiskService}, \texttt{OptimizationService}.
|
||||
\item Each is \textbf{pure and deterministic}: same input $\rightarrow$ same output. These
|
||||
are the services your tests pin down exactly and your AI is evaluated against.
|
||||
\end{itemize}
|
||||
\end{taskbox}
|
||||
|
||||
\subsection{Portfolio State}
|
||||
\begin{taskbox}[Features / Services]
|
||||
\begin{itemize}[nosep]
|
||||
\item \texttt{PortfolioService}: holdings, positions, transactions (in-memory or simple
|
||||
persistence is sufficient).
|
||||
\item Provides the current portfolio composition to the analysis services and the advisor.
|
||||
\end{itemize}
|
||||
\end{taskbox}
|
||||
|
||||
\subsection{Multi-Agent Advisor (orchestration)}
|
||||
\begin{taskbox}[Features]
|
||||
\begin{itemize}[nosep]
|
||||
\item An \texttt{AdvisorAgent} orchestrates specialised sub-agents to answer
|
||||
portfolio questions and produce explained recommendations.
|
||||
\item Sub-agents communicate only through \textbf{service contracts}, never by sharing
|
||||
internal state.
|
||||
\end{itemize}
|
||||
\end{taskbox}
|
||||
\begin{taskbox}[Services / Responsibilities]
|
||||
\begin{itemize}[nosep]
|
||||
\item \texttt{AdvisorAgent} (orchestrator), \texttt{ResearchAgent} (news $\rightarrow$
|
||||
insights), \texttt{RiskAgent} (calls \texttt{RiskService}, interprets), and
|
||||
\texttt{OptimizationAgent} (calls \texttt{OptimizationService}, explains).
|
||||
\item Agents \emph{interpret and explain} numbers; services \emph{compute} them.
|
||||
\end{itemize}
|
||||
\end{taskbox}
|
||||
|
||||
\subsection{Interface (API-first, thin UI)}
|
||||
\begin{taskbox}[Features]
|
||||
\begin{itemize}[nosep]
|
||||
\item A clean HTTP/JSON API is the primary product surface.
|
||||
\item A thin dashboard (e.g.\ Streamlit) for demonstration: show the portfolio, the
|
||||
computed figures, and the advisor's explained recommendation.
|
||||
\item The UI must contain \textbf{no business logic} --- it only calls the API.
|
||||
\end{itemize}
|
||||
\end{taskbox}
|
||||
|
||||
%====================================================================
|
||||
\section{Architecture: From Ontology to Services}
|
||||
|
||||
Before implementing, derive your architecture from the domain. This is the
|
||||
\emph{traceability chain} you practised conceptually in AISE501 --- now you build it for real.
|
||||
|
||||
\begin{conceptbox}[Derivation chain]
|
||||
Domain understanding $\rightarrow$ Domain model $\rightarrow$ \textbf{Ontology} (asset
|
||||
classes, sectors, rules) $\rightarrow$ \textbf{Bounded contexts} $\rightarrow$ Services with
|
||||
contracts $\rightarrow$ AI agents behind anti-corruption layers $\rightarrow$ evaluation,
|
||||
observability, hardening.
|
||||
\end{conceptbox}
|
||||
|
||||
\subsection{Reference architecture}
|
||||
The system follows a service-oriented split. Deterministic services form a trustworthy core;
|
||||
the non-deterministic AI layer sits on top and may only \emph{read} the core through its
|
||||
contracts.
|
||||
|
||||
\begin{lstlisting}[style=promptstyle]
|
||||
+-----------------------------------------------------------+
|
||||
| Thin Dashboard (Streamlit) --- API-first, no logic |
|
||||
+----------------------------+------------------------------+
|
||||
| (stable HTTP/JSON API)
|
||||
+----------------------------+------------------------------+
|
||||
| Multi-Agent Layer (NON-DETERMINISTIC) |
|
||||
| AdvisorAgent (orchestrator) |
|
||||
| |-- ResearchAgent (news -> Insight) |
|
||||
| |-- RiskAgent (calls RiskService) |
|
||||
| +-- OptimizationAgent (calls OptimizationService) |
|
||||
+-----------------------------------------------------------+
|
||||
| DETERMINISTIC SERVICES (NO LLM INSIDE) |
|
||||
| MarketDataService (live API + cache fallback) |
|
||||
| NewsIngestionService(raw news + provenance) |
|
||||
| PerformanceService (returns, Sharpe) |
|
||||
| RiskService (volatility, VaR) |
|
||||
| OptimizationService (mean-variance) |
|
||||
| PortfolioService (holdings, positions) |
|
||||
+-----------------------------------------------------------+
|
||||
| Domain Ontology = architecture contract + guard rail |
|
||||
+-----------------------------------------------------------+
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{The ontology in two roles}
|
||||
\begin{itemize}[nosep]
|
||||
\item \textbf{As a contract (build time):} the ontology defines the bounded contexts and
|
||||
drives the service boundaries and data models.
|
||||
\item \textbf{As a guard (run time):} every AI-produced insight is validated against the
|
||||
ontology before it is allowed into the system, suppressing hallucinated tickers,
|
||||
sectors, or impossible events.
|
||||
\end{itemize}
|
||||
|
||||
%====================================================================
|
||||
\section{AI Integration: Contracts, Guards, and Evaluation}
|
||||
|
||||
\subsection{Anti-Corruption Layer around the LLM}
|
||||
\begin{taskbox}[Requirements]
|
||||
\begin{itemize}[nosep]
|
||||
\item The LLM is reached only through the \texttt{ResearchAgent}, which returns a strictly
|
||||
schema-validated \texttt{Insight}. No other code touches raw model output.
|
||||
\item Use structured output / schema validation; reject or repair non-conforming responses.
|
||||
\item Keep system prompts concise; separate persona, task, and data (use the prompting
|
||||
techniques from AISE501).
|
||||
\end{itemize}
|
||||
\end{taskbox}
|
||||
|
||||
\subsection{Guards against hallucination and failure}
|
||||
\begin{taskbox}[Requirements]
|
||||
\begin{itemize}[nosep]
|
||||
\item Validate every insight against the ontology (valid ticker / sector / event type).
|
||||
\item Apply resilience patterns to \emph{every} external call (market API, news API, LLM
|
||||
API): timeout, retry with backoff, circuit breaker, and a defined fallback.
|
||||
\item The system must degrade gracefully: if the LLM or a data API is down, deterministic
|
||||
analysis must still work and the UI must say so.
|
||||
\end{itemize}
|
||||
\end{taskbox}
|
||||
|
||||
\subsection{Evaluation harness (mandatory)}
|
||||
\begin{taskbox}[Requirements]
|
||||
\begin{itemize}[nosep]
|
||||
\item \textbf{Deterministic services:} pin them with exact tests against the provided
|
||||
reference test vectors.
|
||||
\item \textbf{Non-deterministic AI:} build an eval harness --- e.g.\ a small labelled set
|
||||
of news items with expected sentiment/tickers, plus regression checks against
|
||||
ontology axioms. Report accuracy and failure modes, not just ``it works''.
|
||||
\end{itemize}
|
||||
\end{taskbox}
|
||||
|
||||
\begin{warningbox}
|
||||
\begin{itemize}[nosep]
|
||||
\item \textbf{Never} let an agent compute or invent a numeric figure --- always route
|
||||
through the deterministic service.
|
||||
\item \textbf{Never} pass an unvalidated LLM response further into the system.
|
||||
\item Do not call external APIs without a timeout and a fallback --- they \emph{will} fail
|
||||
during your demo.
|
||||
\item Do not put business logic in the UI; it belongs in services.
|
||||
\item Treat news text as \textbf{untrusted input}: it is a prompt-injection vector.
|
||||
\item Never hardcode API keys --- use environment variables / a \texttt{.env} file
|
||||
excluded from version control.
|
||||
\end{itemize}
|
||||
\end{warningbox}
|
||||
|
||||
%====================================================================
|
||||
\section{Mandatory vs.\ Distinction (Pflicht / K\"ur)}
|
||||
|
||||
\begin{conceptbox}[Mandatory --- required to pass]
|
||||
\begin{itemize}[nosep]
|
||||
\item Architecture derived from the ontology, documented with ADRs and a C4-style diagram.
|
||||
\item Deterministic services with full, exact tests against the reference vectors.
|
||||
\item Orchestrated advisor with \textbf{2--3 specialised sub-agents} cooperating only via
|
||||
service contracts.
|
||||
\item Ontology guard on all AI insights; resilience against external-data outages.
|
||||
\item Evaluation harness for the AI component; basic observability (cost and latency).
|
||||
\end{itemize}
|
||||
\end{conceptbox}
|
||||
|
||||
\begin{conceptbox}[Distinction --- for top grades]
|
||||
\begin{itemize}[nosep]
|
||||
\item \textbf{Autonomous planning}: the advisor decides itself which sub-agents/tools to
|
||||
call rather than following a fixed pipeline.
|
||||
\item \textbf{Self-repair loops}: e.g.\ ``news contradictory $\rightarrow$ fetch more
|
||||
sources'' before answering.
|
||||
\item \textbf{Model routing}: a small/cheap model for sentiment, a larger one for synthesis,
|
||||
with cost/latency reported.
|
||||
\item Deployment with CI/CD and richer observability (tracing).
|
||||
\end{itemize}
|
||||
\end{conceptbox}
|
||||
|
||||
%====================================================================
|
||||
\clearpage
|
||||
\section{Semester Plan and Development Milestones}
|
||||
|
||||
The project is organised in \textbf{two phases}, tightly synchronised with the lecture
|
||||
(script Parts I--V). \textbf{Weeks 1--7 are the design phase}: the weekly two-hour exercise
|
||||
slot is used to produce the requirements, study candidate architectures against the patterns
|
||||
taught in the lecture, and decide and document your architecture. \textbf{Weeks 8--14 are
|
||||
the implementation phase}: the exercise slot becomes a one-hour standup/coaching session,
|
||||
and implementation happens mainly in self-study time. All design deliverables use the
|
||||
methods of the lecture script: quality attribute scenarios with response measures, a utility
|
||||
tree, the requirements profile $R(a)$, the three-stage match, an ADR with rationale, and a
|
||||
measurement contract.
|
||||
|
||||
\begin{center}
|
||||
\small
|
||||
\begin{tabular}{@{}p{1.0cm}p{6.4cm}p{7.0cm}@{}}
|
||||
\toprule
|
||||
\textbf{Week} & \textbf{Lecture (script)} & \textbf{Project work} \\
|
||||
\midrule
|
||||
1 & Part I: decision problem, framework & Kickoff: teams, tooling, domain model, ontology draft \\
|
||||
2 & Part I: twelve dimensions; scenarios, utility tree & Quality attribute scenarios with response measures \\
|
||||
3 & Part I: capability profiles, fit, mini-match, ADR & $R(\mathrm{platform})$ finalised $\rightarrow$ \textbf{Deliverable A1} \\
|
||||
4 & Part II: layered, modular monolith, hexagonal & Architecture study I (Fineract, Cosmic Python) \\
|
||||
5 & Part II: microservices, event-driven & Architecture study II: edges, contracts, resilience \\
|
||||
6 & Part II: pipes-and-filters, serverless; stepping back; class C10 & The match: three stages, decision, ADR draft \\
|
||||
7 & Part IV: three cases, procedure, matrix; measurement contract & Solution design, design-review gate $\rightarrow$ \textbf{Deliverable A2} \\
|
||||
8 & Part III: classes C1--C5 & Walking skeleton (start) \\
|
||||
9 & Part III: classes C6--C9 & \textbf{Walking skeleton runs end-to-end} \\
|
||||
10 & Part IV: hybrids, evolution, eight-step procedure & Deterministic services + exact tests \\
|
||||
11 & Part IV: measurement contract in depth (fitness functions, DORA) & Resilience complete; \textbf{core fully tested} \\
|
||||
12 & Part V: Axis A; Axis B (gateway, eval basics) & Advisor + sub-agents behind the gateway \\
|
||||
13 & Part V: Axis B (security, orchestration economics) & \textbf{Eval harness in CI}; hardening; distinction work \\
|
||||
14 & Synthesis & \textbf{Presentations and architecture defence} \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\begin{taskbox}[M1 --- Requirements and Ontology (Weeks 1--3) --- Deliverable A1]
|
||||
\begin{itemize}[nosep]
|
||||
\item Domain model and ontology of the investment domain.
|
||||
\item Quality attribute scenarios with response measures; utility tree; the requirements
|
||||
profile $R(\mathrm{platform})$ with weights, workload shape, and hard constraints.
|
||||
\item Project and tooling setup (repository, environment, agentic dev tools).
|
||||
\item \textbf{Deliverable A1 (end of week 3): requirements dossier.}
|
||||
\end{itemize}
|
||||
\end{taskbox}
|
||||
|
||||
\begin{taskbox}[M2 --- Architecture Decision and Solution Design (Weeks 4--7) --- Deliverable A2]
|
||||
\begin{itemize}[nosep]
|
||||
\item Study the open-source reference systems from the lecture; evaluate candidate
|
||||
architectures for the deterministic core and the edges.
|
||||
\item Run the three-stage match (knock-out and shape gate; veto with documented
|
||||
mitigations; ordinal reading); record the decision as an ADR with rationale;
|
||||
C4-style diagram.
|
||||
\item Bounded contexts $\rightarrow$ service decomposition and contracts; measurement
|
||||
contract (token budget, eval threshold, module-boundary checks); walking-skeleton
|
||||
plan.
|
||||
\item \textbf{Deliverable A2 (end of week 7): architecture dossier + design-review
|
||||
gate.} Production code starts only after the gate (exploratory spikes are allowed).
|
||||
\end{itemize}
|
||||
\end{taskbox}
|
||||
|
||||
\begin{taskbox}[M3 --- Walking Skeleton (Weeks 8--9)]
|
||||
\begin{itemize}[nosep]
|
||||
\item End-to-end thin slice running: \texttt{MarketDataService} delivers prices and a
|
||||
\emph{minimal} \texttt{ResearchAgent} produces one validated \texttt{Insight}.
|
||||
\item Stable API and a placeholder UI that calls it.
|
||||
\end{itemize}
|
||||
\end{taskbox}
|
||||
|
||||
\begin{taskbox}[M4 --- Deterministic Core and Resilience (Weeks 10--11)]
|
||||
\begin{itemize}[nosep]
|
||||
\item \texttt{Performance}, \texttt{Risk}, \texttt{Optimization} services implemented and
|
||||
fully tested against the reference vectors.
|
||||
\item Resilience patterns on all external calls; graceful degradation verified.
|
||||
\end{itemize}
|
||||
\end{taskbox}
|
||||
|
||||
\begin{taskbox}[M5 --- Multi-Agent Orchestration, Evaluation, and Hardening (Weeks 12--13)]
|
||||
\begin{itemize}[nosep]
|
||||
\item Week 12: advisor orchestrates 2--3 sub-agents through contracts (mandatory);
|
||||
ontology guard active on all insights.
|
||||
\item Week 13: evaluation harness as a CI gate; report accuracy and failure modes;
|
||||
observability of token cost and latency per request.
|
||||
\item Threat model including prompt injection via news; basic hardening;
|
||||
scaling/optimisation (caching, batching).
|
||||
\item Optional Distinction work: autonomy, self-repair, model routing, CI/CD, tracing.
|
||||
\end{itemize}
|
||||
\end{taskbox}
|
||||
|
||||
\begin{taskbox}[M6 --- Presentation and Architecture Defence (Week 14)]
|
||||
\begin{itemize}[nosep]
|
||||
\item Present the system and \textbf{defend your architectural trade-offs}.
|
||||
\item Reflect on where AI helped and where it hurt --- in building (A) and in the system (B).
|
||||
\end{itemize}
|
||||
\end{taskbox}
|
||||
|
||||
\begin{hintbox}
|
||||
\begin{itemize}[nosep]
|
||||
\item Build the Walking Skeleton first thing in the implementation phase (M3, weeks
|
||||
8--9) --- a thin end-to-end slice de-risks everything that follows.
|
||||
\item Use the design phase fully: a decided architecture with contracts and a
|
||||
measurement contract makes the seven implementation weeks sufficient; an undecided
|
||||
one does not.
|
||||
\item Pin the deterministic services with tests \emph{before} you trust any agent output.
|
||||
\item Keep the deterministic core free of LLM calls --- this is the line that is graded.
|
||||
\item Use a snapshot of market/news data so your demo and grading are reproducible even if
|
||||
the live APIs misbehave.
|
||||
\item Commit after each milestone; record architectural decisions as ADRs as you go.
|
||||
\end{itemize}
|
||||
\end{hintbox}
|
||||
|
||||
%====================================================================
|
||||
\section{Assessment of the Project}
|
||||
|
||||
The project counts \textbf{50\,\%} of the module grade --- including the requirements dossier
|
||||
(deliverable A1), the architecture dossier with ADR and measurement contract (deliverable A2),
|
||||
the implementation, and the final presentation with architecture defence. The remaining
|
||||
50\,\% is the written module examination (60 minutes, open book, closed internet).
|
||||
Evaluation of the project emphasises:
|
||||
\begin{itemize}[nosep]
|
||||
\item \textbf{Architecture \& trade-offs} --- quality of decomposition, contracts,
|
||||
deterministic/non-deterministic separation, ADRs.
|
||||
\item \textbf{Robustness} --- resilience, guards, graceful degradation.
|
||||
\item \textbf{Quality} --- tests for deterministic services, eval harness for AI.
|
||||
\item \textbf{AI integration} --- correct anti-corruption layering and ontology guarding.
|
||||
\item \textbf{Operation} --- observability of cost/latency.
|
||||
\item Distinction criteria for top marks (see Section~6).
|
||||
\end{itemize}
|
||||
|
||||
\vfill
|
||||
\begin{center}\small
|
||||
Fachhochschule Graub\"unden $\cdot$ Pulverm\"uhlestrasse 57 $\cdot$ 7000 Chur\\
|
||||
\url{https://fhgr.ch/cds}
|
||||
\end{center}
|
||||
|
||||
\end{document}
|
||||
BIN
semesterinformation_HS26_AISE502_AIinSE2.xlsx
Normal file
BIN
skript/AISE502_Vorlesung_Skript.pdf
Normal file
181
skript/AISE502_Vorlesung_Skript.tex
Normal file
@ -0,0 +1,181 @@
|
||||
\documentclass[12pt,a4paper]{article}
|
||||
|
||||
% ============================================
|
||||
% PACKAGES
|
||||
% ============================================
|
||||
\usepackage[utf8]{inputenc}
|
||||
\usepackage[T1]{fontenc}
|
||||
\usepackage[english]{babel}
|
||||
\usepackage{geometry}
|
||||
\geometry{margin=2.5cm, headheight=14.5pt, footskip=1.8cm}
|
||||
\usepackage{graphicx}
|
||||
\usepackage{hyperref}
|
||||
\usepackage{xurl} % allow URLs to break anywhere (fixes overfull bibliography lines)
|
||||
\usepackage{xcolor}
|
||||
\usepackage{listings}
|
||||
\usepackage{booktabs}
|
||||
\usepackage{longtable}
|
||||
\usepackage{enumitem}
|
||||
\usepackage{fancyhdr}
|
||||
\usepackage{titlesec}
|
||||
\usepackage{tcolorbox}
|
||||
\usepackage{amsmath}
|
||||
\usepackage{amssymb}
|
||||
\usepackage{parskip}
|
||||
\usepackage{tikz}
|
||||
\usetikzlibrary{shapes.geometric, arrows.meta, positioning, fit, backgrounds, calc, decorations.pathreplacing}
|
||||
\usepackage{float}
|
||||
\usepackage{rotating}
|
||||
\usepackage[round,authoryear]{natbib}
|
||||
\bibliographystyle{plainnat}
|
||||
|
||||
% ============================================
|
||||
% COLORS
|
||||
% ============================================
|
||||
\definecolor{bankblue}{rgb}{0.0,0.28,0.67}
|
||||
\definecolor{bankgreen}{rgb}{0.13,0.55,0.13}
|
||||
\definecolor{bankred}{rgb}{0.7,0.13,0.13}
|
||||
\definecolor{aiviolet}{rgb}{0.42,0.19,0.58}
|
||||
\definecolor{projteal}{rgb}{0.0,0.45,0.45}
|
||||
\definecolor{backcolour}{rgb}{0.95,0.95,0.92}
|
||||
\definecolor{codegray}{rgb}{0.5,0.5,0.5}
|
||||
|
||||
% ============================================
|
||||
% CODE LISTING STYLE
|
||||
% ============================================
|
||||
\lstdefinestyle{pythonstyle}{
|
||||
backgroundcolor=\color{backcolour},
|
||||
commentstyle=\color{bankgreen},
|
||||
keywordstyle=\color{blue},
|
||||
numberstyle=\tiny\color{codegray},
|
||||
stringstyle=\color{bankred},
|
||||
basicstyle=\ttfamily\footnotesize,
|
||||
breakatwhitespace=false,
|
||||
breaklines=true,
|
||||
captionpos=b,
|
||||
keepspaces=true,
|
||||
numbers=left,
|
||||
numbersep=5pt,
|
||||
showspaces=false,
|
||||
showstringspaces=false,
|
||||
showtabs=false,
|
||||
tabsize=4,
|
||||
language=Python
|
||||
}
|
||||
\lstset{style=pythonstyle}
|
||||
|
||||
% ============================================
|
||||
% CUSTOM ENVIRONMENTS
|
||||
% ============================================
|
||||
\newtcolorbox{keypoint}{
|
||||
colback=blue!5!white,
|
||||
colframe=bankblue,
|
||||
title=Key Concept
|
||||
}
|
||||
|
||||
\newtcolorbox{examplebox}[1][]{
|
||||
colback=green!5!white,
|
||||
colframe=bankgreen,
|
||||
title={Example: #1}
|
||||
}
|
||||
|
||||
\newtcolorbox{definitionbox}[1][]{
|
||||
colback=yellow!5!white,
|
||||
colframe=yellow!50!black,
|
||||
title={Definition: #1}
|
||||
}
|
||||
|
||||
\newtcolorbox{thinkbox}{
|
||||
colback=orange!5!white,
|
||||
colframe=orange!60!black,
|
||||
title=Discussion
|
||||
}
|
||||
|
||||
\newtcolorbox{hinweisbox}{
|
||||
colback=red!5!white,
|
||||
colframe=bankred,
|
||||
title=Important Note
|
||||
}
|
||||
|
||||
\newtcolorbox{ailinse}[1][]{
|
||||
colback=violet!5!white,
|
||||
colframe=aiviolet,
|
||||
title={AI Lens: #1}
|
||||
}
|
||||
|
||||
\newtcolorbox{projektbox}{
|
||||
colback=teal!5!white,
|
||||
colframe=projteal,
|
||||
title=Project Link: Portfolio Intelligence Platform
|
||||
}
|
||||
|
||||
% ============================================
|
||||
% HEADER/FOOTER
|
||||
% ============================================
|
||||
\pagestyle{fancy}
|
||||
\fancyhf{}
|
||||
\fancyhead[L]{AISE502 -- AI in Software Engineering II}
|
||||
\fancyhead[R]{Lecture Notes}
|
||||
\fancyfoot[L]{\thepage}
|
||||
\fancyfoot[R]{\includegraphics[height=0.9cm]{FHGR_Logo_small}}
|
||||
|
||||
% ============================================
|
||||
% DOCUMENT
|
||||
% ============================================
|
||||
\begin{document}
|
||||
|
||||
|
||||
% ============================================
|
||||
% TITLE PAGE
|
||||
% ============================================
|
||||
\begin{titlepage}
|
||||
\centering
|
||||
\vspace*{1cm}
|
||||
|
||||
\includegraphics[width=0.5\textwidth]{FHGR_Logo_Large}\\[1.5cm]
|
||||
|
||||
{\Huge\bfseries AISE502: AI in Software\\Engineering II\par}
|
||||
\vspace{1.5cm}
|
||||
|
||||
{\Large Lecture Notes\par}
|
||||
\vspace{0.5cm}
|
||||
{\large Core Part: A Theory of Architecture--Application Fit\par}
|
||||
\vspace{1cm}
|
||||
|
||||
{\large Dr.\ Florian Herzog\par}
|
||||
\vspace{0.3cm}
|
||||
{\large University of Applied Sciences of the Grisons (FH Graub\"unden), Chur\par}
|
||||
\vspace{0.5cm}
|
||||
{\large Autumn Semester 2026\par}
|
||||
|
||||
\vfill
|
||||
|
||||
\begin{abstract}
|
||||
These lecture notes form the core of the module AISE502 \emph{AI in Software Engineering II}. They develop a coherent theory of \emph{architecture--application fit}: software architecture is understood as the set of significant, hard-to-reverse decisions, driven by measurable quality attributes, made by systematically matching application requirements profiles against pattern capability profiles, and validated empirically over the entire software lifecycle. \textbf{Part~I} lays the conceptual and methodological foundations: architecture as a decision problem, quality attributes as architectural drivers, measurable quality attribute scenarios, and Architecture Decision Records. \textbf{Part~II} catalogues seven central architectural patterns -- from the layered architecture, the modular monolith and microservices to event-driven, pipeline and serverless architectures -- as capability profiles with their software engineering implications. \textbf{Part~III} characterises ten application classes -- from core banking systems, social media platforms and simulations to the AI-native advisory platform -- as weighted requirements profiles. \textbf{Part~IV} brings both sides together: the fit matrix, the step-by-step decision procedure (utility tree, trade-off analysis, ADR) and the continuous measurement of the decision in operation (fitness functions, DORA metrics, evolution paths). \textbf{Part~V} extends the theory along the AI dimension: AI as a tool in the software lifecycle (Axis~A) and AI as a non-deterministic system component (Axis~B) -- showing that both roles demand the same engineering discipline.
|
||||
|
||||
The methodology applied throughout rests on four principal sources, gratefully acknowledged here: the quality attribute scenarios, architectural tactics, and utility-tree/ATAM decision apparatus of the Software Engineering Institute, as consolidated by \citet{bass2021software}; the architecture-characteristics ratings and trade-off laws of \citet{richards2025fundamentals}; the architectural fitness functions of \citet{ford2022evolutionary}, which turn every decision into a measurable contract; and the empirical delivery-performance research of the DORA programme \citep{forsgren2018accelerate}. The quality vocabulary of the profile dimensions is anchored in ISO/IEC 25010:2023 \citep{iso2023product}.
|
||||
\end{abstract}
|
||||
|
||||
\vspace{1cm}
|
||||
\end{titlepage}
|
||||
|
||||
% ============================================
|
||||
% TABLE OF CONTENTS
|
||||
% ============================================
|
||||
\tableofcontents
|
||||
\newpage
|
||||
|
||||
\input{chapters/part1_architecture_decisions}
|
||||
|
||||
\input{chapters/part2_patterns}
|
||||
|
||||
\input{chapters/part3_application_classes}
|
||||
|
||||
\input{chapters/part4_fit}
|
||||
|
||||
\input{chapters/part5_ai_dimension}
|
||||
|
||||
\newpage
|
||||
\bibliography{references}
|
||||
|
||||
\end{document}
|
||||
BIN
skript/FHGR_Logo_Large.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
skript/FHGR_Logo_small.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
58
skript/STYLE_GUIDE.md
Normal file
@ -0,0 +1,58 @@
|
||||
# Style Guide for AISE502 Lecture Notes Chapters (LaTeX)
|
||||
|
||||
> Durable copy — lives in the project so it survives sessions. The LaTeX chapters
|
||||
> themselves are the NORMATIVE source for all theory content (ratings, weights,
|
||||
> matrix cells); the original master-theory scratchpad file no longer exists.
|
||||
|
||||
## Project structure
|
||||
|
||||
- Main file: `AISE502_Vorlesung_Skript.tex` (it `\input`s the chapters)
|
||||
- Chapters: `chapters/part1_architecture_decisions.tex` … `chapters/part5_ai_dimension.tex`
|
||||
- Bibliography: `references.bib` (natbib, plainnat, authoryear)
|
||||
- Compiler: pdflatex + bibtex. No biber, no lualatex, no minted, no svg. `xurl` is loaded (URLs may break anywhere).
|
||||
|
||||
## Chapter files
|
||||
|
||||
Each chapter file starts with `\part{...}` and `\label{part:...}`, then `\section`, `\subsection`, `\subsubsection`. NO `\documentclass`, NO preamble, NO `\begin{document}` — files are included via `\input`. Comment separators:
|
||||
```latex
|
||||
% ============================================
|
||||
% SECTION: TITLE
|
||||
% ============================================
|
||||
```
|
||||
|
||||
## Language and register
|
||||
|
||||
- **British English**, academic textbook register, for 5th-semester bachelor students (Python-first; know Git, basic SE, basic ML; have never operated a production system).
|
||||
- Didactic rhythm (established in Parts I/II): plain leading question in italics before each pattern/major section; plain-language reasoning first, citation after; every jargon term glossed at first use; concrete anchors from systems students know.
|
||||
- The six A1–A6 statements are called **assumptions** ("six load-bearing assumptions"), NOT axioms. "Domain axioms" (ontology invariants) is a distinct, correct term.
|
||||
- En-dash style: ` -- `. Quotation marks: LaTeX ``...''.
|
||||
|
||||
## Environments (tcolorbox)
|
||||
|
||||
```latex
|
||||
\begin{keypoint} ... \end{keypoint} % Key Concept (blue), >=1 per section; maxims live here
|
||||
\begin{definitionbox}[Term] ... \end{definitionbox} % formal definitions (yellow)
|
||||
\begin{examplebox}[Title] ... \end{examplebox} % worked examples (green); also "Build it and study it" blocks in Part II
|
||||
\begin{thinkbox} ... \end{thinkbox} % discussion questions (orange)
|
||||
\begin{hinweisbox} ... \end{hinweisbox} % warnings/caveats (red, "Important Note")
|
||||
\begin{ailinse}[Title] ... \end{ailinse} % AI lens, Axis A or B (violet)
|
||||
\begin{projektbox} ... \end{projektbox} % course-project link (teal)
|
||||
```
|
||||
Box titles must not contain unbraced commas (pgfkeys); the preamble braces `title={...: #1}` already.
|
||||
|
||||
## Tables and figures
|
||||
|
||||
booktabs, no vertical rules; `\caption` + `\label` everywhere; ratings in math mode: `$++$/$+$/$\circ$/$-$/$--$`; very wide tables in `sidewaystable`. TikZ style: rounded rectangles, `\small\sffamily`, fills `!15`/`!20`, Stealth arrows; colours `bankblue`, `bankgreen`, `bankred`, `aiviolet`, `projteal`.
|
||||
|
||||
## Citations and labels
|
||||
|
||||
natbib `\citep`/`\citet`, keys must exist in `references.bib` — never invent keys. Canonical cross-chapter labels (do not rename): `part:foundations`, `part:patterns`, `part:applications`, `part:fit`, `part:ai`, `tab:dimensions`, `tab:capability`, `tab:requirements`, `tab:fitmatrix`, `lst:adr`. Part-I didactic tables: `tab:weightexamples`, `tab:patternpreview`, `tab:capexamples`, `tab:minimatch`. Part-II OSS catalogue: `tab:osscatalog`.
|
||||
|
||||
## Content invariants (normative, verified against the research base)
|
||||
|
||||
- 7 patterns: L, MM, HX (delta pattern), MS, EDA, PF, SL; agent orchestration as emergent composition pattern (Part V).
|
||||
- 10 application classes C1–C10; C10 = AI-native advisory platform (course project).
|
||||
- 12 profile dimensions D1–D12 (Table 2); D12 = AI integrability ("queue, port, measurement point").
|
||||
- Fit = three-stage non-compensatory procedure (knock-out/shape gate → veto on High weights with documented mitigations → holistic ordinal reading + sensitivity analysis). Never a weighted sum.
|
||||
- Matrix verdicts (examples): C10 row L=−, MM=++, HX=++, MS=○; C3 row L=+, MM=++, MS=−−.
|
||||
- Capability table has 21 footnotes; requirements table has 17; do not alter ratings without documented evidence.
|
||||
827
skript/chapters/part1_architecture_decisions.tex
Normal file
@ -0,0 +1,827 @@
|
||||
\part{Architecture as a Decision Problem}
|
||||
\label{part:foundations}
|
||||
|
||||
% ============================================
|
||||
% SECTION: THE DECISION PROBLEM
|
||||
% ============================================
|
||||
\section{The Decision Problem}
|
||||
\label{sec:decisionproblem}
|
||||
|
||||
This module answers one question: \emph{How do I design, justify, and operate the structure of a software system so that it meets its quality attributes and remains maintainable for years -- even when individual components (AI) are non-deterministic, fallible, and expensive?} This part builds the framework in which that question becomes decidable: a demand side, a supply side, a matching rule, a decision record, and a measurement contract. Before we build, two facts from production establish why a framework is needed at all.
|
||||
|
||||
\subsection{Two facts from production}
|
||||
\label{subsec:fourcases}
|
||||
|
||||
Table~\ref{tab:fourcases} summarises four production systems, each publicly described by its own engineers.
|
||||
|
||||
\begin{table}[htbp]
|
||||
\centering
|
||||
\caption{Four documented production systems establishing the two facts that create the decision problem: radically different structures succeed on comparable problems, and no structure dominates.}
|
||||
\label{tab:fourcases}
|
||||
\footnotesize
|
||||
\begin{tabular}{@{}p{2.3cm}p{4.6cm}p{7.2cm}@{}}
|
||||
\toprule
|
||||
\textbf{System} & \textbf{Structure} & \textbf{Documented outcome} \\
|
||||
\midrule
|
||||
Stack Overflow & \texttt{.NET} monolith on roughly nine on-premise web servers & $\sim 1.3$ billion page views per month at $\sim 12$\,ms render times -- scaled \emph{up}, not \emph{out} \citep{craver2016stackoverflow, milanovic2023stackoverflow} \\
|
||||
Monzo & $\sim 2{,}800$ Go microservices; one language, one monorepo, central migration automation & retail banking at scale -- viable through extreme technological homogeneity \citep{sewell2024monzo} \\
|
||||
Segment & $> 140$ microservices, one per analytics destination & public 2018 rollback to a monolith: operational and test complexity crushed a small team \citep{noonan2018goodbye, infoq2020segment} \\
|
||||
Prime Video & serverless orchestration: Step Functions, Lambda, S3 buffers & consolidation into a single process cut infrastructure cost by $> 90\,\%$; hard scaling limit at $\sim 5\,\%$ of expected load \citep{kolny2023primevideo, cockcroft2023prime} \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
Two facts follow. \textbf{First, structures differ radically for similar-looking problems}: Monzo and Stack Overflow both serve millions of users interactively at high availability -- one with thousands of deployment units, the other with essentially one. \textbf{Second, no structure dominates}: for every pattern there is a documented context in which it failed expensively (Segment, Prime Video) and one in which its unfashionable opposite succeeded at scale (Stack Overflow; Instagram \citep{woodruff2019static}; Shopify \citep{westeinde2019deconstructing}). Neither fact proves monoliths good or microservices bad. Prime Video's failure was a mismatch between a data-intensive, tightly coupled processing flow and an architecture that put expensive distributed boundaries in the middle of it \citep{kolny2023primevideo, cockcroft2023prime}; Segment's was a service cut along \emph{instances of configuration} rather than domain seams \citep{noonan2018goodbye, newman2021building}. The value of an architectural pattern is not a property of the pattern; it is a property of the \emph{match} between the pattern and the application it serves.
|
||||
|
||||
\begin{keypoint}
|
||||
\textbf{Maxim 1.} Patterns are neither good nor bad; only the fit between a requirements profile and a capability profile is.
|
||||
\end{keypoint}
|
||||
|
||||
That is the decision problem: given an application, choose among non-dominated structural alternatives whose value depends on the match -- knowing that the choice will be expensive to reverse.
|
||||
|
||||
\subsection{What architecture addresses}
|
||||
\label{subsec:whatis}
|
||||
|
||||
``Software architecture'' has a documented tendency to mean everything and therefore nothing \citep{fowler2003who}. Four definition families, complementary rather than competing, pin the term down; each contributes one load-bearing element to the framework.
|
||||
|
||||
\begin{definitionbox}[Software architecture (ISO/IEC/IEEE 42010:2022)]
|
||||
Architecture: ``fundamental concepts or properties of an entity in its environment and governing principles for the realization and evolution of this entity and its related life cycle processes'' \citep{iso2022architecture}.
|
||||
\end{definitionbox}
|
||||
|
||||
The \textbf{normative} definition (ISO) supplies the shared vocabulary -- \emph{stakeholders}, \emph{concerns}, \emph{viewpoints}, \emph{views} -- and one obligation this framework builds on directly: recording architecture decisions \emph{and their rationale} is mandatory for a conformant architecture description (Clause~6.10) \citep{iso2022architecture, iso2011architecture, ieee2000recommended}. The \textbf{decision-centric} definition (Booch) supplies the significance criterion: ``architecture represents the significant design decisions that shape a system, where significant is measured by cost of change'' \citep[p.~214]{buschmann2007pattern}; Jansen and Bosch radicalise it -- architecture \emph{is} a composition of design decisions, and the loss of decision knowledge (\emph{knowledge vaporization}) is a principal cause of erosion \citep{jansen2005software}. The \textbf{social} definition (Fowler/Johnson) -- the expert developers' shared understanding, ``the important stuff -- whatever that is'' -- adds that perceived irreversibility is the core of the matter and that a chief task of architects is to \emph{remove} it \citep{fowler2003who}. The \textbf{structural-analytic} definition (SEI) -- ``the set of structures needed to reason about the system'' \citep{bass2021software, perry1992foundations, shaw1996software} -- carries the observation on which everything here turns: \emph{functionality is largely structure-neutral; quality attributes are not}; what the structure determines is \emph{how well} \citep{bass2021software, sommerville2020modernes}.
|
||||
|
||||
Distilled into one sentence: \emph{architecture is the set of hard-to-reverse structural decisions that determine the quality behaviour of a system.}
|
||||
|
||||
The cost-of-change criterion also settles the boundary towards design and implementation. Choosing between a modular monolith and microservices is architectural: reversing it is a migration measured in months. Choosing a logging library is design, revisable in days behind a stable interface; choosing a variable name is implementation, revisable in seconds. The boundary is gradual and context-dependent -- a database choice is architectural in a system without a persistence abstraction, closer to design in a hexagonal one -- and that is the point: good architecture actively pushes decisions from irreversible towards reversible \citep{fowler2003who}. (Scope note: this module operates at solution level, not at the enterprise level of TOGAF's ADM \citep{opengroup2022togaf}; enterprise mandates enter only as constraints in the requirements profile.)
|
||||
|
||||
Two refusals follow, and the framework enforces both. It refuses \emph{fashion}: the dominance claim behind every hype cycle is falsified by Table~\ref{tab:fourcases}. And it refuses \emph{taste}: a claim that cannot be measured or falsified has no place in an architectural decision.
|
||||
|
||||
\subsection{The framework at a glance}
|
||||
\label{subsec:framework}
|
||||
|
||||
Instead of arguing towards the framework, we state it up front and spend the rest of this part constructing it.
|
||||
|
||||
\begin{definitionbox}[The five elements of architecture--application fit]
|
||||
Let $A$ be a set of application classes and $P$ a set of architectural patterns. The framework of this script consists of five elements:
|
||||
\begin{enumerate}
|
||||
\item the \textbf{requirements profile} $R(a) = \bigl(w_1(a), \dots, w_{12}(a);\; S(a);\; K(a)\bigr)$ of a class $a \in A$: priority weights $w_i(a) \in \{\text{High}, \text{Medium}, \text{Low}\}$, a dominant workload shape $S(a)$, hard constraints $K(a)$ -- the \emph{demand side} (Section~\ref{sec:demand});
|
||||
\item the \textbf{capability profile} $C(p) = \bigl(c_1(p), \dots, c_{12}(p);\; S(p)\bigr)$ of a pattern $p \in P$: ordinal ratings $c_i(p) \in \{++, +, \circ, -, --\}$ plus the pattern's native workload shape $S(p)$ -- the \emph{supply side} (Section~\ref{sec:supply});
|
||||
\item the \textbf{architecture--application fit} $\mathrm{fit}(a,p)$: an ordinal, non-compensatory match of the two profiles, computed by rules, not arithmetic (Section~\ref{sec:fit});
|
||||
\item the \textbf{Architecture Decision Record (ADR)}: the permanent, auditable record of the decision and its rationale (Section~\ref{sec:adr});
|
||||
\item the \textbf{measurement contract}: the fitness functions and thresholds under which the decision is continuously tested in operation (Section~\ref{sec:adr}; in full in Part~\ref{part:fit}).
|
||||
\end{enumerate}
|
||||
Both profiles are defined over the twelve dimensions of Table~\ref{tab:dimensions} (Section~\ref{sec:dimensions}).
|
||||
\end{definitionbox}
|
||||
|
||||
Figure~\ref{fig:pipeline} is the map -- of the framework and of the script. This part constructs each element once, by hand; the remaining parts instantiate them at scale: Part~\ref{part:patterns} derives $C(p)$ for seven patterns (Table~\ref{tab:capability}), Part~\ref{part:applications} derives $R(a)$ for ten application classes (Table~\ref{tab:requirements}), Part~\ref{part:fit} computes $\mathrm{fit}(a,p)$ for all seventy pairs and supplies the decision procedure and the measurement apparatus, and Part~\ref{part:ai} extends the space by AI on both of the module's axes.
|
||||
|
||||
\begin{figure}[htbp]
|
||||
\centering
|
||||
\begin{tikzpicture}[
|
||||
node distance=0.9cm and 1.0cm,
|
||||
sysbox/.style={rectangle, draw, rounded corners=4pt, text width=3.2cm, minimum height=1.3cm, align=center, font=\small\sffamily, line width=0.8pt},
|
||||
core/.style={sysbox, fill=bankblue!20, draw=bankblue},
|
||||
comp/.style={sysbox, fill=bankgreen!15, draw=bankgreen},
|
||||
meas/.style={sysbox, fill=violet!15, draw=aiviolet},
|
||||
arr/.style={-{Stealth[length=2.5mm]}, thick, gray!60!black},
|
||||
farr/.style={-{Stealth[length=2.5mm]}, thick, dashed, bankred}
|
||||
]
|
||||
\node[core] (klass) {Application class\\ \scriptsize (Part~\ref{part:applications})};
|
||||
\node[core, right=0.9cm of klass] (profil) {Requirements profile $R(a)$\\ \scriptsize scenarios, utility tree};
|
||||
\node[core, right=0.9cm of profil] (match) {Matching $\mathrm{fit}(a,p)$\\ \scriptsize against $C(p)$ (Parts~\ref{part:patterns}, \ref{part:fit})};
|
||||
\node[comp, below=1.4cm of match] (adr) {Architecture decision\\ \scriptsize ADR with rationale};
|
||||
\node[meas, left=0.9cm of adr] (fitness) {Measurement contract\\ \scriptsize fitness functions in CI/CD};
|
||||
\node[meas, left=0.9cm of fitness] (ops) {Operation\\ \scriptsize DORA, SLOs, Lehman trends};
|
||||
\draw[arr] (klass) -- (profil);
|
||||
\draw[arr] (profil) -- (match);
|
||||
\draw[arr] (match) -- (adr);
|
||||
\draw[arr] (adr) -- (fitness);
|
||||
\draw[arr] (fitness) -- (ops);
|
||||
\draw[farr] (ops.north) -- node[midway, right=2pt, font=\scriptsize\sffamily, text=bankred, align=left] {profile drift (A5):\\ re-measure, evolve, supersede} (klass.south);
|
||||
\end{tikzpicture}%
|
||||
\caption{The framework as a pipeline -- and the map of this script. Demand is matched against supply; the match ends in a recorded decision with a measurement contract, and operation continuously tests whether the decision's promises hold. The dashed feedback edge is not decoration -- it is assumption A5.}
|
||||
\label{fig:pipeline}
|
||||
\end{figure}
|
||||
|
||||
\begin{ailinse}[The two AI axes of this module]
|
||||
AI enters this module twice. On \textbf{Axis~A}, AI is a \emph{tool in the development process}: assistants and agents generate code, tests, and documentation -- changing \emph{how} we make and guard architectural decisions. On \textbf{Axis~B}, AI is a \emph{runtime component of the system itself}: an LLM, an ML model, or an optimiser inside the architecture, bringing non-determinism, seconds-scale latency, and per-call cost -- changing \emph{what} we must decide about. Both are treated systematically in Part~\ref{part:ai}; boxes like this one flag where each axis touches the classical material.
|
||||
\end{ailinse}
|
||||
|
||||
\subsection{Six load-bearing assumptions}
|
||||
\label{sec:axioms}
|
||||
|
||||
The framework rests on six assumptions -- each anchored in established literature, each justifying one element of the framework.
|
||||
|
||||
\textbf{A1 -- Architecture is the set of significant, hard-to-reverse design decisions}, significance measured by cost of change \citep[p.~214]{buschmann2007pattern} -- Johnson's ``decisions you wish you could get right early'' \citep{fowler2003who}. A1 fixes the framework's \emph{object}: what we choose is a decision with high reversal cost, and what we must manage is decision knowledge, whose loss is a documented cause of erosion \citep{jansen2005software}. A1 justifies element~4: every decision the framework produces is recorded as an ADR \citep{nygard2011documenting}, fulfilling the ISO~42010 rationale obligation \citep{iso2022architecture}.
|
||||
|
||||
\textbf{A2 -- Everything in software architecture is a trade-off} -- and if you think you have found something that is not, you have not yet identified the trade-off. This is Richards and Ford's First Law of Software Architecture \citep{richards2025fundamentals}, empirically visible in their own star ratings: microservices lead the aggregate yet score one star on cost and simplicity; layered is the exact mirror -- five stars there, one star on deployability, elasticity, and scalability. Dominance -- one alternative at least as good everywhere and strictly better somewhere -- does not occur in the published profiles. A2 justifies element~3: because no dominant alternative exists, a \emph{matching problem} exists at all -- otherwise this script would be one page long. Corollary: any proposal that claims only benefits is incomplete \emph{by assumption}, and reviewers may demand its sensitivity and trade-off points in the ATAM sense \citep{kazman2000atam}.
|
||||
|
||||
\textbf{A3 -- Quality attributes, not functionality, drive architecture.} Functionality is largely structure-neutral; what the structure determines is \emph{how well} -- performance, availability, modifiability, security \citep{bass2021software}; architecture determines the non-functional properties, and these can rarely be refactored in afterwards \citep{sommerville2020modernes}. A3 justifies the coordinate system: the dimensions over which both profiles range (Section~\ref{sec:dimensions}) are quality attributes and workload/constraint characteristics, anchored in ISO/IEC 25010:2023 \citep{iso2023product} -- never feature lists, which under-determine architecture.
|
||||
|
||||
\textbf{A4 -- Requirements are architecturally usable only as measurable scenarios.} ``The system shall be scalable'' decides nothing and tests nothing; a quality attribute becomes decision-relevant only as a six-part scenario whose non-negotiable part is a \emph{response measure} with number and unit \citep{bass2021software}. Empirically, architecturally significant requirements are vague and implicit and must be systematically elicited \citep{chen2013characterizing}. A4 justifies the construction method of the demand side (Section~\ref{sec:demand}): every requirement in $R(a)$ is a scenario with a response measure, and the weights $w_i(a)$ are derived from the (High, High) leaves of a utility tree \citep{kazman2000atam, barbacci2003quality} -- not from opinion.
|
||||
|
||||
\textbf{A5 -- An architecture decision is a hypothesis, continuously tested over the life cycle.} Lehman's laws: a system embedded in the real world must continually change or become progressively less useful \citep{lehman1980laws, lehman1996laws}; maintenance and evolution consume roughly $40$--$80\,\%$ (typically $\sim 60\,\%$) of life-cycle cost \citep{glass2002facts}. Design-time fit therefore \emph{decays}, and the instruments to re-measure it exist: architectural fitness functions in the CI/CD pipeline \citep{ford2022evolutionary} and the four DORA metrics in delivery \citep{forsgren2018accelerate, dora2023sodr} -- with the strongest single finding in the field, ``loosely coupled architectures and teams are the strongest predictor of continuous delivery'' \citep{dora2017sodr}, and the caveat that DORA's evidence is survey-based, not experimentally causal. Boehm's classical $100\times$ cost-of-change escalation \citep{boehm1981economics, boehm2001top10} is empirically flattened for changes \emph{within} an architecture \citep{menzies2017delayed} but remains steep for changes \emph{of} it -- exactly what the Segment and Prime Video rollbacks were. A5 justifies element~5: every ADR ends with a measurement contract, and evolution paths stay open (Strangler Fig \citep{fowler2004strangler}).
|
||||
|
||||
\textbf{A6 -- AI components extend the quality attribute space but do not change the method.} Runtime AI components are non-deterministic, fallible, latency-heavy, priced per call, and subject to drift and vendor deprecation \citep{sculley2015hidden, amershi2019software, gama2014drift}; they stretch existing quality dimensions by orders of magnitude and add sub-attributes with no classical counterpart -- token cost per request, eval pass rate, prompt-injection resistance \citep{owasp2025llmtop10}. Crucially, ISO/IEC 25010:2023 already carries the vocabulary (\emph{Safety}, \emph{Flexibility/scalability}, \emph{Security/resistance}; Section~\ref{sec:dimensions}) \citep{iso2023product}. What does \emph{not} change is the method: scenarios with response measures, tactics, trade-off analysis, ADRs, fitness functions. A6 justifies how the framework treats AI: it is \emph{absorbed}, not special-cased -- one additional profile dimension (D12) and one additional test artefact class (the eval harness, Part~\ref{part:ai}), nothing else. This is the module's central intellectual bet, and Part~\ref{part:ai} is its defence.
|
||||
|
||||
\begin{keypoint}
|
||||
\textbf{Maxim 2.} Because everything is a trade-off (A2) and quality drives structure (A3), architecture selection is matching; because decisions are costly to reverse (A1) and decay over time (A5), the match must be documented and continuously measured.
|
||||
\end{keypoint}
|
||||
|
||||
% ============================================
|
||||
% SECTION: THE COORDINATE SYSTEM -- TWELVE PROFILE DIMENSIONS
|
||||
% ============================================
|
||||
\section{The Coordinate System: Twelve Profile Dimensions}
|
||||
\label{sec:dimensions}
|
||||
|
||||
The framework box in Section~\ref{subsec:framework} made a promise: demand and supply -- $R(a)$ and $C(p)$ -- would be described in one shared, measurable vocabulary, as vectors over the \emph{same} twelve dimensions. This section builds that coordinate system, and it builds it from the ground up: first the recurring questions that anyone responsible for a real system must answer (Section~\ref{subsec:questions}); then the twelve dimensions those questions become, introduced one by one in plain language (Section~\ref{subsec:dimtour}); then the criteria under which exactly these twelve -- and no others -- were admitted (Section~\ref{subsec:admission}); and finally the reference card, Table~\ref{tab:dimensions}, which condenses everything into the compact form the rest of the script uses (Section~\ref{subsec:dimtable}).
|
||||
|
||||
\subsection{From questions to dimensions}
|
||||
\label{subsec:questions}
|
||||
|
||||
Forget frameworks for a moment and imagine you are responsible -- personally, with your name on the on-call rota -- for a system that real people use. Questions of the following kind will find you, whether or not you have a vocabulary for them:
|
||||
|
||||
\begin{itemize}
|
||||
\item \emph{The university's grade-release portal: what happens at 08:00 on publication day, when the whole semester refreshes the same page at once?}
|
||||
\item \emph{An e-banking transfer: can the same payment ever be booked twice -- or disappear halfway?}
|
||||
\item \emph{One component crashes at noon: does the whole application go dark, or does one widget show a spinner while everything else keeps working?}
|
||||
\item \emph{The regulator calls: ``prove to us, step by step, what happened to this one transaction.'' How long does that take you?}
|
||||
\item \emph{A new feature request arrives: how many places in the code must change -- one module, or seventeen?}
|
||||
\item \emph{Two students must ship a working MVP (minimum viable product -- the smallest version of the product worth releasing) in one semester: does the structure let them, or does it demand a platform team they do not have?}
|
||||
\item \emph{The monthly cloud bill triples: which part of the structure is spending the money, and what was it doing at 03:00?}
|
||||
\item \emph{The team grows from three to thirty: do releases get faster -- or does everyone now wait for everyone else?}
|
||||
\item \emph{Product adds a feature whose core is an LLM call: it takes eight seconds, costs money on every single request, and is sometimes confidently wrong. Where does that live in the architecture?}
|
||||
\end{itemize}
|
||||
|
||||
Three observations turn this list from anecdote into method. First, the questions \emph{recur}: every one of them has ended budgets, products, or careers, and every one of them arises across wildly different systems -- the grade portal and Instagram share the first question, merely at different magnitudes. Second, none of them asks \emph{what} the system does: functionality is largely structure-neutral (A3); every question above is about \emph{how well}, \emph{at what cost}, \emph{under which failure}. Third -- and this is the step that makes a decision theory possible -- each question can be answered with a number: requests per second, double bookings per million transfers, per cent of functionality lost, hours to reconstruct an audit trail, modules touched per feature, weeks to first release, cost per request, deployments per developer per day, seconds and cents per LLM call.
|
||||
|
||||
Now recall what the framework needs. The match of Section~\ref{sec:fit} compares what an application \emph{demands} with what a structure \emph{delivers}. That comparison is only defined if both sides are described in the \emph{same} vocabulary, and it is only testable (A4) if that vocabulary is measurable. The twelve profile dimensions D1--D12 are exactly this: the recurring questions above -- grouped, named, and equipped with defined measures. Nothing more mysterious than that.
|
||||
|
||||
\subsection{The twelve dimensions, one by one}
|
||||
\label{subsec:dimtour}
|
||||
|
||||
The twelve dimensions fall into five thematic groups. Each dimension below follows the same rhythm: the question in plain language, what the dimension means, where it bites, and how it is measured -- with every term of art defined on first use, so that the reference card at the end of this section needs no prior knowledge.
|
||||
|
||||
\subsubsection{Load and speed (D1--D3)}
|
||||
|
||||
The first group asks whether the structure survives its own success: more users, more traffic, less patience.
|
||||
|
||||
\paragraph{D1 -- Read scalability.}
|
||||
\emph{What happens at 08:00 on grade-release day, when the whole semester refreshes at once?} Read scalability is the ability of a structure to serve a growing volume of \emph{read} requests -- requests that look at data without changing it. It matters because most interactive systems are read-dominated by orders of magnitude: for every student filing a grade appeal there are thousands checking a result, and for every Instagram post there are thousands of feed views. Reads have a friendly property: since they change nothing, they can be served from \emph{copies} -- replicated servers and \emph{caches}, a cache being a fast store that holds ready-made answers so they need not be recomputed. That is how Stack Overflow serves roughly $1.3$ billion page views a month from a handful of servers \citep{craver2016stackoverflow}, and how Instagram carried hundreds of millions of users on a deliberately conventional monolith \citep{woodruff2019static} -- in both cases the single write path, not the read traffic, is the hard part. Measured: \emph{throughput} (requests completed per second) as replicas are added -- does doubling the servers double the throughput? -- together with the \emph{cache hit ratio}, the share of requests answered from a cache rather than computed afresh; in production, so-called RED metrics track this per service (Rate, Errors, Duration: how many requests arrive, how many fail, how long they take). Patterns will differ here because some topologies make replicating and caching reads trivial, while others entangle reads with state they cannot easily copy.
|
||||
|
||||
\paragraph{D2 -- Write scalability and elasticity.}
|
||||
\emph{Black Friday: checkout traffic jumps to dozens of times the baseline for one weekend -- and is gone on Monday. Can the structure grow and shrink with the load?} Write scalability is the D1 question for requests that \emph{change} state -- and it is the harder half, because a write cannot be served from a copy: every order, payment, and booking must reach the one authoritative record, durably and in the right order. \emph{Elasticity} adds the time axis: how quickly capacity follows the load, upwards and back down again. The reference point of this script is Shopify's Black Friday/Cyber Monday weekend, with peaks around $280$ million requests per minute \citep{shopify2024bfcm}, carried by replicated ``pods'' of a monolith \citep{westeinde2019deconstructing}; the opposite end of the same dimension is \emph{scale-to-zero} -- a structure that costs nothing while nobody uses it, the core promise of serverless computing \citep{jonas2019berkeley}. Measured: the \emph{sustained ingest rate} (how much incoming write traffic per second the system durably absorbs -- ``ingest'' is simply intake), the \emph{time-to-capacity} after a load step (how many minutes pass between the spike and the capacity to serve it), and the cost of idling at zero. Patterns differ sharply: some can replicate their write path, while others funnel every write through one shared database that no number of additional servers relieves.
|
||||
|
||||
\paragraph{D3 -- Latency and predictability.}
|
||||
\emph{How long does one click take -- and how long does it take on a bad day?} \emph{Latency} is the time between a request and its response; \emph{predictability} says that the interesting quantity is not the average but the distribution. Averages lie: a system can average $120$\,ms while every twentieth request takes four seconds -- and precisely the most active users, who make the most requests, hit those slow ones most often. The field therefore reports \emph{percentiles}: p50 is the median response time, p95 the time the slowest $5\,\%$ of requests see, p99 the time the slowest $1\,\%$ see; the ratio p99/p50, the \emph{tail-latency ratio}, states how much worse a bad request is than a normal one. The stakes are documented: Amazon measured roughly $1\,\%$ of sales lost per additional $100$\,ms of latency \citep{linden2006data}, and Akamai's retail study found up to $7\,\%$ of conversions lost per $100$\,ms \citep{akamai2017retail}. One more term the reference card uses: a \emph{cold start} is the extra delay incurred when a request must first wake up the component that will serve it -- characteristic of scale-to-zero structures, and the price of their D2 virtue. Measured with \emph{distributed tracing}: instrumentation that follows one request across every component it touches and reports where the milliseconds went. Patterns differ because every network hop between components adds latency, and every on-demand start adds a cold start.
|
||||
|
||||
\subsubsection{Correctness and trust (D4--D6)}
|
||||
|
||||
The second group asks whether the system can be trusted -- with money, with uptime, with history.
|
||||
|
||||
\paragraph{D4 -- Consistency and transactional integrity.}
|
||||
\emph{An e-banking transfer: can the same payment ever be booked twice -- or vanish halfway?} This dimension asks whether concurrent access and partial failure can corrupt the data -- whether the system's numbers can silently stop being true. The classic failure is the \emph{lost update}: two processes read the same account balance, both compute a new one, and the second write overwrites the first -- money created or destroyed without any error message. The vocabulary: an \emph{invariant} is a rule that must hold at all times (``debit equals credit across every transfer'', ``no seat is sold twice''); \emph{transactional integrity} means that multi-step operations happen entirely or not at all; \emph{staleness} is how many seconds a copy of the data may lag behind the original -- tolerable for a follower count, intolerable for a ledger. Measured: the anomaly rate under concurrent load, the invariant-violation count (target: exactly zero for anything ledger-like), and the staleness bound; the instruments are \emph{Jepsen-style tests} -- harnesses that hammer a system with concurrent operations while deliberately injecting failures, then check whether the promised guarantees actually held \citep{kleppmann2017designing} -- and \emph{reconciliation jobs}, batch runs that compare two independent records of the same facts and flag every difference. Patterns differ fundamentally: a single database hands the developer transactions for free; every distribution boundary takes part of that away and obliges the developer to compensate by hand.
|
||||
|
||||
\paragraph{D5 -- Availability and fault isolation.}
|
||||
\emph{One component crashes at noon: does the whole app go dark, or does one widget show a spinner?} Availability is the share of time the system does its job; fault isolation is how much of the product dies when one part dies. The plain-language core of the reference card: the \emph{blast radius} of a component is the percentage of functionality lost when that component fails -- in a single-process system it is $100\,\%$ by construction; \emph{MTTR}, the mean time to recovery, is how long the damage lasts on average. Modern operations manage availability as an explicit contract: an \emph{SLO} (service level objective) is a stated target such as ``$99.9\,\%$ of requests succeed this month''; the \emph{error budget} is the tolerated remainder -- the $0.1\,\%$ the team may deliberately ``spend'' on risky releases and experiments; \emph{error-budget burn} is the rate at which incidents consume it. Measured: SLO attainment, burn rate, blast radius per component failure, and MTTR; the honest instrument is the \emph{chaos experiment} -- deliberately killing components under realistic load and measuring what users actually lose \citep{basiri2016chaos}. Run continuously in the delivery pipeline, such an automated, repeatable check of an architectural property is called a \emph{fitness function} \citep{ford2022evolutionary} -- a term the reference card and the rest of the script use constantly. Patterns trade along this dimension rather than winning it: distribution shrinks the blast radius and simultaneously multiplies the number of things that can fail.
|
||||
|
||||
\paragraph{D6 -- Security and auditability.}
|
||||
\emph{The regulator asks: prove what happened to this one transaction, end to end.} Keeping attackers out is necessary everywhere; what discriminates between \emph{structures} is auditability -- the ability to reconstruct history. An \emph{audit trail} is a complete, tamper-evident record of who changed what, when, and on whose authority; in supervised industries it is a legal duty, not a nice-to-have -- Swiss financial institutions must be able to demonstrate the integrity of their operational data to FINMA \citep{finma2023oprisk}, and payment systems live under PCI~DSS \citep{pcissc2022pcidss}. The associated cost term is the \emph{audit scope}: the portion of the system that auditors must examine -- structures that confine sensitive data flows to a small, well-bounded region shrink that scope, and with it the audit bill. Measured: the time to reconstruct a complete audit trail for one transaction (an \emph{audit drill}, run like a fire drill), and the percentage of state changes \emph{journaled} -- written to a permanent, append-only log at the moment they happen. Patterns differ by construction: some record every change as an event as their normal mode of operation; others must reassemble history from whatever scattered log files happen to exist.
|
||||
|
||||
\subsubsection{Change and delivery (D7--D9)}
|
||||
|
||||
The third group prices change: the next feature, the next release, the next hire.
|
||||
|
||||
\paragraph{D7 -- Evolvability and maintainability.}
|
||||
\emph{A feature request arrives: how many places in the code must change?} This dimension prices the \emph{next} change -- and over a lifetime dominated by evolution (A5), it quietly dominates most others. Its central measure has a name worth memorising: \emph{change dispersion}, the number of modules touched by an average feature -- one is excellent, seventeen is an architecture problem. The underlying variable is \emph{coupling}: the degree to which modules depend on each other, so that a change in one ripples into the next; classical metrics quantify it, for instance CBO (\emph{coupling between objects} -- how many other classes a class depends on) and Martin's \emph{instability} (roughly, the share of a module's couplings that point outward, so that changes elsewhere ripple in) \citep{chidamber1994metrics, martin2003agile}; CBO belongs to the Chidamber--Kemerer (CK) metric suite the reference card names. Measured: change dispersion over the version history, coupling metrics, and \emph{declared-boundary violations} -- cases where code bypasses the module boundaries the architecture declares, with a target of zero, enforceable by CI rules that fail the build on any forbidden dependency, using tools such as ArchUnit or Spring Modulith \citep{drotbohm2023modulith}. Patterns differ because each topology draws its boundaries somewhere -- and a feature that respects one pattern's seams cuts straight across another's.
|
||||
|
||||
\paragraph{D8 -- Simplicity and time-to-market.}
|
||||
\emph{Two students must ship a working MVP in one semester. Does the structure let them?} Simplicity measures how much machinery must exist, be understood, and be kept alive before the first unit of value reaches a user. The anchor is deliberately close to home: a two-person team with one semester. A structure that requires a container orchestrator (software that runs and coordinates fleets of services), a message broker (a dedicated middleman that relays messages between components), and a dozen repositories before ``hello, world'' has failed this dimension for that team -- however magnificently it would carry Shopify's Black Friday. Measured: the time from an empty repository to the first production release; the onboarding time until a new developer's first merged contribution; and the plain count of distinct runtime technologies that must be operated. This dimension is where A2 bites hardest: the structures that win D8 tend to concede D2 or D11, and vice versa -- which is why a small team's rational choice differs from a platform company's.
|
||||
|
||||
\paragraph{D9 -- Testability and deployability.}
|
||||
\emph{Can a developer know within seconds that a change is safe -- and release it this afternoon without coordinating with three other teams?} Two abilities, deliberately fused: fast, trustworthy verification and independent, low-risk release. The vocabulary: a \emph{hermetic test} runs entirely self-contained -- on the developer's machine or in CI, with no shared staging environment and no live external service -- which is what makes it fast and repeatable; \emph{deployment frequency} is how often the team releases to production; the \emph{change failure rate} is the share of releases that break something. The latter two belong to the four delivery metrics of DORA -- a long-running research programme that measures software delivery performance across thousands of organisations \citep{forsgren2018accelerate} -- and DORA's 2017 analysis is why the fusion is deliberate: the ability to test without an integrated environment and to deploy independently of other teams predicted delivery performance more strongly than test and deployment automation itself \citep{dora2017sodr}. Measured: test feedback time, share of hermetic tests, deployment frequency, and change failure rate -- all read directly from pipeline telemetry. Patterns differ because both abilities are surface expressions of coupling, and coupling is precisely what topologies differ in.
|
||||
|
||||
\subsubsection{Economics and organisation (D10--D11)}
|
||||
|
||||
The fourth group leaves the code: structures cost money to run, and they constrain how organisations can work.
|
||||
|
||||
\paragraph{D10 -- Operating cost efficiency.}
|
||||
\emph{The cloud bill tripled. Which part of the structure spends the money -- and what was it doing at 03:00?} This dimension prices the running system -- machines \emph{and} people. The vocabulary: \emph{cost per request} attributes spend to work actually done; \emph{idle cost} is what you pay for capacity that does nothing (the 03:00 question); \emph{TCO}, the total cost of ownership, is the honest sum -- building, running, and the platform work in between; an \emph{FTE}, a full-time equivalent, is the unit of that last part: one person's full working time. The hidden term matters most: the cost of a self-managed container platform is typically dominated not by compute prices but by the platform-team FTEs required to keep it alive \citep{fowler2015premium, portainer2024k8scost} -- the ``microservice premium'' materialises as staffing. Prime Video's $>90\,\%$ cost reduction from Section~\ref{subsec:fourcases} shows the same dimension from the infrastructure side \citep{kolny2023primevideo}. Measured: the TCO split across build, platform, and run; cost per request; idle cost; and platform-team FTEs -- the discipline that makes cloud spend visible and attributable per team and feature is called \emph{FinOps}. Patterns differ enormously here, and in \emph{both} directions: the same workload can cost a multiple of itself depending on the structure it runs in and the shape of its load.
|
||||
|
||||
\paragraph{D11 -- Team scaling (Conway fit).}
|
||||
\emph{The team grows from three to thirty. Do releases speed up -- or does everyone wait on everyone?} Conway's law, in one plain sentence: a system's structure ends up mirroring the communication structure of the organisation that builds it \citep{conway1968committees} -- which makes every architecture decision a team-structure decision, whether the architect intends that or not \citep{skelton2019team}. This dimension therefore asks how well a structure supports many teams working in parallel, and its operational core is the coordination question: how many teams can design, build, and release without waiting for each other? Measured: \emph{deployments per developer per day} as the team count grows -- DORA found this figure rising in loosely coupled organisations and falling in tightly coupled ones \citep{forsgren2018accelerate} -- and the number of teams able to release without cross-team coordination. Patterns differ because some topologies give each team its own independently deployable unit, while others make thirty people queue for one release train.
|
||||
|
||||
\subsubsection{The new dimension (D12)}
|
||||
|
||||
The last dimension is genuinely new, and assumption A6 forces it into the coordinate system.
|
||||
|
||||
\paragraph{D12 -- AI integrability.}
|
||||
\emph{The new feature's core is an LLM call: eight seconds, paid per request, sometimes confidently wrong. How hard does the structure fight it?} AI integrability measures how cheaply a structure can host a component that is slow, fallible, and priced per call. Such a component needs three things from its surroundings, stated here in plain words because the rest of the script uses them constantly. A \emph{queue}: a waiting line in which requests park, so that an eight-second call -- or a provider outage, or a rate limit -- does not block everything behind it. A \emph{port}: a narrow, contract-shaped interface behind which the component's non-determinism is isolated, so that ordinary, deterministic tests can substitute a fake for it. A \emph{measurement point}: a place where the cost and quality of every single call are observable -- necessary because LLM providers price per \emph{token}, a fragment of a word, so that \emph{token cost} accrues per request rather than per month, and because a component that can be wrong must be scored continuously. The scoring instrument is the \emph{eval harness}: a versioned set of test inputs with expected qualities, against which the AI component's pass rate is computed -- the AI counterpart of a regression test suite \citep{zheng2023judging}, run as a CI gate alongside per-request cost budgets \citep{ford2022evolutionary}. Patterns differ sharply in whether queue, port, and measurement point come naturally or must be bolted on -- Part~\ref{part:ai} derives the full column.
|
||||
|
||||
\begin{examplebox}[One system, one profile: a retail e-banking application]
|
||||
Walk a familiar system through the five groups. \emph{Load and speed:} traffic peaks on payday mornings; reads (balance checks) outnumber writes (payments) enormously; users tolerate two seconds, not ten -- D1 and D3 matter, D2 is modest. \emph{Correctness and trust:} a double-booked transfer is existential and the audit trail is a legal duty -- D4 and D6 are as high as they go; and if the login page dies, payments must keep clearing -- D5 high. \emph{Change and delivery:} releases are monthly and formally reviewed, but the system must absorb regulatory change for decades -- D7 high, D9 moderate. \emph{Economics and organisation:} the bank operates a platform organisation anyway, and dozens of teams must work in parallel -- D10 medium, D11 high. \emph{AI:} a chat assistant is attractive, but a confidently wrong answer about a balance is a safety problem -- D12 medium, with hard guardrails. The individual judgements are debatable; the point is not. A real system has a \emph{profile} -- demanding on a few dimensions, relaxed on others -- and writing that profile down rigorously is exactly what Section~\ref{sec:demand} does.
|
||||
\end{examplebox}
|
||||
|
||||
\begin{thinkbox}
|
||||
Pick an app you use daily. Which three dimensions dominate it? On which dimension would its operator accept a bad rating without losing sleep? Compare with your neighbour -- where you disagree, you have found a \emph{weight} discussion, and that is precisely what a utility tree resolves (Section~\ref{sec:demand}).
|
||||
\end{thinkbox}
|
||||
|
||||
\subsection{Why exactly these twelve}
|
||||
\label{subsec:admission}
|
||||
|
||||
Twelve intuitions are not yet a coordinate system. This subsection adds the quality control: what kind of requirement qualifies at all, where the names come from, and which conditions a candidate had to pass to become a dimension.
|
||||
|
||||
\paragraph{Quality attributes, not functions.} A \emph{functional requirement} states what the system shall do: compute interest, post a booking, render a feed. A \emph{quality attribute requirement} (the entrenched but misleading term is ``non-functional'') states how well, under which conditions, and at what cost. The architectural asymmetry between the two is the content of A3: ``post a booking'' can be implemented inside a layered monolith, as a \emph{saga} (a chain of compensating steps) across microservices, or as an event-sourced log -- three structures previewed in Section~\ref{subsec:patternpreview} and dissected in Part~\ref{part:patterns} -- the function is identical; the consistency guarantee, the latency distribution, the audit trail, and the cost of the next change are radically different \citep{bass2021software, sommerville2020modernes}. All twelve dimensions are therefore quality attributes or workload and constraint characteristics -- never features, which under-determine architecture. We use ``quality attribute'' as the primary term, following \citet{bass2021software}.
|
||||
|
||||
\paragraph{The names: ISO/IEC 25010:2023.}
|
||||
\label{subsec:iso25010} % label kept for backward compatibility; sits inside subsection 2.3 and resolves to the same number as subsec:admission
|
||||
The naming standard for quality attributes is ISO/IEC 25010, the product quality model of the SQuaRE series; its 2023 revision defines nine characteristics, each with named sub-characteristics: functional suitability, performance efficiency, compatibility, interaction capability, reliability, security, maintainability, flexibility, and safety \citep{iso2023product, iso2023quality, iso2011product}. Three 2023 changes matter directly here: \emph{Safety} became a new top-level characteristic (fail safe, hazard warning -- exactly what one must state for a component that can produce wrong output with full confidence); \emph{usability} was recast as \emph{Interaction capability}; and \emph{portability} became \emph{Flexibility} with an explicit new \emph{scalability} sub-characteristic, while \emph{Security} gained \emph{resistance} -- sustaining operation under attack, the normative hook for prompt-injection robustness \citep{iso2023product, owasp2025llmtop10}. The 2023 vocabulary thus covers AI-bearing systems without private extensions -- A6 starts with the quality model itself -- and its sub-characteristics appear as the anchors in the third column of Table~\ref{tab:dimensions}.
|
||||
|
||||
\paragraph{Three admission conditions.} With the raw material fixed by A3 and the names fixed by the standard, a candidate became one of the twelve only if it passed three conditions:
|
||||
|
||||
\begin{enumerate}
|
||||
\item \textbf{Standard anchoring.} Each dimension maps to ISO/IEC 25010:2023 vocabulary, so the profile language stays anchored in the standard quality model; where a dimension reaches beyond it (cost, organisation), the anchor is stated in parentheses.
|
||||
\item \textbf{Discrimination.} Each dimension must discriminate between at least two of the seven patterns of Part~\ref{part:patterns} -- a dimension on which all patterns score alike carries no matching information.
|
||||
\item \textbf{Instrumentation.} Each dimension must have a \emph{defined response measure and a measurement instrument}, so that every rating over it is a testable prediction, not an adjective. This is A4 applied to the theory itself: \textbf{no instrument, no dimension.}
|
||||
\end{enumerate}
|
||||
|
||||
You have already watched the third condition at work: every block of Section~\ref{subsec:dimtour} ended with how the dimension is measured, because a dimension without an instrument would not have entered this script. Note what the condition excludes: ``elegance'', ``future-proofness'', and similar candidates without a defined response measure. Twelve is also a didactic compromise: few enough to survey, rich enough to discriminate.
|
||||
|
||||
\begin{hinweisbox}
|
||||
The nine characteristics are a \emph{taxonomy}, not a \emph{metric}: ISO/IEC 25010 measures nothing by itself, and quality taxonomies are neither complete nor free of overlap -- is a denial-of-service outage an availability, security, or performance problem? \citet{bass2021software} offer the pragmatic resolution this module adopts: do not argue about the box; write the concern as a six-part scenario with a response measure (Section~\ref{sec:demand}), and the classification question dissolves. ISO~25010 supplies vocabulary and completeness checklists; the measurement work is done by scenarios and fitness functions.
|
||||
\end{hinweisbox}
|
||||
|
||||
\subsection{The reference card}
|
||||
\label{subsec:dimtable}
|
||||
|
||||
Table~\ref{tab:dimensions} condenses Section~\ref{subsec:dimtour} into the module's canonical reference card. It adds nothing new: every term in its columns was defined above, and every row is the compact form of one dimension block you have already read. What the table adds is \emph{status}: every rating, weight, and fit cell of Parts~\ref{part:patterns}--\ref{part:fit} is expressed over exactly these twelve rows, each admitted under the three conditions of Section~\ref{subsec:admission}. When a later chapter says ``D7'', this table is what it means.
|
||||
|
||||
\begin{sidewaystable}
|
||||
\centering
|
||||
\caption{The twelve profile dimensions with ISO/IEC 25010:2023 anchor, response measures, and measurement instruments. This is the canonical dimension table of the module: capability profiles (Table~\ref{tab:capability}), requirements profiles (Table~\ref{tab:requirements}), and the fit matrix (Table~\ref{tab:fitmatrix}) are all expressed over these dimensions.}
|
||||
\label{tab:dimensions}
|
||||
\footnotesize
|
||||
\begin{tabular}{@{}p{0.7cm}p{3.1cm}p{4.0cm}p{6.3cm}p{6.3cm}@{}}
|
||||
\toprule
|
||||
\textbf{\#} & \textbf{Dimension} & \textbf{ISO 25010:2023 anchor} & \textbf{Response measure (examples)} & \textbf{Measurement instrument} \\
|
||||
\midrule
|
||||
D1 & Read scalability & Flexibility $\to$ scalability; Performance $\to$ capacity & Throughput at $k\times$ horizontal replication; cache hit ratio; p95 read latency under load & Step-profile load tests; production RED metrics \\
|
||||
D2 & Write scalability \& elasticity & Flexibility $\to$ scalability & Sustained ingest rate; time-to-capacity after a load step; scale-to-zero cost & Load tests with load steps; elasticity-lag measurement \citep{jonas2019berkeley} \\
|
||||
D3 & Latency \& predictability & Performance $\to$ time behaviour & p50/p95/p99 response time; cold-start frequency; tail-latency ratio p99/p50 & Distributed tracing (OpenTelemetry); latency budgets as CI gates \citep{ford2022evolutionary} \\
|
||||
D4 & Consistency \& transactional integrity & Functional correctness; Reliability & Anomaly rate under concurrency; invariant-violation count ($0$ for ledgers); staleness bound (s) & Jepsen-style consistency tests; invariant checks; reconciliation jobs \citep{kleppmann2017designing} \\
|
||||
D5 & Availability \& fault isolation & Reliability $\to$ availability, fault tolerance & SLO attainment; error-budget burn; blast radius (\% of functionality lost per component failure); MTTR & SLOs and error budgets; chaos experiments as continual holistic fitness functions \citep{basiri2016chaos, ford2022evolutionary} \\
|
||||
D6 & Security \& auditability & Security $\to$ accountability, non-repudiation, resistance & Time to reconstruct a complete audit trail for one transaction; \% of state changes journaled; audit scope size & Audit-trail drills; immutable logs / event sourcing; PCI/FINMA scope reviews \citep{finma2023oprisk, pcissc2022pcidss} \\
|
||||
D7 & Evolvability \& maintainability & Maintainability $\to$ modularity, modifiability, analysability & Change dispersion (modules touched per average feature); coupling metrics (CBO, instability $I$); declared-boundary violations (target $0$) & ArchUnit / Spring Modulith verification as CI gates; CK metrics \citep{chidamber1994metrics, martin2003agile, drotbohm2023modulith} \\
|
||||
D8 & Simplicity \& time-to-market & (Process quality; Maintainability $\to$ analysability) & Time from empty repository to first production release; onboarding time to first merged PR; number of runtime technologies & Delivery calendar; team surveys; tech-radar count \\
|
||||
D9 & Testability \& deployability & Maintainability $\to$ testability & Test feedback time; \% of hermetic tests (no integrated environment needed); deployment frequency; change failure rate & Pipeline telemetry; DORA capability items on independent testing and deployment \citep{forsgren2018accelerate} \\
|
||||
D10 & Operating cost efficiency & (Cost; Performance $\to$ resource utilization) & TCO split build/platform/run; cost per request; idle cost; platform-team FTEs & FinOps reporting; cost-per-request telemetry; TCO benchmarks \citep{portainer2024k8scost, kolny2023primevideo} \\
|
||||
D11 & Team scaling (Conway fit) & (Organisational) & Deployments per developer per day as team count grows; number of teams able to release without cross-team coordination & DORA scaling analysis \citep{forsgren2018accelerate}; Team Topologies review \citep{skelton2019team, conway1968committees} \\
|
||||
D12 & AI integrability & Safety $\to$ fail safe, operational constraint; Security $\to$ resistance & Tolerance for seconds-scale latency and asynchronous integration; feasibility of isolating non-determinism behind contracts; token-cost observability per request & Eval-harness pass rate $\geq$ threshold in CI; cost budgets per request as fitness functions \citep{ford2022evolutionary, zheng2023judging} \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{sidewaystable}
|
||||
|
||||
Three remarks on individual dimensions.
|
||||
|
||||
\textbf{D9 fuses testability and deployability deliberately.} DORA's 2017 analysis found precisely this pair -- can the team test without an integrated environment, and deploy independently of other teams -- to be the architecture characteristics contributing most to continuous delivery, more than test and deployment automation itself \citep{dora2017sodr, forsgren2018accelerate}. Both are surface expressions of the same underlying variable, coupling; splitting them would double-count one property.
|
||||
|
||||
\textbf{D10 and D11 reach beyond the product quality model}, and the table says so with parenthesised anchors. They are admitted nonetheless because they pass the other two conditions: both discriminate between patterns, and both are instrumented -- by the personnel-dominated TCO evidence and the DORA scaling analysis presented in Section~\ref{subsec:dimtour} \citep{fowler2015premium, portainer2024k8scost, forsgren2018accelerate, conway1968committees, skelton2019team}.
|
||||
|
||||
\textbf{D12 is the only genuinely new dimension, and A6 forces it.} It measures how cheaply a structure can host a component that is slow, fallible, and priced per call -- concretely, whether the pattern naturally provides the \emph{queue}, the \emph{port}, and the \emph{measurement point} introduced in Section~\ref{subsec:dimtour}. Patterns differ sharply here -- exactly the discrimination condition -- and Part~\ref{part:ai} derives the D12 ratings in detail.
|
||||
|
||||
\begin{keypoint}
|
||||
The twelve dimensions of Table~\ref{tab:dimensions} are the module's canonical coordinate system: ISO-anchored, pattern-discriminating, and -- without exception -- equipped with response measures and instruments. Every capability rating is a testable prediction on this frame; every requirement weight is a utility-tree-derived priority on it; every fit cell is their rule-based comparison. When in doubt anywhere in this script, return to this table.
|
||||
\end{keypoint}
|
||||
|
||||
% ============================================
|
||||
% SECTION: CONSTRUCTING THE DEMAND SIDE -- R(a)
|
||||
% ============================================
|
||||
\section{Constructing the Demand Side: The Requirements Profile $R(a)$}
|
||||
\label{sec:demand}
|
||||
|
||||
The demand side of the framework is the requirements profile
|
||||
\[
|
||||
R(a) = \bigl(w_1(a), \dots, w_{12}(a);\; S(a);\; K(a)\bigr):
|
||||
\]
|
||||
twelve priority weights, one workload shape, one set of hard constraints. None of these is written down by intuition; each is \emph{produced} by a defined method, and each subsection ends by naming the component of $R(a)$ it has just produced.
|
||||
|
||||
\subsection{From stakeholder wishes to architecturally significant requirements}
|
||||
\label{subsec:asr}
|
||||
|
||||
Not all requirements shape architecture; most functional ones do not (A3). The ones that do have a name:
|
||||
|
||||
\begin{definitionbox}[Architecturally significant requirement (ASR)]
|
||||
An \emph{architecturally significant requirement} is a requirement that has a profound effect on the architecture -- one whose late accommodation would be disproportionately expensive -- and that is typically also difficult to achieve \citep{bass2021software}.
|
||||
\end{definitionbox}
|
||||
|
||||
The grounded-theory study of \citet{chen2013characterizing} -- 90 practitioners from over 500 organisations -- found that ASRs are typically poorly specified, vague, and implicit, hidden inside business goals (``we plan to enter three new markets next year'' implies a scalability and a compliance ASR) or assumed context. They cannot be read off a requirements document; they must be \emph{elicited}. The established format is the SEI's Quality Attribute Workshop (QAW) \citep{barbacci2003quality}, whose essence is two design choices. First, \emph{who is in the room}: not the development team alone, but the stakeholders whose concerns the architecture must balance -- users, operators, auditors, regulators, product owners \citep{iso2022architecture}. Second, the \emph{sequence}: business and mission drivers first, then identification of architectural drivers, scenario brainstorming, consolidation, prioritisation by stakeholder vote, and refinement of the top candidates into the measurable form of Section~\ref{subsec:sixparts}.
|
||||
|
||||
\emph{Produced:} the raw material of $R(a)$ -- a prioritised pool of candidate ASRs, elicited from stakeholders and business goals, but not yet measurable.
|
||||
|
||||
\subsection{Quality attribute scenarios: the measurable form}
|
||||
\label{subsec:sixparts}
|
||||
|
||||
A4 demands that each candidate requirement be brought into a form that can discriminate between architectures. That form is fixed:
|
||||
|
||||
\begin{definitionbox}[Quality attribute scenario]
|
||||
A \emph{quality attribute scenario} is a short, testable specification of a quality requirement, consisting of six parts \citep{bass2021software}:
|
||||
\begin{enumerate}
|
||||
\item \textbf{Source of stimulus} -- who or what triggers the situation: a user, another system, an attacker, a developer.
|
||||
\item \textbf{Stimulus} -- the arriving event: a request, a failure, a change request, a load spike.
|
||||
\item \textbf{Environment} -- the operating condition: normal operation, overload, degraded mode, development time.
|
||||
\item \textbf{Artifact} -- the part of the system that is stimulated: the whole system, a component, a data store.
|
||||
\item \textbf{Response} -- the desired observable reaction.
|
||||
\item \textbf{Response measure} -- the quantity, with number and unit, by which success is judged: latency percentile, recovery time, person-days, detection rate.
|
||||
\end{enumerate}
|
||||
\end{definitionbox}
|
||||
|
||||
The response measure is the non-negotiable part. ``The system shall be scalable'' names an aspiration; a scenario with a response measure names a test. Without a number and a unit, the requirement cannot be falsified, and an unfalsifiable requirement cannot discriminate between candidate architectures. Bass et al.\ distinguish \emph{general scenarios} (attribute-specific templates) from \emph{concrete scenarios} (instances filled in for one system) \citep{bass2021software}; an application class in Part~\ref{part:applications} carries characteristic concrete scenarios that act as the measuring rod for every pattern held against it.
|
||||
|
||||
\begin{examplebox}[Worked scenario 1: availability in a payment service (banking)]
|
||||
\emph{Source:} a heartbeat monitor. \emph{Stimulus:} reports the failure of one application server. \emph{Environment:} normal operation, mid-day load. \emph{Artifact:} the payment service. \emph{Response:} requests are redirected to replicas; operations staff are notified; in-flight transactions either complete or roll back atomically. \emph{Response measure:} failover completed in under $30$\,s; zero transactions lost or double-posted.
|
||||
|
||||
``The payment service shall be highly available'' hides at least three architectural decisions that the scenario exposes: replicas (redundancy tactic), failure detection (heartbeat tactic), and transactional atomicity across the failover -- a guarantee some patterns provide structurally and others do not. The response measure -- $30$\,s, zero loss -- is directly executable as a chaos experiment \citep{basiri2016chaos}: kill an instance under load and measure. The scenario is simultaneously a requirement, a design driver, and a test specification.
|
||||
\end{examplebox}
|
||||
|
||||
\begin{examplebox}[Worked scenario 2: safety in an AI advisory platform (Axis B)]
|
||||
\emph{Source:} a customer. \emph{Stimulus:} submits a request for which the LLM generates a factually wrong recommendation. \emph{Environment:} normal operation. \emph{Artifact:} the advisory platform. \emph{Response:} the deterministic validation layer detects and blocks the answer and escalates to a human advisor. \emph{Response measure:} detection rate $\geq 99\,\%$ on the versioned evaluation set, at less than $2$\,s added latency.
|
||||
|
||||
Two things are notable. First, the six-part form needed \emph{no extension} for a non-deterministic component -- A6 at work: the stimulus is probabilistic (the model \emph{will} sometimes hallucinate), and the requirement is placed not on the model but on the \emph{system around it}. Second, the response measure presupposes an artefact: a versioned evaluation set against which a detection rate can be computed at all -- the eval harness, the AI counterpart of a regression test suite (Part~\ref{part:ai}). In ISO/IEC 25010:2023 terms, this is a \emph{Safety} scenario (fail safe, hazard warning) \citep{iso2023product}.
|
||||
\end{examplebox}
|
||||
|
||||
\emph{Produced:} the candidate ASRs in falsifiable form -- concrete six-part scenarios, each with a response measure.
|
||||
|
||||
\subsection{The utility tree: from scenarios to weights}
|
||||
\label{subsec:utilitytree}
|
||||
|
||||
A workshop produces more scenarios than any analysis can carry. The \emph{utility tree}, introduced with the ATAM, prioritises them top-down \citep{kazman2000atam, bass2021software}: the root ``Utility'' branches into quality attributes, these into refinements, and each refinement into concrete scenarios as leaves. Every leaf is rated on two independent dimensions, each High/Medium/Low: \textbf{business importance} (what does it cost us if this scenario fails?) and \textbf{achievement difficulty} (how hard is it, architecturally, to satisfy?). The \textbf{(H,\,H) leaves} -- important \emph{and} hard -- are the architecturally critical points on which analysis and design effort concentrate. Figure~\ref{fig:utilitytree} shows a compressed example for a core-banking system.
|
||||
|
||||
\begin{figure}[htbp]
|
||||
\centering
|
||||
\begin{tikzpicture}[
|
||||
sysbox/.style={rectangle, draw, rounded corners=4pt, align=center, font=\scriptsize\sffamily, line width=0.8pt, inner sep=4pt},
|
||||
root/.style={sysbox, fill=bankblue!20, draw=bankblue, font=\small\sffamily\bfseries, minimum height=1.1cm, minimum width=1.9cm},
|
||||
attr/.style={sysbox, fill=bankgreen!15, draw=bankgreen, minimum width=2.6cm, minimum height=0.85cm},
|
||||
leafhh/.style={sysbox, fill=bankred!15, draw=bankred, text width=6.6cm},
|
||||
leaf/.style={sysbox, fill=gray!12, draw=gray!60!black, text width=6.6cm},
|
||||
arr/.style={-{Stealth[length=2.2mm]}, thick, gray!60!black}
|
||||
]
|
||||
\node[root] (util) at (0,0) {Utility};
|
||||
\node[attr] (cons) at (3.6,2.7) {Consistency \&\\integrity};
|
||||
\node[attr] (avail) at (3.6,0.9) {Availability};
|
||||
\node[attr] (perf) at (3.6,-0.9) {Performance};
|
||||
\node[attr] (mod) at (3.6,-2.7) {Modifiability};
|
||||
\node[leafhh] (l1) at (9.2,2.7) {\textbf{(H,\,H)} No booking lost or double-posted under concurrent node failure; invariant violations $= 0$};
|
||||
\node[leafhh] (l2) at (9.2,0.9) {\textbf{(H,\,H)} Failover of the payment service $< 30$\,s with zero transaction loss};
|
||||
\node[leaf] (l3) at (9.2,-0.9) {(H,\,M) Card authorisation p95 $< 2$\,s at $3\times$ baseline load};
|
||||
\node[leaf] (l4) at (9.2,-2.7) {(M,\,H) New regulatory report integrated in $\leq 10$ person-days, touching $\leq 2$ modules};
|
||||
\draw[arr] (util) -- (cons);
|
||||
\draw[arr] (util) -- (avail);
|
||||
\draw[arr] (util) -- (perf);
|
||||
\draw[arr] (util) -- (mod);
|
||||
\draw[arr] (cons) -- (l1);
|
||||
\draw[arr] (avail) -- (l2);
|
||||
\draw[arr] (perf) -- (l3);
|
||||
\draw[arr] (mod) -- (l4);
|
||||
\end{tikzpicture}%
|
||||
\caption{A compressed utility tree for a core-banking system. Leaves are concrete scenarios (abbreviated to their response measures) rated by (business importance, achievement difficulty); the highlighted (H,\,H) leaves determine which dimensions receive High weight in the requirements profile.}
|
||||
\label{fig:utilitytree}
|
||||
\end{figure}
|
||||
|
||||
For the framework, the utility tree performs the decisive job: it is the \emph{methodical derivation of the weights}. A dimension $D_i$ receives $w_i(a) = \text{High}$ exactly when the class's characteristic utility tree has (H,\,H) leaves under the corresponding attribute; Medium and Low follow from the remaining leaf ratings. When Part~\ref{part:applications} assigns core banking a High weight on consistency, that is a claim about documented (H,\,H) scenarios, not an opinion of the lecturer. One consequence is announced here and cashed in at the match (Section~\ref{sec:fit}): \textbf{High weights carry veto power} -- a High weight marks a binding scenario, one whose failure is existential for the class.
|
||||
|
||||
\emph{Produced:} the twelve priority weights $w_1(a), \dots, w_{12}(a) \in \{\text{H}, \text{M}, \text{L}\}$.
|
||||
|
||||
\subsection{What a weight means, dimension by dimension}
|
||||
\label{subsec:weightexamples}
|
||||
|
||||
The utility tree says \emph{how} a weight is derived; it does not yet say what a High \emph{feels like}. So walk the twelve dimensions once more with a concrete question in mind: which kind of application pushes this dimension to High -- and which kind can honestly leave it at Low? Table~\ref{tab:weightexamples} answers with one example each, and almost every example is drawn from the ten application classes whose full profiles Part~\ref{part:applications} derives.
|
||||
|
||||
\begin{table}[htbp]
|
||||
\centering
|
||||
\caption{What a High and a Low requirement look like, dimension by dimension. Most examples anticipate one of the ten application classes of Part~\ref{part:applications} (Table~\ref{tab:requirements}); where no class weights the dimension Low, the Low example is a deliberately generic system outside the class set. A High weight is a veto claim backed by (H,\,H) utility-tree leaves, a Low weight a deliberate release.}
|
||||
\label{tab:weightexamples}
|
||||
\footnotesize
|
||||
\begin{tabular}{@{}p{2.7cm}p{5.7cm}p{5.6cm}@{}}
|
||||
\toprule
|
||||
\textbf{Dimension} & \textbf{A High requirement: example} & \textbf{A Low requirement: example} \\
|
||||
\midrule
|
||||
D1 Read scalability & A public social/content feed: thousands of reads per write, and every user sits on the read path \citep{krikorian2013timelines} & An ERP used by clerks: load is bounded by headcount and office hours \\
|
||||
D2 Write scalability \& elasticity & E-commerce checkout on Black Friday: $10$--$50\times$ seasonal write peaks \citep{shopify2024bfcm}; IoT ingest that never pauses & A BI warehouse loaded once, nightly, inside a batch window \\
|
||||
D3 Latency \& predictability & Interactive messaging: visible lag kills the product & An overnight Monte-Carlo run: the makespan matters, not any single millisecond \\
|
||||
D4 Consistency \& integrity & A payments ledger: one double booking is an existential defect & A social feed: a stale like-count harms nobody \\
|
||||
D5 Availability \& fault isolation & E-commerce: downtime converts directly into lost revenue per minute \citep{linden2006data} & An internal report generator: hours of downtime are tolerable \\
|
||||
D6 Security \& auditability & Core banking under FINMA/BCBS duties: the audit trail is law \citep{finma2023oprisk, bcbs2013rdarr} & An IoT telemetry buffer: transient, impersonal data \\
|
||||
D7 Evolvability \& maintainability & Any system built to live for decades: banking, ERP \citep{reuters2017cobol, sap2020maintenance} & A one-off data migration script: it runs once and is deleted \\
|
||||
D8 Simplicity \& time-to-market & An internal back-office tool: its value is that it ships this quarter & A core ledger: care beats speed, and D8 yields \\
|
||||
D9 Testability \& deployability & Anything changed weekly by several teams: releasing must not require heroics & A frozen batch job that changes twice a year \\
|
||||
D10 Operating cost efficiency & Per-request-priced AI platforms and batch compute farms: run cost is a first-order product property & A core banking system: the run bill is dwarfed by correctness and compliance budgets \\
|
||||
D11 Team scaling (Conway fit) & A platform built by thirty teams: coordination cost is the bottleneck \citep{skelton2019team} & A two-person project: Conway's law has nothing to mirror \\
|
||||
D12 AI integrability & The AI-native advisory platform: hosting slow, fallible, per-call-priced components \emph{is} the product & A classical accounting module: no AI component in sight \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
First, be clear about what a weight \emph{asserts}. A High weight is not enthusiasm; it is a claim with teeth: this dimension carries (H,\,H) leaves -- scenarios whose failure is existential -- and it may therefore \emph{veto} a structure in the match (Section~\ref{sec:fit}), however well that structure scores elsewhere. A Low weight is equally deliberate: not ``we do not care'', but ``we will not pay structure for this'' -- the Monte-Carlo team genuinely should not spend one design decision on millisecond latency. Medium is the tradeable middle. Because a High is a veto claim, every High in a profile must survive the question: \emph{show me the (H,\,H) leaf}.
|
||||
|
||||
Second, notice the most instructive contrast in the table: the D4 row. The payments ledger and the social feed are near-perfect \emph{mirror images} -- for the ledger a wrong number is existential and a stale one merely embarrassing, for the feed precisely the reverse: a stale feed is acceptable, an unavailable one is not. Part~\ref{part:applications} uses exactly this pair (core banking against social/content) as its didactic anchor, because a structure optimised for one is close to pessimal for the other.
|
||||
|
||||
Third, the D7 and D8 rows expose a tension inside a single organisation: shipping fast and living long pull in opposite directions, and both are legitimately High -- in \emph{different} systems. The interesting case is the system that claims both at once: the unglamorous internal workflow tool must ship this quarter \emph{and} absorb reorganisations for the next fifteen years \citep{glass2002facts}. Whether one structure can honour both claims is precisely a matching question -- and the profile we assemble next makes it concrete.
|
||||
|
||||
\subsection{Workload shape and hard constraints}
|
||||
\label{subsec:shapeconstraints}
|
||||
|
||||
Two components of $R(a)$ remain; neither is a weight, and both are produced by inventory rather than prioritisation.
|
||||
|
||||
\textbf{The workload shape $S(a)$} states how load arrives: \emph{interactive} request/response, \emph{continuous stream}, \emph{scheduled batch}, or an explicitly \emph{hybrid} combination -- with its quantitative signature: read/write ratio, load pattern (steady, diurnal, seasonal, spiky), latency budget, data volume, change rate. The dominant shape matters because patterns have native shapes too (Section~\ref{sec:supply}): a batch pipeline cannot carry an interactive core, however well its ratings read, and the match enforces that as a gate. The signature is measured, not guessed: read/write ratios from access logs, load patterns from telemetry, latency budgets from the binding scenarios.
|
||||
|
||||
\textbf{The hard constraints $K(a)$} are collected as an explicit inventory: regulatory obligations (e.g.\ BCBS~239, PCI~DSS v4.0, the EU AI Act \citep{bcbs2013rdarr, pcissc2022pcidss, eu2024aiact}), team size and skills (Conway), budget, and mandated platforms. The separation from weights is load-bearing: \textbf{constraints are knock-out filters, never weights}. A pattern that violates a constraint is excluded \emph{before} any scoring, never averaged away \citep{keeney1993decisions}: a payment architecture that cannot produce the audit trail PCI~DSS requires is not ``weak on one criterion'' -- it is not a candidate.
|
||||
|
||||
\emph{Produced:} the workload shape $S(a)$ and the constraint set $K(a)$.
|
||||
|
||||
\subsection{$R(a)$ assembled}
|
||||
\label{subsec:reqassembled}
|
||||
|
||||
The three methods together yield the demand side of the framework:
|
||||
|
||||
\begin{definitionbox}[Requirements profile $R(a)$]
|
||||
Each application class $a \in A$ has a \emph{requirements profile}
|
||||
\[
|
||||
R(a) = \bigl(w_1(a), \dots, w_{12}(a);\; S(a);\; K(a)\bigr)
|
||||
\]
|
||||
where $w_i(a) \in \{\text{High}, \text{Medium}, \text{Low}\}$ is the priority weight of dimension $D_i$ (Table~\ref{tab:dimensions}), derived from the class's characteristic utility tree (A4); $S(a)$ is the dominant \emph{workload shape} with its quantitative signature; and $K(a)$ is the set of \emph{hard constraints} -- regulatory obligations, team size and skills, budget, mandated platforms -- which act as knock-out filters, not weights \citep{keeney1993decisions}.
|
||||
\end{definitionbox}
|
||||
|
||||
\begin{examplebox}[Worked construction: $R(\text{C10})$ -- the AI-native advisory platform]
|
||||
C10 is the class of the course project: an advisory platform whose answers are generated by LLMs over a grounded knowledge base \citep{lewis2020rag, zaharia2024compound}. Its characteristic utility tree has (H,\,H) leaves under five attributes: every statement needs provenance and every agent step must be logged -- observability is \emph{domain functionality} here ($\to$ D6); models, prompts, and frameworks change at an extreme rate ($\to$ D7); evals are the operative meaning of testability ($\to$ D9); the platform is expensive \emph{per request} (tokens, GPU), not per user -- a run-cost class no classical profile contains ($\to$ D10); and the value proposition depends on hosting slow, fallible, per-call-priced components ($\to$ D12). Hence:
|
||||
\begin{itemize}
|
||||
\item \textbf{Weights:} High on D6, D7, D9, D10, D12; Medium on D1, D3, D4, D5, D8; Low on D2 and D11. Two Mediums surprise students: D3, because users accept seconds-to-minutes for an advisory answer -- the High-grade concern is cost per request, not speed; and D4, because the profile is a hybrid -- the knowledge index may be eventually consistent while the transaction and audit path is strictly ACID.
|
||||
\item \textbf{Workload shape:} $S(\text{C10})$ is explicitly hybrid -- interactive request/response for the advisory dialogue, batch/asynchronous pipelines for indexing and evaluation runs.
|
||||
\item \textbf{Constraints:} $K(\text{C10}) = \{$EU AI Act 2024/1689: logging, documentation, human-oversight duties, potentially high-risk classification \citep{eu2024aiact}; GDPR \citep{eu2016dsgvo}$\}$.
|
||||
\end{itemize}
|
||||
$R(\text{C10})$ is now a complete, argued profile: every High traces to (H,\,H) scenarios, the shape is stated with its signature, and the constraints are knock-out conditions for the match.
|
||||
\end{examplebox}
|
||||
|
||||
One profile could be a coincidence. A second, deliberately unglamorous one shows that the method produces genuinely \emph{different} demand -- and it takes eight lines.
|
||||
|
||||
\begin{examplebox}[Worked construction: $R(\text{back-office})$ -- an internal workflow tool]
|
||||
Consider the university's grade-publication portal, or any internal tool that routes approvals, files, and postings between clerks -- the industry's modal, unglamorous case. Its (H,\,H) leaves sit under five attributes. \textbf{High} on D4: an approval or a posting must never be lost or duplicated -- the records \emph{are} the process. High on D6: statutory retention (e.g.\ Swiss OR~958f) and internal-control rules make the approval trail auditable by obligation. High on D7: the cost of this class lives almost entirely in evolution -- reorganisations and process changes over a $10$--$20$-year horizon, not operation \citep{glass2002facts}. High on D8: built by a small internal IT team, its value is that it ships this quarter. High on D10: an internal tool earns no revenue to bill infrastructure against, so run cost must stay near zero. \textbf{Medium} on D3 and D9 (responsive enough for office work; releases are routine but not weekly). \textbf{Low} everywhere else: load is bounded by employee headcount (D1, D2), hours of downtime are tolerable (D5), one team suffices (D11), and no AI component is in sight (D12). \textbf{Shape:} interactive request/response at office-hours load. \textbf{Constraints:} $K = \{$retention law; internal-control rules; GDPR \citep{eu2016dsgvo}$\}$.
|
||||
|
||||
Now place the two profiles side by side. Each has five Highs, but not the same five: they overlap where regulation and longevity reach everywhere (D6, D7, D10) and diverge exactly on the discriminating pairs -- the back-office tool demands D4 and D8 where the advisory platform is relaxed, the platform demands D9 and D12 where the tool is indifferent. Different High-sets arm \emph{different vetoes}, so no single structure can be the answer to both demands -- which is A2 made operational, and precisely why a matching step (Section~\ref{sec:fit}) exists at all. Section~\ref{subsec:minimatch} runs the match for the first profile; a think-box there hands you the second.
|
||||
\end{examplebox}
|
||||
|
||||
Part~\ref{part:applications} repeats exactly this construction for ten application classes -- the two just built among them, as C10 and C3 -- and Table~\ref{tab:requirements} is nothing but its result, ten profiles side by side, every High argued from documented evidence.
|
||||
|
||||
\begin{projektbox}
|
||||
In week~2 you will run a compressed Quality Attribute Workshop for the \textbf{Portfolio Intelligence Platform}. In stakeholder roles (retail customer, compliance officer, operations engineer, product owner), you will brainstorm, consolidate, and prioritise quality attribute scenarios, refine the top candidates into the six-part form -- each with a numeric response measure -- and assemble them into a utility tree. Deliverable: at least eight concrete scenarios, at least three addressing the platform's AI components (answer correctness, token cost per request, provider migration), with the (H,\,H) leaves identified. This is not a warm-up exercise: the (H,\,H) leaves become the weights of your requirements profile, which you will match against the capability profiles of Part~\ref{part:patterns} in the ADR you record in week~6.
|
||||
\end{projektbox}
|
||||
|
||||
\begin{keypoint}
|
||||
\textbf{Maxim 6.} An architecture decision without a response measure is an opinion; with a response measure and a fitness function it is a testable hypothesis. $R(a)$ operationalises this on the demand side: elicited ASRs, made falsifiable as scenarios, prioritised into weights by the utility tree, completed by a measured workload shape and an explicit constraint inventory.
|
||||
\end{keypoint}
|
||||
|
||||
\begin{thinkbox}
|
||||
Take ``the platform shall be user-friendly'' and turn it into a six-part scenario with a response measure. What did you have to decide -- about users, tasks, context, thresholds -- that the sentence silently left open? Now do the same for ``the AI must not hallucinate''. Which was harder to make measurable, and why?
|
||||
\end{thinkbox}
|
||||
|
||||
% ============================================
|
||||
% SECTION: CONSTRUCTING THE SUPPLY SIDE -- C(p)
|
||||
% ============================================
|
||||
\section{Constructing the Supply Side: The Capability Profile $C(p)$}
|
||||
\label{sec:supply}
|
||||
|
||||
The supply side asks the symmetric question: what can a given structure deliver on the same twelve dimensions? The answer is the capability profile
|
||||
\[
|
||||
C(p) = \bigl(c_1(p), \dots, c_{12}(p);\; S(p)\bigr),
|
||||
\]
|
||||
and -- exactly as on the demand side -- each rating is \emph{derived}, not asserted. But before anything can be rated, the candidates themselves must be on the table.
|
||||
|
||||
\subsection{The seven candidates: a first look}
|
||||
\label{subsec:patternpreview}
|
||||
|
||||
So far, the patterns have been little more than names in forward references. That is not good enough for what follows: the derivation examples of this section and the worked match of Section~\ref{sec:fit} only mean something if the reader can picture the structures being rated. Table~\ref{tab:patternpreview} therefore introduces the seven candidates -- the set $P$ of the framework -- each in one sentence, with its signature strength and its signature cost. The two-letter codes are used throughout the script. You have, in fact, already met four of them in production dress: Stack Overflow runs a layered-style monolith, Monzo runs microservices, Prime Video's failed design was serverless, and Segment's rollback was a microservice cut (Table~\ref{tab:fourcases}).
|
||||
|
||||
\begin{table}[htbp]
|
||||
\centering
|
||||
\caption{The seven candidate patterns -- the set $P$ of the framework -- in one sentence each. Part~\ref{part:patterns} dissects every pattern with its topology, tactics, and footnoted capability profile; here they need only be concrete enough that the derivation examples below and the worked match of Section~\ref{sec:fit} have referents.}
|
||||
\label{tab:patternpreview}
|
||||
\footnotesize
|
||||
\begin{tabular}{@{}p{2.4cm}p{5.4cm}p{3.0cm}p{3.2cm}@{}}
|
||||
\toprule
|
||||
\textbf{Pattern (code)} & \textbf{Structure in one sentence} & \textbf{Signature strength} & \textbf{Signature cost} \\
|
||||
\midrule
|
||||
Layered / 3-tier (L) & One deployable, cut into horizontal \emph{technical} layers: presentation, logic, persistence & Simple and cheap: one build, one database, one process & A typical feature cuts across all layers \\
|
||||
Modular monolith (MM) & One deployable, cut into \emph{domain} modules with machine-enforced boundaries & Monolith economics with modular evolvability & Boundaries erode without continuous governance \\
|
||||
Hexagonal / ports \& adapters (HX) & A domain core behind technology-neutral ports with swappable adapters -- a discipline \emph{inside} a host, not a distribution style & Hermetic testability; swappable technology & Indirection that pays off only under change \\
|
||||
Microservices (MS) & Many independently deployable services, database per service & Team scaling; independent deployment & No ACID across services; the highest operating cost in the set \\
|
||||
Event-driven (EDA) & Components communicate through asynchronous events via a broker & Decoupling, elasticity, fault isolation & Eventual consistency; end-to-end testing is hard \\
|
||||
Pipes-and-filters / batch (PF) & Data flows through a chain or DAG of processing steps & Throughput and reproducibility for batch work & Not built for interactive latency \\
|
||||
Serverless / FaaS (SL) & Functions on managed infrastructure: scale-to-zero, per-execution billing & Elasticity; zero idle cost & Cold starts; cost inverts under sustained load \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
Each row compresses an established literature: layered and pipes-and-filters are classical styles \citep{buschmann1996posa, shaw1996software, richards2025fundamentals}; the modular monolith is the domain-partitioned refinement of the monolith \citep{su2024modular, richards2025fundamentals}; hexagonal is Cockburn's ports-and-adapters discipline \citep{cockburn2005hexagonal, cockburn2024hexagonal}; microservices follow \citet{lewis2014microservices} and \citet{newman2021building}; event-driven architecture rests on messaging patterns \citep{hohpe2003enterprise}; serverless on the Berkeley analysis \citep{jonas2019berkeley, cncf2018serverless}. One entry needs flagging now because it behaves unlike the others: \textbf{HX is not a competitor in the same race}. It organises dependencies \emph{inside} whichever host structure it is applied to, and therefore composes with the other six -- a hexagonal modular monolith is one coherent design, not two rival ones. The next subsection makes that demarcation precise; Part~\ref{part:patterns} devotes a full chapter to each pattern.
|
||||
|
||||
\subsection{Tactics: the causal mechanism from structure to quality}
|
||||
\label{subsec:patterntactic}
|
||||
|
||||
Students routinely conflate three levels of design vocabulary; the framework keeps them apart, because its explanatory mechanism lives exactly in the gap between them.
|
||||
|
||||
\begin{definitionbox}[Architectural pattern (style)]
|
||||
An \emph{architectural pattern} -- used synonymously with \emph{architectural style}, following common usage in \citet{richards2025fundamentals} and the style taxonomy of \citet{shaw1996software} -- is a named, documented macro-structure of a system or subsystem: a topology of elements, permitted relations between them, and known consequences.
|
||||
\end{definitionbox}
|
||||
|
||||
\begin{definitionbox}[Architectural tactic]
|
||||
A \emph{tactic} is an elementary design decision that directly influences the response of one quality attribute -- the atomic unit of architectural design \citep{bachmann2003deriving, bass2021software}. Examples: \emph{heartbeat} and \emph{redundancy} (availability), \emph{use an intermediary} and \emph{defer binding} (modifiability), \emph{introduce concurrency} and \emph{maintain multiple copies} (performance).
|
||||
\end{definitionbox}
|
||||
|
||||
The causal link between the two levels is the theoretical backbone of the matching apparatus: \textbf{patterns are bundles of tactics}. An event-driven architecture structurally packages ``use an intermediary'' (modifiability) and ``introduce concurrency'' (performance) while structurally impeding ``transactions'' (consistency) \citep{bass2021software}; it therefore helps some quality attributes and hurts others \emph{by construction}, not by accident.
|
||||
|
||||
\begin{keypoint}
|
||||
Patterns are bundles of tactics: a pattern structurally privileges some tactics while impeding others, so every pattern helps some quality attributes and hurts others \emph{by construction}. This causal chain -- topology $\to$ tactics $\to$ quality attribute responses -- makes every $++$ and every $--$ in a capability profile explainable and testable rather than a matter of taste.
|
||||
\end{keypoint}
|
||||
|
||||
Two demarcations matter for the rest of the script. First, \textbf{hexagonal architecture (ports and adapters) is a pattern of dependency organisation, not a distribution style} \citep{cockburn2005hexagonal, cockburn2024hexagonal}: orthogonal to the monolith/microservices axis, it \emph{composes} with the other six patterns -- a hexagonal modular monolith and hexagonal microservices are both coherent designs. Second, patterns are always evaluated \emph{per subsystem}, not per company logo: real systems combine a core pattern with different patterns at their edges, and Part~\ref{part:fit} treats such hybrids as the normal case.
|
||||
|
||||
\subsection{Deriving a rating $c_i(p)$}
|
||||
\label{subsec:derivation}
|
||||
|
||||
A rating $c_i(p) \in \{++, +, \circ, -, --\}$ is an \emph{ordinal} claim: how well does the pattern's topology structurally support dimension $D_i$? It is derived from three sources of evidence, applied in order.
|
||||
|
||||
\begin{enumerate}
|
||||
\item \textbf{Tactics analysis.} Which tactics does the topology make cheap, and which does it impede? This is the causal core: a $--$ that cannot be traced to a structural impediment is an assertion, not a rating.
|
||||
\item \textbf{Published ratings.} The star ratings of \citet{richards2025fundamentals} calibrate ours, five-step to five-step ($5\star \to ++$, $4\star \to +$, $3\star \to \circ$, $2\star \to -$, $1\star \to --$), and \textbf{every deviation from the source ratings is footnoted} in Part~\ref{part:patterns}. Where no stars exist (hexagonal, serverless), the profile is derived from primary sources \citep{cockburn2024hexagonal, jonas2019berkeley, cncf2018serverless} and flagged.
|
||||
\item \textbf{Documented production systems.} Cases like those of Table~\ref{tab:fourcases} act as calibration points: a rating that contradicts a documented production result must either explain the context difference or yield.
|
||||
\end{enumerate}
|
||||
|
||||
Two micro-derivations make the method concrete -- one positive rating, one negative.
|
||||
|
||||
\begin{examplebox}[Micro-derivation 1: why event-driven architecture rates $++$ on D7 (evolvability)]
|
||||
\emph{Tactics analysis.} The broker topology is the tactic ``use an intermediary'' \citep{bass2021software} built into the macro-structure: producers publish events to a broker; consumers subscribe. A new consumer -- a recommendation engine, a moderation service, an audit feed -- therefore attaches to the event stream \emph{without touching a single producer}. The response measure of D7, change dispersion (modules touched per average feature), is structurally minimised for consumer-side growth: adding functionality is additive, not invasive. \emph{Published rating.} Richards and Ford rate the style's evolvability at five stars \citep{richards2025fundamentals} -- $++$ under the mapping, no deviation to footnote. \emph{Production evidence.} LinkedIn's Kafka ecosystem grew for a decade by attaching new consumers to the same durable log \citep{kreps2011kafka, lee2019kafka}. The rating is a trade, exactly as A2 predicts: the same intermediary that decouples producers from consumers also impedes transactions and hides the workflow -- the costs land on D4 and D9.
|
||||
\end{examplebox}
|
||||
|
||||
\begin{examplebox}[Micro-derivation 2: why microservices rate $--$ on D4 (consistency)]
|
||||
\emph{Tactics analysis.} The weakness is structural, not incidental. Database-per-service is constitutive of the pattern, and it means \emph{no ACID transaction spans a service boundary}. A business invariant that crosses services (order $\to$ stock $\to$ ledger) must be maintained by a \emph{saga} -- a sequence of local transactions with compensating actions -- which trades atomicity for choreography or orchestration complexity \citep{richardson2018microservices, newman2021building}: intermediate states are visible, and compensation is not rollback. Against D4's response measures (anomaly rate under concurrency; invariant-violation count, target $0$ for ledgers), the topology impedes the transaction tactic by construction. Hence $--$. \emph{Production evidence.} A documented mitigation exists, but it is conditional -- Monzo makes sagas work at organisational scale under extreme technological homogeneity \citep{sewell2024monzo} -- and the matching procedure of Section~\ref{sec:fit} handles exactly this case: a veto on a High-weight dimension that only a \emph{documented} mitigation can lift.
|
||||
\end{examplebox}
|
||||
|
||||
The two micro-derivations show the method at full depth on two single cells; Table~\ref{tab:capexamples} sweeps the same question -- \emph{what structural fact earns the rating?} -- across all twelve dimensions at once, naming for each the topology that supports it best and the topology that fights it hardest.
|
||||
|
||||
\begin{table}[htbp]
|
||||
\centering
|
||||
\caption{What $++$ and $--$ look like, dimension by dimension: the structural fact behind the extreme ratings, with the patterns of Table~\ref{tab:patternpreview} that exhibit it. Where the honest rating of a named pattern falls short of the column's extreme -- $+$ instead of $++$, $-$ or $\circ$ instead of $--$ -- the entry says so on either side: ordinal distances are part of the claim.}
|
||||
\label{tab:capexamples}
|
||||
\footnotesize
|
||||
\begin{tabular}{@{}p{2.7cm}p{5.7cm}p{5.6cm}@{}}
|
||||
\toprule
|
||||
\textbf{Dimension} & \textbf{What $++$ looks like structurally} & \textbf{What $--$ (or the weak end) looks like} \\
|
||||
\midrule
|
||||
D1 Read scalability & Independently replicated, cacheable read paths per service or consumer (MS, EDA) & Reads entangled with one schema and one application tier (L: $\circ$ -- caching relieves it, the single write path remains) \\
|
||||
D2 Write scalability \& elasticity & Partitioned ingest with elastic consumers (EDA, SL) & One relational database receiving every write (L) \\
|
||||
D3 Latency \& predictability & In-process calls: no network hop, no cold start (L, MM: $+$) & Answers arrive in makespans, not milliseconds (PF -- by design) \\
|
||||
D4 Consistency \& integrity & One ACID transaction boundary around all state (L, MM) & Sagas across service databases (MS); eventual consistency through a broker (EDA) \\
|
||||
D5 Availability \& fault isolation & Bulkheaded services: blast radius one service (MS, EDA) & One process: blast radius $100\,\%$ by construction (L, MM: $-$) \\
|
||||
D6 Security \& auditability & One audit log, one small compliance scope (L, MM, PF: $+$) & An honest middle with two faces: per-service isolation \emph{versus} audit trails scattered across asynchronous hops (MS: $\circ$) \\
|
||||
D7 Evolvability \& maintainability & Enforced module boundaries (MM: $+$); new consumers attach without touching producers (EDA) & A typical feature cuts across every technical layer (L: $-$) \\
|
||||
D8 Simplicity \& time-to-market & One repository, one pipeline, shipping this week (L, PF) & Platform engineering before the first feature (MS, EDA) \\
|
||||
D9 Testability \& deployability & Hermetic domain tests behind ports (HX); per-module test selection (MM: $+$) & Verification only against an integrated environment (L: $-$, in practice); event flows that resist end-to-end tests (EDA: $-$) \\
|
||||
D10 Operating cost efficiency & One cheap deployable, near-zero platform staff (L, MM, PF) & The microservice premium, paid in platform-team FTEs (MS) \\
|
||||
D11 Team scaling (Conway fit) & One team per service, independent release trains (MS) & One release train for everyone (L: $-$) \\
|
||||
D12 AI integrability & A natural queue, port, and measurement point (EDA, HX, PF) & An honest middle: platform timeouts against minutes-long AI runs (SL: $\circ$) \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
Read the table as a promise about Part~\ref{part:patterns}: the capability profiles there (Table~\ref{tab:capability}) are exactly these structural facts, made systematic -- every cell derived by the three-source method above, calibrated against the published star ratings under the fixed mapping, checked against production systems, every deviation footnoted. A rating is never taste; if you cannot point at the topology and name the tactic it privileges or impedes, you do not have a rating. Note also the rows where the table refuses a $--$ (D6, D12): where a structure's weakness is genuinely two-faced or workload-dependent, the honest rating is a middle one, and pretending otherwise would be the supply-side version of the vague requirement A4 forbids on the demand side.
|
||||
|
||||
\subsection{Native workload shape and assembly}
|
||||
\label{subsec:capassembled}
|
||||
|
||||
Like an application, every pattern has a native workload shape $S(p)$: layered, modular-monolith, and microservice structures natively serve interactive request/response; event-driven architecture serves streams and asynchronous flows; pipes-and-filters serves scheduled batch; serverless serves event-triggered, short-lived work; hexagonal, as a composition pattern, inherits its host's shape. $S(p)$ is not a rating but a type: it feeds the workload-shape gate of the match.
|
||||
|
||||
\begin{definitionbox}[Capability profile $C(p)$]
|
||||
Each pattern $p \in P$ has a \emph{capability profile}
|
||||
\[
|
||||
C(p) = \bigl(c_1(p), \dots, c_{12}(p);\; S(p)\bigr), \qquad c_i(p) \in \{++,\, +,\, \circ,\, -,\, --\},
|
||||
\]
|
||||
an \emph{ordinal} rating of how well the pattern structurally supports dimension $D_i$ (Table~\ref{tab:dimensions}), justified through the tactics the pattern bundles or impedes, anchored where possible in the published star ratings of \citet{richards2025fundamentals} under the mapping above, with every deviation from the source ratings footnoted. $S(p)$ is the pattern's native workload shape.
|
||||
\end{definitionbox}
|
||||
|
||||
Part~\ref{part:patterns} repeats this construction for the seven candidates of Table~\ref{tab:patternpreview}, and Table~\ref{tab:capability} is nothing but its result, seven profiles side by side, every deviation footnoted.
|
||||
|
||||
\begin{ailinse}[Axis B preview: an LLM component stresses D3, D10, and D12]
|
||||
Suppose one component of the system is an LLM call. Nothing new is needed -- the coordinate system already carries it. \emph{D3}: LLM calls cost seconds where classical calls cost milliseconds, turning time behaviour from a tuning concern into a structural one (queues, asynchronous integration, caching). \emph{D10}: per-token pricing makes operating cost a per-request attribute -- a badly designed prompt chain is a cost regression the way an $n{+}1$ query is a latency regression. \emph{D12}: the pattern either provides the queue, the port, and the measurement point such a component needs, or it does not -- and the seven patterns differ sharply on exactly that. The supply side absorbs AI as ratings on existing dimensions, per A6; Part~\ref{part:ai} derives the D12 column in detail.
|
||||
\end{ailinse}
|
||||
|
||||
\begin{keypoint}
|
||||
A capability rating is a testable prediction, not a preference: derived from tactics, calibrated against published star ratings under a fixed mapping, checked against documented production systems, every deviation footnoted. Supply is constructed with the same rigour as demand.
|
||||
\end{keypoint}
|
||||
|
||||
% ============================================
|
||||
% SECTION: THE MATCH -- fit(a,p)
|
||||
% ============================================
|
||||
\section{The Match: $\mathrm{fit}(a,p)$}
|
||||
\label{sec:fit}
|
||||
|
||||
Demand and supply are now constructed; what remains is the rule that compares them. We derive it constructively: the way the profiles were built dictates which properties any admissible aggregation must have -- and those properties leave essentially one shape of procedure.
|
||||
|
||||
\subsection{What the construction dictates}
|
||||
\label{subsec:aggregation}
|
||||
|
||||
Three properties of the profiles are not stylistic choices but results of their construction, and each imposes a requirement on the aggregation.
|
||||
|
||||
First, \textbf{constraints are knock-outs}: $K(a)$ was collected as an inventory of obligations precisely because a violated obligation cannot be traded against merit (Section~\ref{subsec:shapeconstraints}), so the aggregation must eliminate violating patterns \emph{before} any scoring \citep{keeney1993decisions} -- and the workload shape belongs to the same family, since a pattern whose native $S(p)$ contradicts the dominant $S(a)$ cannot carry the class's core. Second, \textbf{High weights carry vetoes}: a High weight was \emph{defined} as the presence of (H,\,H) leaves -- scenarios whose failure is existential -- and announced as a veto claim (Sections~\ref{subsec:utilitytree} and \ref{subsec:weightexamples}); a pattern that is structurally weak exactly there fails those scenarios, and excellence elsewhere does not un-fail them, so the aggregation must be \emph{non-compensatory} on High-weight dimensions. Third, \textbf{everything is ordinal}: ordinal inputs license ordinal outputs -- rankings and exclusions, never percentages -- and any result must be checked for stability under plausible re-weighting.
|
||||
|
||||
These three requirements admit essentially one procedure:
|
||||
|
||||
\begin{definitionbox}[Architecture--application fit]
|
||||
The \emph{architecture--application fit} $\mathrm{fit}(a,p)$ is an ordinal aggregate of the dimension-wise comparison of $R(a)$ and $C(p)$, expressed on the same five-step scale $\{++, +, \circ, -, --\}$ and determined by a deliberately \textbf{non-compensatory, three-stage procedure}:
|
||||
\begin{enumerate}
|
||||
\item \textbf{Knock-out screening.} Hard constraints $K(a)$ eliminate patterns before any scoring; a violated constraint cannot be averaged away. The \emph{workload-shape gate} belongs to this stage: if $S(p)$ does not match the dominant $S(a)$, the pattern cannot be the dominant structure of the class's core -- its cell is capped at $\circ$ (subsystem role); it may reach $+$ only where it carries a \emph{constitutive} subsystem of an explicitly shape-hybrid class, and it falls to $-$/$--$ where it would actively harm the class's binding scenarios.
|
||||
\item \textbf{Veto rule on High-weight dimensions.} If $c_i(p) = --$ on any dimension that $a$ weights High, $\mathrm{fit}(a,p)$ is capped at $-$; if $c_i(p) = -$, the cap is $\circ$ -- \emph{unless a documented mitigation exists} (a tactic or hybrid composition with production evidence), in which case the cell says so explicitly and the cap is lifted.
|
||||
\item \textbf{Holistic ordinal reading with mandatory sensitivity analysis.} The surviving candidates are ranked by their support of the High-weight dimensions; conflicts on Medium-weight dimensions are noted and can downgrade a rating by one step when they cluster. The result is a \emph{ranking with exclusions}, never ``pattern A is $12\,\%$ better''. If the ranking flips under plausible weight variation, that instability is not noise -- it marks a genuine trade-off point in the ATAM sense and must be escalated to scenario-based analysis \citep{kazman2000atam}.
|
||||
\end{enumerate}
|
||||
\end{definitionbox}
|
||||
|
||||
``Non-compensatory'' is the key property, and it mirrors the documented failures of Section~\ref{sec:decisionproblem}: Prime Video's serverless design was excellent on elasticity and deployability, and none of that compensated for the cost structure its workload shape imposed \citep{kolny2023primevideo}. Stage~2's mitigation clause keeps the rule honest: a veto can be lifted, but only by a \emph{documented} tactic or hybrid with production evidence -- ``pod-sharded replication of the monolith'' \citep{westeinde2019deconstructing} or ``event-driven edges around an ACID core'' -- never by optimism.
|
||||
|
||||
\begin{examplebox}[Same class -- opposite structures: why constraints decide within the feasible set]
|
||||
Core banking admits \emph{opposite} viable architectures. LMAX runs a deterministic, single-threaded, event-sourced matching core processing six million orders per second on one JVM thread \citep{fowler2011lmax}; Monzo runs the same domain on roughly $2{,}800$ Go microservices \citep{sewell2024monzo}. Both satisfy the class's binding scenarios (zero booking loss, full auditability). The lesson: $R(a)$ alone does not force one pattern -- it defines a \emph{feasible set}, and the constraints and organisational context in $K(a)$ decide within it. A matching theory that pretended to compute a single winner from the profile alone would be falsified by this pair; a theory that outputs a ranked feasible set plus the constraints that discriminate is confirmed by it.
|
||||
\end{examplebox}
|
||||
|
||||
\subsection{The mechanics on a real case: matching the advisory platform}
|
||||
\label{subsec:minimatch}
|
||||
|
||||
A three-stage procedure reads abstract until it runs. So run it -- once, small, end to end. The demand side is $R(\text{C10})$, the advisory-platform profile assembled in Section~\ref{subsec:reqassembled}: High on D6, D7, D9, D10, D12; shape hybrid; EU AI Act and GDPR in $K$. Against it we hold three deliberately contrasting candidates from Table~\ref{tab:patternpreview}: the layered monolith (L), the modular monolith (MM), and microservices (MS).
|
||||
|
||||
\textbf{Stage 1 -- knock-out and shape gate.} $S(\text{C10})$ is explicitly hybrid: an interactive advisory dialogue at the core, batch and asynchronous pipelines (indexing, evaluation runs) beside it. All three candidates are natively interactive, so all three pass the gate \emph{for the core} -- the pipelines will be carried by PF- and EDA-shaped subsystems in any of the three designs, since hybrids are the normal case (Section~\ref{subsec:matrixstatus}). Nor does any hard constraint in $K(\text{C10})$ eliminate a candidate outright: the EU AI Act's logging and human-oversight duties \citep{eu2024aiact} are satisfiable in all three -- though note, for stage 3, that they \emph{favour} structures in which every model call flows through one auditable path.
|
||||
|
||||
\textbf{Stage 2 -- vetoes on the High dimensions.} Now the High set $\{$D6, D7, D9, D10, D12$\}$ interrogates each survivor, using the capability ratings previewed in Table~\ref{tab:capexamples} and derived in full in Part~\ref{part:patterns}. \emph{L:} the layered monolith rates $-$ on High-weighted D7 -- the veto rule caps it at $\circ$ unless a documented mitigation exists, and at C10's extreme change rate of models, prompts, and frameworks there is none: technical layers give the non-deterministic component no boundary, no queue, and no measurement point -- the three things it needs most. D9 is a second $-$ on a High dimension, and D12 offers only $\circ$; two unmitigated vetoes that cluster push the stage-3 reading one step below the cap, to $-$. \emph{MS:} microservices rate $--$ on High-weighted D10, which would cap the cell at $-$ -- but here the mitigation clause earns its keep. C10's D10-High targets \emph{per-request AI cost} (tokens, GPU), which dominates infrastructure cost and is governed at a gateway -- a concern orthogonal to distribution -- so the platform-cost $--$ relaxes to $\circ$ rather than $-$. What stops MS from rising further is stage 3's holistic reading: synchronous service chains multiply seconds-scale LLM latency and failure rates \citep{nygard2018release}, and the pattern's signature payoff, team scaling, sits on Low-weighted D11 -- for a student-sized team the microservice premium buys nothing \citep{fowler2015premium}. \emph{MM:} no veto fires at all -- the modular monolith rates $+$ or better on every dimension of the High set, and its one structural $-$ (D5, blast radius) is Medium-weighted and mitigated by replicated instances.
|
||||
|
||||
\textbf{Stage 3 -- ordinal reading.} MM leads the High set outright: D6 $+$, D7 $+$, D9 $+$, D10 $++$, D12 $+$. And one composition improves it further: applying HX as the internal discipline of the monolith raises D9 and D12 to $++$ -- the LLM becomes an adapter on a port, mockable in hermetic tests, swappable on provider deprecation, guarded by contract validation \citep{cockburn2024hexagonal, evans2003ddd}. The hexagonal modular monolith is therefore the primary recommendation -- and it is exactly the architecture of the course project. Table~\ref{tab:minimatch} compresses the whole computation.
|
||||
|
||||
\begin{table}[htbp]
|
||||
\centering
|
||||
\caption{The mini-match: $R(\text{C10})$ against three contrasting candidates. Rows are the five High-weight dimensions of C10 with the capability ratings $c_i(p)$; the verdict row is the architecture--application fit, identical to the C10 row of the full matrix (Table~\ref{tab:fitmatrix}).}
|
||||
\label{tab:minimatch}
|
||||
\footnotesize
|
||||
\begin{tabular}{@{}p{3.6cm}p{3.0cm}p{3.6cm}p{3.6cm}@{}}
|
||||
\toprule
|
||||
\textbf{High dimension of C10} & \textbf{L} & \textbf{MM ($+$ HX inside)} & \textbf{MS} \\
|
||||
\midrule
|
||||
D6 Security \& auditability & $+$ & $+$ & $\circ$ \\
|
||||
D7 Evolvability & $-$ \emph{(veto)} & $+$ & $++$ \\
|
||||
D9 Testability \& deployability & $-$ \emph{(veto)} & $+$ ($++$ with HX) & $+$ \\
|
||||
D10 Operating cost & $++$ & $++$ & $--$ \emph{(veto)} \\
|
||||
D12 AI integrability & $\circ$ & $+$ ($++$ with HX) & $\circ$ \\
|
||||
\midrule
|
||||
Stage-2 outcome & two unmitigated vetoes, clustering & no veto & D10 veto relaxed: per-request AI cost is a gateway concern, orthogonal to distribution \\
|
||||
\textbf{Verdict $\mathrm{fit}(\text{C10},p)$} & $-$ & $++$ & $\circ$ \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
That is the entire mechanics: one profile, three candidates, three stages, a ranking with exclusions. You have now seen every element of the framework do real work once -- demand constructed (Section~\ref{sec:demand}), supply derived (Section~\ref{sec:supply}), the match computed. Part~\ref{part:fit} runs the same computation for all seventy pairs and adds what a single worked row cannot show: sensitivity analysis, hybrids, and evolution paths.
|
||||
|
||||
\begin{thinkbox}
|
||||
Run the same three candidates against $R(\text{back-office})$ from Section~\ref{subsec:reqassembled} -- High on D4, D6, D7, D8, D10. Which veto fires first, and does the verdict change? Check yourself: microservices now hit two unmitigated $--$ vetoes at once (D8 and D10, both High for this class), while the layered monolith's strengths sit exactly on the class's High set (D4, D8, D10) and only D7 caps it -- liftable by scoping to a small, stable domain -- so the verdicts become L $+$, MM $++$, MS $--$: the same winner, but a radically re-ordered field.
|
||||
\end{thinkbox}
|
||||
|
||||
\subsection{Why the obvious alternative fails}
|
||||
\label{subsec:nomcdm}
|
||||
|
||||
Why is the familiar alternative -- score each pattern $1$--$5$ per criterion, multiply by weights, add up, $V = \sum_i w_i \cdot v_i$ -- not used? It looks rigorous; for this problem it is not. Multi-attribute value theory licenses the additive form only under three conditions \citep{keeney1993decisions}: cardinal (interval) scales, preferential independence of the criteria, and weights interpreted as trade-off rates. All three fail here: the ratings are ordinal by construction (what would ``microservices score $4.3$ on consistency'' mean?); preferential independence is violated by definition -- architecture trade-offs mean precisely that the value of ``scalability $= ++$'' depends on what happens to consistency, so A2 is a statement of preferential dependence; and nobody can state, or defend to an auditor, the rate at which audit-trail quality is exchangeable for deployment frequency.
|
||||
|
||||
The AHP repair \citep{saaty1980analytic, saaty1977scaling} -- pairwise comparisons, eigenvector-derived priorities, a consistency check -- inherits documented defects: adding an alternative (even a copy of an existing one) can \emph{reverse the ranking} of the others \citep{belton1983shortcoming, maleki2013comprehensive}; Dyer's verdict was that the method is ``flawed as a procedure for ranking alternatives'' \citep{dyer1990remarks}; and its verbal nine-point scale collects ordinal intensity judgements but computes with them as ratio-scale numbers -- a reinterpretation measurement theory does not license \citep{banaecosta2008critical}. What this framework keeps from multi-criteria decision analysis is its \emph{explication discipline} -- criteria on the table, weights argued rather than assumed, options compared systematically; what it drops is the arithmetic pretensions.
|
||||
|
||||
\begin{hinweisbox}
|
||||
\textbf{Beware pseudo-precision.} A weighted-sum matrix over ordinal ratings produces numbers -- ``pattern A: $3.87$; pattern B: $3.79$'' -- whose significant digits are artefacts of the procedure, not measurements of anything. Such numbers end discussions that should be had (the $0.08$ gap will not survive any plausible re-weighting) and lend false authority to whatever assumptions were buried in the scores. The professional habit this module trains is the opposite: report \emph{rankings with exclusions}, state the veto behind each exclusion, and run the sensitivity analysis. If the recommendation flips when weights vary plausibly, you have found a genuine trade-off point -- a \emph{finding} to escalate to stakeholders, not an error to hide with more decimals \citep{kazman2000atam, keeney1993decisions}.
|
||||
\end{hinweisbox}
|
||||
|
||||
\subsection{The status of the matrix}
|
||||
\label{subsec:matrixstatus}
|
||||
|
||||
Applying the three-stage procedure to all pairs yields the $7\times 10$ matching matrix of Part~\ref{part:fit} (Table~\ref{tab:fitmatrix}), and one point governs how every cell is to be read: the matrix is an \textbf{explication and communication instrument} -- a compressed, teachable heuristic that forces criteria, weights, and assumptions into the open -- \emph{not} a computation that determines decisions. The rigorous method behind every contested cell is the ATAM: scenario walk-throughs, sensitivity points, trade-off points, risks and non-risks \citep{kazman2000atam, clements2002evaluating}; where money must decide, the CBAM extends it with utility-response curves and ROI \citep{kazman2002making, asundi2001using}. Three honest limits hold throughout: the scales are ordinal (no percentages, ever); the ratings are context-dependent (the serverless cost rating literally inverts with load shape); and hybrids are the normal case, the matrix read \emph{per subsystem}. Part~\ref{part:fit} computes the full matrix and works one decision at full depth -- $\mathrm{fit}(\text{C1}, \text{MS})$ against $\mathrm{fit}(\text{C1}, \text{MM})$, stage by stage, with the sensitivity analysis the mini-match of Section~\ref{subsec:minimatch} deliberately kept small; the two worked examples are complementary, C10 as the introduction, C1 as the deep case.
|
||||
|
||||
\begin{keypoint}
|
||||
The fit function is computed by rules, not arithmetic: knock-out constraints and the workload-shape gate first, then vetoes on High-weight dimensions (liftable only by documented mitigations), then a holistic ordinal reading under mandatory sensitivity analysis. A weighted sum would presuppose cardinal scales, preferential independence, and defensible trade-off rates -- all demonstrably absent -- and would let excellence somewhere compensate for catastrophe where it matters. Non-compensatory matching is not methodological caution; it is how architectural failure actually works.
|
||||
\end{keypoint}
|
||||
|
||||
% ============================================
|
||||
% SECTION: RECORDING AND TESTING THE DECISION
|
||||
% ============================================
|
||||
\section{Recording and Testing the Decision}
|
||||
\label{sec:adr}
|
||||
|
||||
The match produces a decision -- and A1 says the decision, not the diagram, is the primary artefact. Undocumented decisions evaporate: the code shows \emph{what} was built, never \emph{why}, and within a few staff rotations the rationale is gone -- later changes then violate constraints nobody remembers, which is what teams experience as ``legacy'' \citep{jansen2005software}. ISO/IEC/IEEE 42010:2022 draws the normative conclusion: a conformant architecture description \emph{must} record architecture decisions and their rationale (Clause~6.10) \citep{iso2022architecture}. This section presents the lightweight de-facto standard that fulfils the obligation, and the contract that turns the recorded decision into a tested hypothesis (A5).
|
||||
|
||||
\subsection{Architecture Decision Records}
|
||||
\label{subsec:nygard}
|
||||
|
||||
\begin{definitionbox}[Architecture Decision Record (ADR)]
|
||||
An \emph{Architecture Decision Record} is a short text document -- one to two pages, versioned in the code repository, one decision per file -- with the structure proposed by \citet{nygard2011documenting}: \textbf{Title} (numbered noun phrase), \textbf{Status} (proposed / accepted / deprecated / superseded), \textbf{Context} (the forces at play -- technical, political, social, project-specific -- described in value-neutral terms), \textbf{Decision} (active voice: ``We will \dots''), and \textbf{Consequences} (the resulting context, positive \emph{and} negative).
|
||||
\end{definitionbox}
|
||||
|
||||
Three design choices make the format work: \emph{co-location} (ADRs live in the repository, next to the code they govern, not in a wiki that dies with the project office); \emph{brevity} (one decision, one page -- a format cheap enough to be used beats a comprehensive one that is not); and, most importantly, \emph{immutability}: a superseded ADR is never edited or deleted -- a new ADR supersedes it. Immutability is the direct countermeasure to knowledge vaporization: the record of \emph{why we changed our minds} is often more valuable than the current answer.
|
||||
|
||||
The \textbf{MADR} format extends Nygard's structure with explicit \textbf{decision drivers} and \textbf{considered options}, each with pros and cons, plus an optional \textbf{confirmation} section stating how compliance will be verified \citep{kopp2018markdown, madr2024template}. For this module, MADR is the format of choice for a structural reason: ``decision drivers $+$ considered options'' is exactly one row of the matching matrix in narrative long form -- a completed matrix is the tabular compression of many MADRs. Listing~\ref{lst:adr} shows the template instantiated for a decision you will actually face in the course project.
|
||||
|
||||
\begin{lstlisting}[language={}, caption={A MADR-style ADR for the course project: the LLM gateway decision. The Confirmation section is the measurement contract in embryonic form.}, label={lst:adr}]
|
||||
# ADR-011: Route all LLM calls through one gateway port
|
||||
|
||||
Status: accepted (2026-10-14) | supersedes ADR-004
|
||||
Deciders: architecture owner (name), platform team
|
||||
|
||||
## Context and problem statement
|
||||
Advisory features call a commercial LLM. Providers deprecate
|
||||
models on 6-12 month cycles; token costs must be attributable
|
||||
per request; domain logic must stay testable without paid,
|
||||
non-deterministic API calls in the test path.
|
||||
|
||||
## Decision drivers
|
||||
* D7 Evolvability: provider/model change must stay cheap
|
||||
* D9 Testability: hermetic domain tests, no live API calls
|
||||
* D12 AI integrability: per-request cost observability
|
||||
|
||||
## Considered options
|
||||
1. Direct provider-SDK calls from domain services
|
||||
2. One LLM gateway behind a domain-owned port <-- chosen
|
||||
3. Per-feature adapters without a shared gateway
|
||||
|
||||
## Decision
|
||||
We will route every model call through a single gateway that
|
||||
owns prompts, schema validation, retries, model routing, and
|
||||
cost telemetry. Domain code depends only on the port interface.
|
||||
|
||||
## Consequences
|
||||
* Good: provider migration is an adapter task (see ADR-004
|
||||
for the failed alternative); domain tests run against fakes.
|
||||
* Bad: one more runtime component; ~20-50 ms added latency;
|
||||
the gateway is a single point requiring its own SLO.
|
||||
|
||||
## Confirmation (measurement contract)
|
||||
* Static rule: no domain module imports the provider SDK
|
||||
(ArchUnit, CI gate, 0 violations tolerated)
|
||||
* Eval-harness pass rate >= 95% on every model/prompt change
|
||||
* Token cost per request <= budget (p95), monitored continually
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Diagrams for decisions: the C4 model in brief}
|
||||
\label{subsec:c4}
|
||||
|
||||
Decisions need diagrams -- sparingly, and at the right zoom level. The \textbf{C4 model} is a notation- and tool-independent abstraction scheme with four zoom levels -- system context, container, component, code \citep{brown2024c4}; in ISO~42010 terms, a minimalist set of viewpoints \citep{iso2022architecture}. For this module, one level dominates: the seven patterns differ most visibly at \emph{container} level -- a modular monolith is one container with enforced internal boundaries, a microservice system is many, an event-driven system inserts a broker container between them -- so C4 container diagrams are the standard notation for Parts~\ref{part:patterns} and \ref{part:fit}. Where a full documentation skeleton is wanted, the arc42 template provides one, with designated homes for ADRs and quality scenarios \citep{starke2024arc42, starke2023effektive} -- but the artefacts, not the skeleton, carry the method.
|
||||
|
||||
\subsection{The measurement contract}
|
||||
\label{subsec:contract}
|
||||
|
||||
The Confirmation section of Listing~\ref{lst:adr} is the fifth framework element in embryonic form. A5 established that fit decays and must be re-measured; the \textbf{measurement contract} is where the decision commits to that discipline: every ADR ends with the \emph{fitness functions and thresholds that would tell us the decision has failed} \citep{ford2022evolutionary} -- static rules as CI gates, scenario response measures as automated tests, cost and latency budgets as telemetry alarms -- and, in operation, the four DORA metrics test whether the delivery-relevant promises of the structure are being kept \citep{forsgren2018accelerate, dora2023sodr}. When the contract is breached, the response is a documented evolution path (Strangler Fig \citep{fowler2004strangler}) recorded as a superseding ADR, never a silent rewrite. Part~\ref{part:fit} develops the full apparatus: the eight-step decision procedure with the measurement contract as its mandatory final step.
|
||||
|
||||
\begin{keypoint}
|
||||
The ADR is where the framework meets ISO/IEC/IEEE 42010's conformance demand: decisions and rationale \emph{must} be recorded, and the MADR fields ``decision drivers'' and ``considered options'' carry the utility-tree weights and the matrix row into a permanent, auditable, superseding-not-overwriting record. No architecture decision is complete until it exists as an ADR ending in a measurement contract.
|
||||
\end{keypoint}
|
||||
|
||||
\begin{ailinse}[Axis A: an agent drafts the ADR -- a human owns the decision]
|
||||
ADRs are an ideal task for AI assistance and a hard boundary for AI authority. An agent with access to the repository, the utility tree, and the matching matrix can \emph{draft} a competent MADR in minutes: enumerate the options, fill in pros and cons from the capability profiles, propose fitness functions for the confirmation section. Use that. But the decision itself is an act of accountability, not of text generation: a nameable person weighs the drivers, accepts the negative consequences, and answers for them later. And note a second-order effect: agents \emph{read} ADRs and convention files on every run \citep{openai2025agentsmd, anthropic2025claudecode}, so documentation quality is reproduced at machine speed, in whichever direction it points \citep{dora2025aireport} -- a precise ADR corpus is leverage; a stale one is automated misdirection.
|
||||
\end{ailinse}
|
||||
|
||||
% ============================================
|
||||
% SECTION: SUMMARY -- THE RED LINE
|
||||
% ============================================
|
||||
\section{Summary: The Red Line}
|
||||
\label{sec:summary}
|
||||
|
||||
This part built one framework, in one direction: \textbf{demand $\to$ supply $\to$ match $\to$ record $\to$ test.}
|
||||
|
||||
\begin{enumerate}
|
||||
\item \textbf{The problem} (Section~\ref{sec:decisionproblem}): structures differ radically and none dominates, so architecture -- the set of hard-to-reverse structural decisions that determine a system's quality behaviour -- is a matching problem, resting on assumptions A1--A6.
|
||||
\item \textbf{The coordinate system} (Section~\ref{sec:dimensions}): twelve dimensions, ISO-anchored, pattern-discriminating, instrumented -- no instrument, no dimension.
|
||||
\item \textbf{Demand} (Section~\ref{sec:demand}): elicited ASRs $\to$ scenarios with response measures $\to$ utility-tree weights, plus measured workload shape and constraint inventory -- assembled into $R(a)$, worked twice: the AI-native advisory platform and a back-office workflow tool.
|
||||
\item \textbf{Supply} (Section~\ref{sec:supply}): the seven candidate patterns previewed, then tactics analysis, calibrated star ratings with footnoted deviations, production evidence -- assembled into $C(p)$ with its native shape.
|
||||
\item \textbf{Match, record, test} (Sections~\ref{sec:fit}, \ref{sec:adr}): the non-compensatory three-stage procedure yields $\mathrm{fit}(a,p)$ as a ranking with exclusions -- worked once for the advisory platform against three candidates; the decision is recorded as an ADR ending in a measurement contract that operation continuously tests.
|
||||
\end{enumerate}
|
||||
|
||||
Table~\ref{tab:redline} maps each element to where the script instantiates it at scale. Note what the middle column now certifies: this part did not only \emph{define} the loop, it \emph{ran} it once at small scale -- two requirements profiles, a dimension-wise capability preview, one complete match ending in the course-project architecture. A reader who stops here has seen demand, supply, and matching each done concretely; Parts~\ref{part:patterns}--\ref{part:fit} do the same at scale.
|
||||
|
||||
\begin{table}[htbp]
|
||||
\centering
|
||||
\caption{The five framework elements, where this part constructed them, and where the script instantiates them at scale.}
|
||||
\label{tab:redline}
|
||||
\footnotesize
|
||||
\begin{tabular}{@{}p{3.4cm}p{4.4cm}p{6.2cm}@{}}
|
||||
\toprule
|
||||
\textbf{Framework element} & \textbf{Constructed in} & \textbf{Instantiated at scale} \\
|
||||
\midrule
|
||||
Twelve dimensions $D_1$--$D_{12}$ & Section~\ref{sec:dimensions}, Table~\ref{tab:dimensions} & the shared coordinate system of every profile and every matrix cell \\
|
||||
Requirements profile $R(a)$ & Section~\ref{sec:demand} (worked: C10 and back-office; Table~\ref{tab:weightexamples}) & Part~\ref{part:applications}: ten application classes, Table~\ref{tab:requirements} \\
|
||||
Capability profile $C(p)$ & Section~\ref{sec:supply} (previewed: Table~\ref{tab:patternpreview}; worked: EDA/D7, MS/D4, Table~\ref{tab:capexamples}) & Part~\ref{part:patterns}: seven patterns, Table~\ref{tab:capability} \\
|
||||
Fit $\mathrm{fit}(a,p)$ & Section~\ref{sec:fit} (worked: C10 vs.\ L/MM/MS, Table~\ref{tab:minimatch}) & Part~\ref{part:fit}: the $7\times 10$ matrix (Table~\ref{tab:fitmatrix}), hybrids, evolution paths, decision procedure \\
|
||||
ADR and measurement contract & Section~\ref{sec:adr}, Listing~\ref{lst:adr} & Part~\ref{part:fit}: the procedure's mandatory final steps; operation via fitness functions and DORA metrics \\
|
||||
AI extension of the space & D12 (Section~\ref{sec:dimensions}); A6 & Part~\ref{part:ai}: Axis A and Axis B, class C10, the eval harness \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\begin{keypoint}
|
||||
The chain to remember: application class $\to$ scenarios with response measures $\to$ utility tree $\to$ requirements profile $R(a)$ $\to$ non-compensatory matching against capability profiles $C(p)$ $\to$ ADR with rationale $\to$ measurement contract $\to$ operation, and -- because profiles drift -- back around. Architecture, in this module, is not a diagram you draw once; it is a hypothesis you state precisely, decide accountably, and measure for as long as the system lives.
|
||||
\end{keypoint}
|
||||
|
||||
1128
skript/chapters/part2_patterns.tex
Normal file
938
skript/chapters/part3_application_classes.tex
Normal file
@ -0,0 +1,938 @@
|
||||
% ============================================================
|
||||
% AISE502 -- Part III: Requirements Profiles:
|
||||
% The Ten Application Classes
|
||||
% ============================================================
|
||||
|
||||
\part{Requirements Profiles: The Ten Application Classes}
|
||||
\label{part:applications}
|
||||
|
||||
% ============================================
|
||||
% SECTION: APPLICATION CLASSES AS REQUIREMENTS PROFILES
|
||||
% ============================================
|
||||
\section{Application Classes as Requirements Profiles}
|
||||
\label{sec:appclass-intro}
|
||||
|
||||
Part~\ref{part:patterns} characterised the supply side of the matching problem: seven architectural patterns, each described by a capability profile $C(p)$ over the twelve dimensions of Table~\ref{tab:dimensions}. This part characterises the demand side -- and if architecture selection is a matching problem, the operational consequence of Assumptions A2 and A3 in Part~\ref{part:foundations}, then the demand side must be described in the \emph{same} vocabulary and at the \emph{same} resolution as the supply side. A statement such as ``we are building a banking system'' carries almost no architectural information; a statement such as ``an instant payment must reach confirmed finality in under ten seconds end-to-end, with zero transaction loss, under a regulator-enforced audit obligation'' carries almost all of it. The unit that packages such statements is the \emph{application class}.
|
||||
|
||||
\begin{definitionbox}[Application class]
|
||||
An \emph{application class} is a recurring bundle of architecturally significant requirements (ASRs): a set of dominant quality attribute scenarios with \emph{typical response measures}, a characteristic \emph{workload shape} with its quantitative signature, and a \emph{regulatory frame} that acts as a set of hard constraints \citep{bass2021software, chen2013characterizing}. Formally, a class $a$ is described by its requirements profile
|
||||
\[
|
||||
R(a) = \bigl(w_1(a), \ldots, w_{12}(a);\; S(a);\; K(a)\bigr),
|
||||
\]
|
||||
where $w_i(a) \in \{\text{H}, \text{M}, \text{L}\}$ weights profile dimension $D_i$, $S(a)$ is the dominant workload shape, and $K(a)$ is the set of hard constraints (see the formal model in Part~\ref{part:foundations}).
|
||||
\end{definitionbox}
|
||||
|
||||
Two pieces of method recall are needed before the catalogue begins, because every class section uses them: where the weights come from, and what the shape and constraint elements do.
|
||||
|
||||
\subsection{Where the weights come from: utility trees, not opinions}
|
||||
\label{subsec:weights-origin}
|
||||
|
||||
The weights $w_i(a)$ are not editorial judgements. Assumption A4 states that a quality attribute becomes decision-relevant only as a six-part scenario -- source, stimulus, environment, artifact, response, response measure -- and that architecturally significant requirements are empirically vague and implicit and must be elicited systematically \citep{bass2021software, chen2013characterizing}. The elicitation instruments are the Quality Attribute Workshop \citep{barbacci2003quality} and the \emph{utility tree} of the ATAM method, in which each scenario leaf is rated on the pair (business importance, achievement difficulty), each on \{H, M, L\} \citep{kazman2000atam}. The (H,\,H) leaves of a class's characteristic utility tree \emph{are} the High weights of $R(a)$. A weight in this part is therefore a compressed empirical claim: ``systems of this class recurrently produce (H,\,H) scenario leaves on this dimension.'' Each class section makes that claim auditable: it leads with the class's documented challenges -- incidents, production numbers, statutory obligations -- and states two to three \emph{binding scenarios} with response measures, of the kind that populate the (H,\,H) region of the class's utility tree.
|
||||
|
||||
The semantics of the three weight levels follow the formal model of Part~\ref{part:foundations} and are deliberately asymmetric:
|
||||
|
||||
\begin{itemize}
|
||||
\item \textbf{H (High)} -- the dimension carries binding scenarios; it exercises \emph{veto power}. If a pattern's capability rating on an H-weighted dimension is $--$, the fit of that pattern is capped at $-$; if the rating is $-$, the cap is $\circ$ -- unless a documented mitigation with production evidence exists, in which case the matrix cell in Part~\ref{part:fit} says so explicitly.
|
||||
\item \textbf{M (Medium)} -- the dimension matters and is measured, but conflicts on it are noted rather than vetoed; clustered Medium conflicts can downgrade a fit rating by one step.
|
||||
\item \textbf{L (Low)} -- the dimension does not discriminate for this class; effort spent optimising it is, for this class, waste.
|
||||
\end{itemize}
|
||||
|
||||
\begin{hinweisbox}
|
||||
H does not mean ``more important than M in a weighted sum''. There is no weighted sum: the profiles are ordinal, and the aggregation in Part~\ref{part:foundations} is deliberately non-compensatory \citep{keeney1993decisions}. An H weight is a \emph{veto trigger}, not a coefficient. Ten excellent Medium ratings cannot buy back one violated High-weighted dimension -- exactly as no amount of feature velocity buys back a double-posted booking in a ledger.
|
||||
\end{hinweisbox}
|
||||
|
||||
\subsection{Workload shape and hard constraints}
|
||||
\label{subsec:shape-constraints}
|
||||
|
||||
$S(a)$, the dominant workload shape, is the second load-bearing element of a profile. Four shapes recur: \emph{interactive} request/response, \emph{continuous stream}, \emph{scheduled batch}, and explicitly \emph{hybrid} combinations. The shape gate of the decision procedure (Part~\ref{part:foundations}) operates on it: a pattern whose native shape does not match the dominant $S(a)$ cannot be the dominant structure of the class's core, however attractive its other ratings. Each shape carries a quantitative signature -- read/write ratio, load pattern, latency budget, data volume, change rate -- and the class sections report these signatures with documented production numbers, because a workload claim without a number is as unfalsifiable as a scalability requirement without one.
|
||||
|
||||
$K(a)$, the set of hard constraints, is where regulation enters the theory. Constraints are \emph{knock-out filters}, not weights: a pattern or deployment form that violates a constraint is excluded before any scoring and can never be averaged away \citep{keeney1993decisions}. For the classes in this catalogue the constraints are predominantly regulatory -- BCBS~239 risk-data aggregation \citep{bcbs2013rdarr}, FINMA Circular 2023/1 \citep{finma2023oprisk}, DORA \citep{eu2022dora}, PCI~DSS v4.0 \citep{pcissc2022pcidss}, the EU AI Act \citep{eu2024aiact} -- plus organisational facts (team size and skills, mandated platforms, budget). Regulation, in this theory, is not a compliance afterthought: it is a first-class architectural requirement that translates directly into structure -- immutable journals, scope zoning, data classification at module boundaries, logging obligations for AI components.
|
||||
|
||||
\begin{keypoint}
|
||||
An application class is not an industry label; it is an ASR bundle. The weights of its requirements profile are derived from the (H,\,H) leaves of its characteristic utility tree; its workload shape gates which patterns can carry its core; its regulatory constraints knock candidates out before scoring begins. One organisation typically operates \emph{several} classes at once -- a bank runs a C1 booking core, C3 back-office workflows, C6 overnight risk runs, C7 reporting, and increasingly a C10 advisory layer -- which is why the fit matrix of Part~\ref{part:fit} is read per subsystem, never per company logo.
|
||||
\end{keypoint}
|
||||
|
||||
\subsection{A map of the ten classes}
|
||||
\label{subsec:classmap}
|
||||
|
||||
Two variables discriminate more strongly between the classes than any others: the dominant workload shape and the consistency semantics that the class core requires. Figure~\ref{fig:classmap} places the ten classes on these two axes. The horizontal axis is not a continuum in the metric sense -- consistency models are qualitatively distinct \citep{kleppmann2017designing, vogels2009eventually} -- but it is ordinally meaningful: from strict ACID on the left, through hybrid and per-subsystem splits, to eventual consistency on the right. Two classes sit at semantics that are neither ACID nor eventual: C6 requires \emph{reproducibility} (``identical inputs and seeds yield bit-identical outputs''), and C7 requires \emph{freshness by refresh contract} (``consistent as of yesterday 24:00'') -- a third family of consistency semantics that Sections~\ref{sec:c6} and~\ref{sec:c7} develop.
|
||||
|
||||
\begin{figure}[htbp]
|
||||
\centering
|
||||
\resizebox{\textwidth}{!}{%
|
||||
\begin{tikzpicture}[
|
||||
x=1cm, y=1cm,
|
||||
classnode/.style={rectangle, draw, rounded corners=3pt, minimum width=2.0cm, minimum height=0.85cm, align=center, font=\scriptsize\sffamily, line width=0.8pt},
|
||||
inter/.style={classnode, fill=bankblue!15, draw=bankblue},
|
||||
stream/.style={classnode, fill=bankgreen!15, draw=bankgreen},
|
||||
batchn/.style={classnode, fill=gray!15, draw=gray!60!black},
|
||||
hybridn/.style={classnode, fill=projteal!15, draw=projteal, font=\scriptsize\sffamily\bfseries},
|
||||
bandlabel/.style={font=\scriptsize\sffamily\bfseries, anchor=west, text=gray!50!black},
|
||||
axislabel/.style={font=\scriptsize\sffamily, text=gray!50!black}
|
||||
]
|
||||
% --- workload-shape bands ---
|
||||
\fill[gray!6] (0,6.0) rectangle (13.6,8.7);
|
||||
\fill[gray!12] (0,4.1) rectangle (13.6,6.0);
|
||||
\fill[gray!6] (0,2.2) rectangle (13.6,4.1);
|
||||
\fill[gray!12] (0,0.3) rectangle (13.6,2.2);
|
||||
\node[bandlabel] at (0.15,8.45) {interactive request/response};
|
||||
\node[bandlabel] at (0.15,5.75) {continuous stream};
|
||||
\node[bandlabel] at (0.15,3.85) {scheduled batch};
|
||||
\node[bandlabel] at (0.15,1.95) {hybrid: interactive + batch/async};
|
||||
% --- consistency axis ---
|
||||
\draw[-{Stealth[length=2.5mm]}, thick, gray!60!black] (0,0) -- (13.6,0);
|
||||
\foreach \x in {1.7,5.6,9.2,12.5} \draw[gray!60!black, thick] (\x,0) -- (\x,0.12);
|
||||
\node[axislabel, anchor=north] at (1.7,-0.1) {strict ACID};
|
||||
\node[axislabel, anchor=north] at (5.6,-0.1) {hybrid (split by subsystem)};
|
||||
\node[axislabel, anchor=north] at (9.2,-0.55) {causal / per-key / by contract};
|
||||
\node[axislabel, anchor=north] at (12.5,-0.1) {eventual};
|
||||
\node[axislabel, anchor=north] at (6.8,-1.1) {consistency semantics required by the class core (guarantee weakens $\rightarrow$)};
|
||||
% --- interactive band ---
|
||||
\node[inter] at (1.7,7.7) {C1 core banking\\ \tiny ACID ledger};
|
||||
\node[inter] at (1.7,6.6) {C4 ERP\\ \tiny + batch runs};
|
||||
\node[inter] at (4.0,7.7) {C3 back-office};
|
||||
\node[inter] at (5.6,6.7) {C5 e-commerce\\ \tiny checkout ACID, catalogue eventual};
|
||||
\node[inter] at (9.2,7.6) {C9 collab/messaging\\ \tiny connection-stateful, causal per channel};
|
||||
\node[inter] at (12.2,6.7) {C2 social/content\\ \tiny stale feed acceptable};
|
||||
% --- stream band ---
|
||||
\node[stream] at (10.9,5.0) {C8 IoT streaming\\ \tiny event time, exactly-once state};
|
||||
% --- batch band ---
|
||||
\node[batchn] at (7.3,3.2) {C6 simulation/batch\\ \tiny reproducible (seeds)};
|
||||
\node[batchn] at (10.3,3.2) {C7 DSS/BI\\ \tiny fresh by refresh contract};
|
||||
% --- hybrid band ---
|
||||
\node[hybridn] at (5.6,1.25) {C10 AI-native advisory\\ \tiny index eventual, audit path ACID};
|
||||
\end{tikzpicture}}%
|
||||
\caption{The ten application classes located by dominant workload shape $S(a)$ (horizontal bands) and by the consistency semantics their core requires (horizontal axis). Positions are qualitative and follow the consolidated requirements table (Table~\ref{tab:requirements}) and its footnotes; C1 and C2 sit at opposite ends of the consistency axis within the same band -- the didactic mirror pair of this part. C10, the course project, is the only class whose \emph{shape} is constitutively hybrid.}
|
||||
\label{fig:classmap}
|
||||
\end{figure}
|
||||
|
||||
\subsection{How to read the class sections}
|
||||
\label{subsec:howtoread}
|
||||
|
||||
Each of the following ten sections speaks the same rhythm, and it is the rhythm of Part~\ref{part:patterns} turned around -- there, a topology was priced across the twelve dimensions; here, a set of requirements is built up until the weights on those same dimensions follow. Each section opens with a plain leading question in italics and a characterisation with everyday examples; then comes \emph{the challenges it brings} -- the documented incidents, production numbers, and statutory obligations that generate the class's binding scenarios, each challenge tied explicitly to the dimension(s) it stresses; then \emph{the requirements profile} -- a twelve-row table that derives the weights from those challenges, cell-identical to the class's column in the consolidated table (Table~\ref{tab:requirements}, assembled at the end of this part once all ten classes have been seen); and finally \emph{what real systems chose -- and why} -- documented production architectures and open-source reference systems, read through the capability profiles of Part~\ref{part:patterns} (Tables~\ref{tab:cap-l}--\ref{tab:cap-sl}), closing with the class's primary and secondary recommendation. The order is the point: challenges first, weights after, structures last -- examples first, generalisation after. The formal matching of the profiles against Table~\ref{tab:capability} is the subject of Part~\ref{part:fit}; every closing recommendation in this part is a preview that Part~\ref{part:fit} recomputes through the three-stage procedure.
|
||||
|
||||
\begin{hinweisbox}
|
||||
Classifying a concrete system as an instance of one of these classes is step~(i) of the decision procedure in Part~\ref{part:foundations} -- and it is a \emph{hypothesis about the system's ASR bundle}, to be inherited and then corrected against elicited scenarios, never a verdict. Real systems blend classes; the blend, not the label, is what the utility tree must capture.
|
||||
\end{hinweisbox}
|
||||
|
||||
\begin{thinkbox}
|
||||
Take three software systems you have used this week -- for instance your e-banking app, a messaging tool, and a streaming service. Which application classes do they instantiate? Which single quality attribute scenario, with which response measure, would you nominate as each system's most binding requirement? Where would a failure of that scenario become visible first: in revenue, in a regulator's report, or in user churn?
|
||||
\end{thinkbox}
|
||||
|
||||
% ============================================
|
||||
% SECTION: C1 CORE BANKING / TRANSACTION SYSTEMS
|
||||
% ============================================
|
||||
\section{C1 -- Core Banking / Transaction Systems}
|
||||
\label{sec:c1}
|
||||
|
||||
\emph{A payment is booked twice, or not at all: which of the two can a bank survive?} Neither -- and that double impossibility is the class in one sentence. The class comprises systems of record for accounts, payments, and positions: the booking core of a bank, a payment-clearing platform, an exchange's matching and settlement layer -- the machinery behind your e-banking balance, the card authorisation at a supermarket till, the salary that arrives on the 25th. Its defining property is that a lost or double-posted booking event is an \emph{existential} defect -- it creates or destroys money -- whereas unavailability is expensive but reversible. Double-entry bookkeeping demands atomic, serialisable transactions over the ledger; this is the classical ACID territory \citep{kleppmann2017designing}. And auditability is not a preference but a regulator-enforced obligation: every state change must be journaled and reconstructable, which is why event-sourced journals and ledger data models fit this class naturally.
|
||||
|
||||
\subsection{The challenges it brings}
|
||||
|
||||
Start with the sums at stake. The Swiss Interbank Clearing system settles on average roughly CHF~226 billion per day, with peaks above CHF~386 billion \citep{snb2024sic}. At that volume a double-posted or lost booking is not a bug ticket; it is a balance-sheet event -- which is a demand on D4 (consistency and integrity) and D6 (auditability) before any other consideration. Every payment is a write, surrounded by several reads for cover checks, sanctions screening, and fraud scoring, so the class is comparatively \emph{write-critical} -- but the concurrency of those writes against shared accounts, not their raw rate, is what stresses D4.
|
||||
|
||||
The second challenge is a speed spread of six orders of magnitude \emph{within} one class: batch clearing takes hours, instant payments must complete in under 10\,s, card authorisation in 1--2\,s, and exchange trading operates at microseconds. Latency therefore matters everywhere but means something different in each regime -- which is why the profile weights D3 Medium with a footnote rather than High (Table~\ref{tab:requirements}, footnote~3). The SIC5 instant-payment infrastructure is dimensioned for load peaks in the order of 2{,}000 payments per second and is built on a clustered, in-memory replicated-state-machine design \citep{aeron2024six}; VisaNet states a \emph{capacity} of more than 65{,}000 transaction messages per second while its average load lies orders of magnitude below -- a textbook illustration of the difference between capacity dimensioning and normal load \citep{visa2018factsheet}, and the reason D2 (write scalability) is planned, not elastic, in this class. The load pattern itself is constant with deterministic peaks: end of day, end of month, salary runs. Unavailability, meanwhile, is a loss event on national infrastructure with regulator-defined disruption tolerances -- a demand on D5 (availability and fault isolation).
|
||||
|
||||
The third challenge is time. System lifetimes are measured in decades: Reuters reported in 2017 that 220 billion lines of COBOL remained in production use and that 43\,\% of US banking systems were COBOL-based \citep{reuters2017cobol} -- ossification is the class's documented failure mode, which makes D7 (evolvability) a High-weight \emph{requirement} precisely because it is so often unmet. The change-rate signature is bimodal: the booking core (account, posting) changes rarely, the periphery (channels, onboarding, products) changes constantly. Even the interfaces evolve on decade scales: SWIFT carried over one million ISO~20022 messages per day by the end of 2024, with the MT/MX coexistence phase ending in November 2025 -- a multi-year, industry-wide coordinated interface migration \citep{pymnts2024swift}, again a D7 stress. Data are structured, records small, and retention extreme (ten years and more).
|
||||
|
||||
Three binding scenarios compress these challenges into the (H,\,H) region of the utility tree -- Assumption A4 in action, each with its response measure:
|
||||
|
||||
\begin{itemize}
|
||||
\item \textbf{S1 (instant payment finality).} A customer submits an instant payment (stimulus) in normal operation (environment) to the payment core (artifact); the system clears, settles, and posts the payment with confirmed finality (response) in \textbf{under 10 seconds end-to-end, with zero transaction loss} (response measure) -- the operating regime for which the Swiss SIC5 instant-payment infrastructure was built \citep{aeron2024six}. A joint demand on D3, D4, and D5.
|
||||
\item \textbf{S2 (ledger integrity under concurrency).} Concurrent postings against the same account (stimulus) during peak load (environment) leave the double-entry invariant intact (response): \textbf{zero invariant violations, verified by a daily reconciliation job with zero unexplained discrepancies} (response measure) \citep{kleppmann2017designing}. The D4 veto scenario -- and, through the reconciliation job, a demand on D9 (testability).
|
||||
\item \textbf{S3 (audit-trail reconstruction).} An auditor requests the complete causal history of one transaction chosen at random (stimulus) up to ten years back (environment); the system reproduces the full trail (response) \textbf{within one working day, from immutable records} (response measure) -- the operational reading of BCBS~239's aggregation and reporting principles \citep{bcbs2013rdarr}. A demand on D6 and D9.
|
||||
\end{itemize}
|
||||
|
||||
The regulatory frame turns several of these demands into knock-outs. $K(\text{C1})$ is the densest constraint set in the catalogue: BCBS~239 demands demonstrable risk-data aggregation and reporting capability -- a direct architectural requirement on data integration and lineage \citep{bcbs2013rdarr}. In Switzerland, FINMA Circular 2023/1 (in force since 1~January 2024) imposes ICT risk management, the protection of \emph{critical data} in confidentiality, integrity, and availability, and business-continuity requirements with defined disruption tolerances for critical functions \citep{finma2023oprisk}. In the EU, DORA (Regulation (EU) 2022/2554, applicable since 17~January 2025) adds ICT risk management, incident-reporting duties, resilience testing, and a third-party risk register \citep{eu2022dora}; the GDPR governs personal data throughout \citep{eu2016dsgvo}. Read as knock-outs: any candidate structure that cannot guarantee an ACID booking core, an immutable and complete audit journal, and ten-plus-year retention is eliminated \emph{before} any fit scoring -- however well it scales.
|
||||
|
||||
\subsection{The requirements profile}
|
||||
|
||||
With these challenges in mind, the weights follow -- and recall from Part~\ref{part:foundations} that every H exercises veto power in the matching. Table~\ref{tab:req-c1} derives the C1 column of the consolidated table, weight by weight.
|
||||
|
||||
\begin{table}[htbp]
|
||||
\centering
|
||||
\footnotesize
|
||||
\caption{Requirements profile of C1 (core banking) -- column C1 of Table~\ref{tab:requirements}, cell-identical; note numbers refer to that table's footnotes.}
|
||||
\label{tab:req-c1}
|
||||
\begin{tabular}{@{}p{3.4cm}cp{8.3cm}@{}}
|
||||
\toprule
|
||||
\textbf{Dimension} & \textbf{Weight} & \textbf{Why} \\
|
||||
\midrule
|
||||
D1 Read scalability & M & every posting is surrounded by reads (cover checks, sanctions, fraud scoring), but volumes stay modest by consumer-platform standards \\
|
||||
D2 Write scalability \& elasticity & M & load is constant with deterministic peaks; capacity is dimensioned ahead, not scaled elastically -- the VisaNet lesson \\
|
||||
D3 Latency & M & class-internal spread of orders of magnitude, from trading microseconds to clearing hours (note~3) \\
|
||||
D4 Consistency \& integrity & \textbf{H} & a lost or double-posted booking creates or destroys money; double-entry demands serialisable ACID transactions \\
|
||||
D5 Availability \& fault isolation & \textbf{H} & payment rails are national infrastructure; outages are loss events with regulator-defined disruption tolerances \\
|
||||
D6 Security \& auditability & \textbf{H} & the immutable audit journal is a statutory obligation (BCBS~239, FINMA 2023/1, DORA) \\
|
||||
D7 Evolvability & \textbf{H} & lifetimes span decades and ossification is the documented failure mode -- the COBOL evidence \\
|
||||
D8 Simplicity \& TTM & L & the class trades time-to-market for integrity without hesitation \\
|
||||
D9 Testability \& deployability & \textbf{H} & reconciliation and audit-trail reconstruction must be verifiable by construction (S2, S3) \\
|
||||
D10 Operating cost & L & run cost is traded for integrity as willingly as D8 \\
|
||||
D11 Team scaling & M & binding only at neobank organisational scale -- the Monzo condition \\
|
||||
D12 AI integrability & M & fraud and sanctions scoring dock at the edge; the booking path stays deterministic \\
|
||||
\midrule
|
||||
Workload shape $S(a)$ & \multicolumn{2}{l}{interactive (+ batch edges)} \\
|
||||
Hard constraints $K(a)$ & \multicolumn{2}{p{9.0cm}}{BCBS 239; FINMA 2023/1; DORA (EU 2022/2554); ACID booking core; 10+ yr retention} \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\subsection{What real systems chose -- and why}
|
||||
|
||||
Two documented production systems demonstrate that this profile does \emph{not} determine a single pattern. \textbf{LMAX}, a retail-trading platform, processes six million orders per second on a \emph{single} JVM thread: an in-memory, event-sourced, deterministic sequential core surrounded by lock-free ring buffers \citep{fowler2011lmax}. In dimension terms: a single-threaded sequential core is serialisable \emph{by construction} -- the strongest possible answer to the D4 veto -- and deterministic replay of the event journal answers D6 and D9 at once; what it surrenders is elastic write scaling (D2), which the class weights only Medium. \textbf{Monzo}, a UK digital bank, operates roughly 2{,}800 Go microservices (about 1{,}600 in 2020) -- viable only through extreme technological homogeneity: one language, one monorepo, central migration automation \citep{sewell2024monzo, register2020monzo}. Monzo's binding dimension was D11 (team scaling), the one dimension on which the microservices column excels (Table~\ref{tab:cap-ms}); the price -- the $--$ on simplicity and cost that the same column carries -- was paid deliberately, and the D4 risk of sagas in the money path was mitigated by homogeneity and central tooling. Both satisfy banking-grade requirements with opposite structures: LMAX optimises the deterministic core, Monzo optimises organisational scaling -- Assumption A2's trade-off, resolved twice, in opposite directions, within one feasible set.
|
||||
|
||||
The open-source reference is \textbf{Apache Fineract}, the core-banking platform from the Mifos initiative and an Apache top-level project: a Java/Spring backend, API-first and multi-tenant, with relational persistence; through the Mifos/Fineract APIs it serves several hundred institutions with tens of millions of end customers \citep{fineract2024core}. Architecturally it is a modular monolith behind a REST facade -- and the modular-monolith column of Part~\ref{part:patterns} (Table~\ref{tab:cap-mm}) explains why that works: one ACID quantum serves the D4 veto, domain modules absorb the peripheral change rate that D7 demands, and the pattern's weak cell -- $-$ on D5, one process as blast radius -- is mitigated by the classical banking tactic of hot-standby replication. Fineract is a standing counter-example to the assumption that banking at scale implies microservices.
|
||||
|
||||
\begin{examplebox}[LMAX versus Monzo: one profile -- two structures]
|
||||
LMAX and Monzo occupy the same requirements profile -- strict ordering and integrity of financial transactions, regulator-grade auditability -- yet chose structures at opposite ends of the distribution spectrum. The resolution is in the formal model: $R(a)$ constrains the \emph{feasible set}; within it, the hard constraints $K(a)$ and the organisational context (team size, skills, latency regime) select the point. LMAX's binding scenario was microsecond-scale deterministic ordering, which rewards a single-threaded event-sourced core \citep{fowler2011lmax}; Monzo's binding constraint was scaling hundreds of engineers safely, which rewards independent deployability bought with enforced homogeneity \citep{sewell2024monzo}.
|
||||
\end{examplebox}
|
||||
|
||||
\begin{keypoint}
|
||||
$R(a)$ alone does not force one pattern; it defines the feasible set, and constraints decide within it. C1's veto dimensions -- consistency (D4), availability (D5), security and auditability (D6), evolvability (D7), testability (D9) -- eliminate structures that cannot carry an ACID, journaled, decades-lived core; they do not rank the survivors. That is why the LMAX/Monzo pair is evidence \emph{for} the theory, not against it.
|
||||
\end{keypoint}
|
||||
|
||||
\begin{ailinse}[Fraud scoring at the edge of the ledger (Axis B)]
|
||||
AI enters C1 at the periphery, never in the booking path: fraud and sanctions scoring are ML classification components (millisecond-latency, deterministic after training) consulted \emph{before} a posting is committed, and increasingly LLM-based components for case triage and customer communication. The class's D12 weight is Medium precisely because of this placement: the deterministic core must be isolatable from the probabilistic edge, which is a ports-and-adapters discipline (Part~\ref{part:ai}). A fraud model that could abort or mutate a posting mid-transaction would violate the class's D4 veto -- the architectural rule \emph{agents propose, deterministic services decide and book} originates in this class.
|
||||
\end{ailinse}
|
||||
|
||||
Where the weak dimensions of the winning structures bite, documented practice mitigates by \emph{placing} patterns rather than replacing them: the immutable event journal -- EDA's natural artefact -- serves as the regulatory audit trail at the core's edges, and end-of-day clearing, statements, and risk runs are genuine pipes-and-filters batch runs beside the interactive core. In one sentence: the primary recommendation for C1 is a hexagonal modular monolith for the booking core (MM and HX at $++$), with EDA at the edges and PF for the batch runs as secondary -- and microservices only when organisation size forces D11 to High, the Monzo condition; Part~\ref{part:fit} computes this verdict through the three-stage procedure.
|
||||
|
||||
% ============================================
|
||||
% SECTION: C2 SOCIAL MEDIA / CONTENT PLATFORMS
|
||||
% ============================================
|
||||
\section{C2 -- Social Media / Content Platforms}
|
||||
\label{sec:c2}
|
||||
|
||||
\emph{Three hundred thousand people refresh their feed every second while six thousand post: what structure serves the ratio?} The class comprises consumer platforms whose product is a continuously updated content feed: social networks, media-sharing platforms, content communities -- the apps that fill the tram ride. Its defining property is the exact inversion of C1: a feed that is a few seconds \emph{stale} is acceptable; a feed that does not \emph{load} is not. Consistency is explicitly negotiable -- eventual consistency is a design choice, not a defect \citep{vogels2009eventually} -- while read scalability, availability, and feed latency carry the binding scenarios.
|
||||
|
||||
\subsection{The challenges it brings}
|
||||
|
||||
The numbers in the leading question are Twitter's documented 2013 figures, still the canonical calibration: roughly 300{,}000 timeline reads per second against roughly 6{,}000 tweet writes per second -- a ratio of about 50:1 \citep{krikorian2013timelines, hoff2013twitter}. A read path that carries the product at that ratio is a demand on D1 (read scalability) before anything else. The raw write rate is modest; what is not modest is the \emph{fan-out amplification}: one write by an account with millions of followers implies millions of logical deliveries. The naive materialisation (``\texttt{SELECT} over all follows at read time'') was tried and abandoned; the documented solution is fan-out-on-write into in-memory timeline caches (bounded to some 800 entries per home timeline), hybridised with fan-out-on-read for extreme-follower accounts \citep{krikorian2013timelines}. This is the textbook case of the architectural decision \emph{write work versus read work as a function of the read/write ratio} \citep{kleppmann2017designing} -- and the reason D2 stays Medium (Table~\ref{tab:requirements}, footnote~1): the amplification is absorbed by a dedicated fan-out subsystem, not by the write path proper.
|
||||
|
||||
The second challenge is the pace of the product. The feature change rate is among the highest in industry: permanent A/B experiments and daily deployments are the norm -- Instagram exemplifies the signature with roughly 100 deployments per day on a Django codebase of several million lines \citep{woodruff2019static}. That pace is a joint demand on D7 (evolvability), D9 (testability and deployability), and -- once the organisation grows into hundreds of feature teams -- D11 (team scaling). The third challenge is the load pattern: spiky and viral (breaking news, events), with traffic multiplying within minutes, which stresses D5 (availability and fault isolation) and keeps D3 (latency) binding at global peak. Data volume is very large and predominantly unstructured (text, images, video); the platform is long-lived while individual features are short-lived.
|
||||
|
||||
The binding scenarios, with response measures:
|
||||
|
||||
\begin{itemize}
|
||||
\item \textbf{S1 (feed latency).} A user opens the home feed (stimulus) at global peak (environment); the feed renders (response) with \textbf{p99 server-side latency below 200\,ms} (response measure) -- the regime that read-path architectures such as precomputed timelines and edge caches exist to meet \citep{krikorian2013timelines}. A demand on D1 and D3.
|
||||
\item \textbf{S2 (fan-out delivery).} A user posts (stimulus) in normal operation (environment); the post becomes visible to followers (response) \textbf{within 5 seconds for the vast majority of accounts} (response measure) -- Twitter's stated delivery target, missed by design for extreme-follower accounts and compensated by a hybrid fan-out \citep{krikorian2013timelines, hoff2013twitter}. A demand on D2's amplification reading -- and a licence on D4: seconds of staleness are within contract.
|
||||
\item \textbf{S3 (availability under viral spikes).} An external event multiplies traffic within minutes (stimulus); the platform continues serving feeds (response) with \textbf{SLO attainment maintained and blast radius of any single component failure below a declared bound} (response measure). The D5 scenario.
|
||||
\end{itemize}
|
||||
|
||||
The regulatory frame is comparatively light but not empty: the EU Digital Services Act imposes content-moderation, transparency, and systemic-risk duties on platforms, and the GDPR governs profiling and personal data \citep{eu2016dsgvo}. Neither forces a consistency model, which is precisely why this class can trade consistency away -- the mirror image of C1, where regulation forbids exactly that trade. $K(\text{C2})$ therefore knocks out little; the discrimination work in this class is done by the weights, not the constraints.
|
||||
|
||||
\subsection{The requirements profile}
|
||||
|
||||
With the challenges in mind -- the 50:1 ratio, the fan-out amplification, the deployment pace, the viral spikes -- the weights follow; each H is a veto trigger in Part~\ref{part:fit}'s matching. Table~\ref{tab:req-c2} is the C2 column of the consolidated table.
|
||||
|
||||
\begin{table}[htbp]
|
||||
\centering
|
||||
\footnotesize
|
||||
\caption{Requirements profile of C2 (social media / content platform) -- column C2 of Table~\ref{tab:requirements}, cell-identical; note numbers refer to that table's footnotes.}
|
||||
\label{tab:req-c2}
|
||||
\begin{tabular}{@{}p{3.4cm}cp{8.3cm}@{}}
|
||||
\toprule
|
||||
\textbf{Dimension} & \textbf{Weight} & \textbf{Why} \\
|
||||
\midrule
|
||||
D1 Read scalability & \textbf{H} & a ca.~50:1 read/write ratio -- the read path carries the product \\
|
||||
D2 Write scalability \& elasticity & M & raw write rate is modest (ca.~6\,k/s); fan-out amplification is absorbed by the fan-out subsystem (note~1) \\
|
||||
D3 Latency & \textbf{H} & the feed must render at p99 below 200\,ms at global peak or the product feels broken \\
|
||||
D4 Consistency \& integrity & L & a feed seconds stale is invisible; eventual consistency is a design choice \\
|
||||
D5 Availability \& fault isolation & \textbf{H} & an unavailable feed is the defect; viral spikes arrive within minutes \\
|
||||
D6 Security \& auditability & M & moderation and profiling duties (DSA, GDPR) matter but do not shape the core topology \\
|
||||
D7 Evolvability & \textbf{H} & permanent A/B experimentation; features live weeks while the platform lives decades \\
|
||||
D8 Simplicity \& TTM & M & simplicity is welcome but is outbid by feature velocity at scale \\
|
||||
D9 Testability \& deployability & \textbf{H} & ca.~100 deployments per day are impossible without cheap, safe releases \\
|
||||
D10 Operating cost & M & fleet cost matters but never vetoes the read path \\
|
||||
D11 Team scaling & \textbf{H} & hundreds of feature teams must deploy independently -- the documented growth bottleneck \\
|
||||
D12 AI integrability & M & ranking and moderation are ML components, placed off the p99 path \\
|
||||
\midrule
|
||||
Workload shape $S(a)$ & \multicolumn{2}{l}{interactive read-heavy} \\
|
||||
Hard constraints $K(a)$ & \multicolumn{2}{p{9.0cm}}{DSA; GDPR} \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\subsection{What real systems chose -- and why}
|
||||
|
||||
\textbf{Instagram} is the documented monolith-at-scale case: to this day a Django monolith at its core -- several million lines of Python, thousands of endpoints, roughly 100 deployments per day -- scaled horizontally across tens of thousands of identical servers over sharded PostgreSQL and Cassandra \citep{woodruff2019static}. In dimension terms, Instagram exploited exactly the cell that the layered and modular-monolith columns share (Tables~\ref{tab:cap-l} and~\ref{tab:cap-mm}, note~1 of Table~\ref{tab:capability}): stateless replication of the application tier scales \emph{reads} far, so the class's D1 High is servable from a monolith -- a monolith is a potential \emph{organisational} problem, not a read-scaling problem. The trade-off (Assumption A2) bites on D11: one release train throttles hundreds of teams, which is why \textbf{Twitter/X} historically migrated from a Rails monolith to JVM services as organisation and load grew, and why its fan-out architecture is an \emph{event flow} at heart -- fan-out-on-write is publish/subscribe, the EDA column's home turf (Table~\ref{tab:cap-eda}: $++$ on D1, D2, and D7's attach-new-consumers reading) \citep{krikorian2013timelines}. The microservices column (Table~\ref{tab:cap-ms}) serves the same three High weights -- independent scaling of feed, media, and graph services matches D1, independent team deployments match D9 and D11 -- at the documented price of its $--$ on D8 and D10, accepted at this scale.
|
||||
|
||||
The open-source reference is \textbf{Mastodon}: a Ruby-on-Rails monolith with Sidekiq job queues, PostgreSQL (single writer, read replicas), Redis as feed cache and queue backend, and a Node.js streaming API, federated via ActivityPub \citep{mastodon2024docs, warski2022mastodon}. It is didactically ideal because the entire fan-out mechanic -- one Sidekiq job per follower feed -- is inspectable in source code, and the scaling limits of the Rails monolith are documented rather than hidden: Mastodon \emph{is} the secondary recommendation running in public.
|
||||
|
||||
\begin{keypoint}
|
||||
C1 and C2 are mirror images, and the mirror axis is the consistency/availability trade. C1: a stale balance is a defect, an unavailable channel is an inconvenience. C2: a stale feed is an inconvenience, an unavailable feed is the defect. Same twelve dimensions, inverted weights on D1 and D4 -- this contrast pair is the fastest way to internalise that weights, not dimensions, define a class.
|
||||
\end{keypoint}
|
||||
|
||||
\begin{ailinse}[Feed ranking and moderation as runtime AI (Axis B)]
|
||||
In C2, AI is not an add-on but the product's economic engine: feed ranking, recommendation, and content moderation are ML components in the serving path. Architecturally they inherit the class's own discipline -- ranking models are trained in offline pipelines (a C6/C7-shaped subsystem) and served from precomputed feature stores at millisecond latency, so that the p99 feed budget of scenario S1 survives; moderation classifiers sit on the asynchronous ingestion path, where seconds of latency are invisible. The class thereby illustrates a general Axis-B rule developed in Part~\ref{part:ai}: the latency class of the AI component, not its accuracy, decides \emph{where} in the topology it may live.
|
||||
\end{ailinse}
|
||||
|
||||
In one sentence: the primary recommendation for C2 is an EDA + microservices hybrid at organisational scale (MS and EDA at $++$), with a modular monolith as secondary until that scale is \emph{measured}, not assumed -- deployments per developer per day as teams multiply is the deciding measurement; Part~\ref{part:fit} computes this verdict through the three-stage procedure.
|
||||
|
||||
% ============================================
|
||||
% SECTION: C3 BACK-OFFICE / WORKFLOW APPLICATIONS
|
||||
% ============================================
|
||||
\section{C3 -- Back-Office / Workflow Applications}
|
||||
\label{sec:c3}
|
||||
|
||||
\emph{The organisation reorganises again, and by next sprint the approval workflow must follow: which structure absorbs its fortieth process change as cheaply as its first?} The class comprises internal administration systems: case management, approval workflows, HR and procurement processes, departmental record-keeping -- the vacation request, the invoice approval, the onboarding checklist. It is the modal, unglamorous case of industrial software -- systematically under-represented in engineering blogs precisely because nothing about it is spectacular, which is itself the didactic point. Users are employees, numbering dozens to thousands; hours of downtime are usually tolerable; load is low and planable.
|
||||
|
||||
\subsection{The challenges it brings}
|
||||
|
||||
The dominant challenge is not technical at all: it is that the \emph{organisation} keeps changing under the software. The economics are dominated by evolution: maintenance and enhancement consume roughly 40--80\,\% (typically about 60\,\%) of life-cycle cost, mostly for adapting to reorganisations and process changes rather than for repair \citep{glass2002facts, sommerville2020modernes} -- the single strongest demand in this class, and it lands on D7 (evolvability). Lifetimes run 10--20 years and routinely exceed the plan, so the fortieth process change of the leading question is not rhetorical.
|
||||
|
||||
The second challenge is the budget. These systems are built by small internal teams against internal cost centres; every franc spent on platform machinery is a franc unavailable for the next reorganisation. That is a standing demand on D8 (simplicity and time-to-market) and D10 (operating cost) -- and, as the example box below prices out, a standing veto against premium structures. The workload itself generates almost no pressure: CRUD-dominated and moderately read-heavy (an 80/20 rule of thumb), office-hours load, small-to-medium structured data volumes (gigabytes to a few terabytes, often with document attachments) -- D1, D2, and D5 simply do not bind. A single relational ACID database is almost always sufficient; integration demand, however, is high (identity/LDAP, ERP, document management, e-mail).
|
||||
|
||||
The third challenge is correctness with witnesses. Internal control systems demand enforced dual control and a complete audit trail per case -- demands on D4 (transactional case state) and D6 (auditability). The binding scenarios:
|
||||
|
||||
\begin{itemize}
|
||||
\item \textbf{S1 (process change dispersion).} The organisation changes an approval process (stimulus) during normal evolution (environment); the change is implemented and released (response) \textbf{touching no more than the process definition and one module, within one sprint} (response measure) -- change dispersion is the operative evolvability metric here (Table~\ref{tab:dimensions}). The D7 scenario.
|
||||
\item \textbf{S2 (four-eyes integrity).} A clerk approves a case that requires dual control (stimulus); the system enforces the second approval and journals both (response) with \textbf{zero bypasses and a complete, sequential audit trail per case} (response measure) -- the internal-control-system obligation read as a scenario. A demand on D4 and D6.
|
||||
\item \textbf{S3 (interactive adequacy).} A caseworker submits a form (stimulus) during office hours (environment); the system responds (response) \textbf{within 1--2 seconds} (response measure) -- internal users tolerate more latency than customers, but not unboundedly more. D3, weighted Medium.
|
||||
\end{itemize}
|
||||
|
||||
$K(\text{C3})$ reads as knock-outs: the GDPR for employee data \citep{eu2016dsgvo}; statutory retention duties (in Switzerland, Art.~958\emph{f} of the Code of Obligations requires business records to be retained for ten years); internal control systems with enforced dual control; for public administration additionally administrative law and accessibility requirements. A structure that cannot produce a sequential, tamper-evident audit trail per case, or that cannot guarantee retention, is excluded -- constraints that favour simple, journaled, transactional designs.
|
||||
|
||||
\subsection{The requirements profile}
|
||||
|
||||
With the challenges in mind -- evolution dominating cost, budgets that punish premium structures, audit obligations -- the weights follow, each H a veto trigger per Part~\ref{part:foundations}. Table~\ref{tab:req-c3} is the C3 column of the consolidated table.
|
||||
|
||||
\begin{table}[htbp]
|
||||
\centering
|
||||
\footnotesize
|
||||
\caption{Requirements profile of C3 (back-office / workflow) -- column C3 of Table~\ref{tab:requirements}, cell-identical.}
|
||||
\label{tab:req-c3}
|
||||
\begin{tabular}{@{}p{3.4cm}cp{8.3cm}@{}}
|
||||
\toprule
|
||||
\textbf{Dimension} & \textbf{Weight} & \textbf{Why} \\
|
||||
\midrule
|
||||
D1 Read scalability & L & dozens to thousands of internal users at office-hours load \\
|
||||
D2 Write scalability \& elasticity & L & two requests per second at the July vacation peak -- nothing to elasticise \\
|
||||
D3 Latency & M & 1--2\,s form turnaround suffices for employees, but not unboundedly more (S3) \\
|
||||
D4 Consistency \& integrity & \textbf{H} & case state and approvals must be transactionally correct; one skipped approval is an ICS finding \\
|
||||
D5 Availability \& fault isolation & L & hours of downtime are tolerable; the work waits \\
|
||||
D6 Security \& auditability & \textbf{H} & four-eyes enforcement and a sequential, tamper-evident audit trail per case (S2) \\
|
||||
D7 Evolvability & \textbf{H} & ca.~60\,\% of life-cycle cost is evolution, driven by reorganisations (S1) \\
|
||||
D8 Simplicity \& TTM & \textbf{H} & small teams, internal budgets: the simplest adequate structure wins \\
|
||||
D9 Testability \& deployability & M & releases are weekly, not hourly; regression scope stays modest \\
|
||||
D10 Operating cost & \textbf{H} & the budget belongs to the next reorganisation, not to platform staff \\
|
||||
D11 Team scaling & L & one team, often part-time \\
|
||||
D12 AI integrability & L & document extraction decorates the intake edge; the case core stays untouched \\
|
||||
\midrule
|
||||
Workload shape $S(a)$ & \multicolumn{2}{l}{interactive} \\
|
||||
Hard constraints $K(a)$ & \multicolumn{2}{p{9.0cm}}{Retention law (e.g.\ OR 958\emph{f}); internal control systems; GDPR} \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\subsection{What real systems chose -- and why}
|
||||
|
||||
The modal industrial answer is a three-tier or modular-monolith application over one relational database -- and the capability tables of Part~\ref{part:patterns} explain why in two steps. The layered column (Table~\ref{tab:cap-l}) serves D8 and D10 at $++$ -- one artefact, one pipeline, near-zero platform staff -- and its ACID cell serves the D4 veto; its weakness is exactly where this class hurts most, the $-$ on D7, which is why layering fits only small, stable scope. The modular-monolith column (Table~\ref{tab:cap-mm}) buys the same run cost with domain boundaries that absorb the reorganisation-driven change rate -- D7 rises to $+$ while D4 and D10 keep their ratings, at the price of one step on D8 (boundary governance is a permanent line item) -- the Pareto choice when process change is frequent \citep{glass2002facts}.
|
||||
|
||||
The documented reference for the class's other big lever -- externalising the thing that changes most -- is \textbf{Camunda}, whose own product evolution is a miniature architecture lecture: Camunda~7 embeds the process engine as a Java library with relational persistence -- classical and monolith-friendly -- while Camunda~8 rebuilt the engine (Zeebe) as a partitioned, replicated, horizontally scalable distributed system; the migration between the two documents precisely what distribution buys and what it costs \citep{camunda2024zeebe}. Process models follow BPMN~2.0; when a reorganisation arrives, the process definition changes, not the codebase -- scenario S1 met by design. Open-source references for the forms-over-data core include \textbf{Flowable} and the \textbf{Frappe} framework underlying ERPNext, whose metadata-driven DocTypes generate schema, forms, and REST APIs from declarative definitions \citep{frappe2024erpnext}.
|
||||
|
||||
\begin{examplebox}[Why this class punishes distribution]
|
||||
Consider a vacation-approval workflow serving 800 employees, peaking at perhaps two requests per second on the first workday of July. Every quality attribute that microservices buy -- independent scaling, independent deployment by many teams, fault isolation across quanta -- is priced in platform staffing and operational complexity that this workload cannot amortise \citep{fowler2015premium}. The Segment case (Part~\ref{part:foundations}) showed a small team crushed by exactly this premium \citep{noonan2018goodbye}. C3 is the clearest instance of the rule that D8 = H and D10 = H jointly veto premium-priced structures: the class needs its budget for the next reorganisation, not for a service mesh.
|
||||
\end{examplebox}
|
||||
|
||||
\begin{keypoint}
|
||||
C3 is the industry's modal case, and its profile rewards the simplest structure that meets the audit constraints: evolution dominates the cost function \citep{glass2002facts}, so D7 = H; nobody pays for scale that office-hours load never generates, so D8 = H and D10 = H jointly veto every premium-priced structure. Unglamorous is not a defect of this class -- it is its optimum.
|
||||
\end{keypoint}
|
||||
|
||||
\begin{ailinse}[Document extraction and workflow triage (Axis B)]
|
||||
The AI foothold in C3 is unstructured input: incoming invoices, applications, and correspondence are increasingly parsed by LLM-based extraction components that propose structured case data. The class's constraints shape the integration: extraction runs asynchronously before the workflow starts (latency-tolerant), its output is validated against the domain schema before any case is created (the ontology-guard tactic of Part~\ref{part:ai}), and the four-eyes obligation of scenario~S2 extends to AI proposals -- a human confirms, the system journals both the proposal and the confirmation. D12 = L in the profile because none of this touches the class's core; it decorates the intake edge.
|
||||
\end{ailinse}
|
||||
|
||||
In one sentence: the primary recommendation for C3 is a modular monolith with externalised process logic -- a Camunda-class workflow engine behind a port -- (MM at $++$), with layered 3-tier as secondary for small, stable scope (L at $+$); Part~\ref{part:fit} computes this verdict through the three-stage procedure.
|
||||
|
||||
% ============================================
|
||||
% SECTION: C4 ERP / ENTERPRISE CORE SYSTEMS
|
||||
% ============================================
|
||||
\section{C4 -- ERP / Enterprise Core Systems}
|
||||
\label{sec:c4}
|
||||
|
||||
\emph{A sales order must update stock and ledger in the same breath -- for thirty years: what does ``integrated'' actually demand?} The class comprises integrated enterprise systems: order management, inventory, finance, HR, and production planning sharing \emph{one} data model. Its defining property is that the product's value \emph{is} the integration: an order posting updates stock and ledger in one transaction, and every module sees every other module's data consistently. This property -- cross-module ACID transactions over a shared schema -- is exactly what distribution makes structurally expensive.
|
||||
|
||||
\subsection{The challenges it brings}
|
||||
|
||||
The first challenge is the one in the leading question: cross-module atomicity. An order confirmation must commit order, stock reservation, and ledger posting together, with zero half-completed postings, ever -- the hardest possible demand on D4 (consistency and integrity), and one that couples directly to D6 (auditability), because financial-reporting law demands an unbroken, tamper-evident chain from source document to ledger entry. Eventual consistency \emph{between ledger and inventory} is not merely inconvenient -- it contradicts the audit obligation itself.
|
||||
|
||||
The second challenge is time, in its most extreme form in the catalogue. SAP R/3 appeared in 1992, and SAP had to extend mainstream maintenance for the ECC generation to end-2027 (optionally 2030) because customers could not complete their migrations \citep{sap2020maintenance}; ERP life cycles of 20--30 years are the normal case, and replacement projects run for years. Under that horizon, \emph{customising pressure is permanent} -- every enterprise adapts the system to itself -- so the central architectural requirement is a disciplined extension mechanism (modules and add-ons rather than core modification): a demand on D7 (evolvability) whose operative sub-requirement is that extensions survive releases. The change-rate signature is the inverse of the load signature: core processes are stable, customisations churn.
|
||||
|
||||
The third challenge is rhythm rather than volume. The workload is mixed: an OLTP core with deterministic batch peaks (month-end and year-end close, MRP runs, payroll); interactive latency of 1--2\,s suffices (D3 Medium), the batch window is a hard boundary, and load is almost never the problem -- D1 and D2 stay Low, and planned maintenance windows are an accepted norm, which caps D5 at Medium. Data volumes are medium to large, highly structured, with very long retention. The binding scenarios:
|
||||
|
||||
\begin{itemize}
|
||||
\item \textbf{S1 (cross-module posting).} A sales order is confirmed (stimulus) in normal operation (environment); order, stock reservation, and ledger posting commit atomically (response) with \textbf{zero half-completed postings, ever} (response measure). The D4 veto scenario.
|
||||
\item \textbf{S2 (period-end close).} Month-end closing starts (stimulus) at the period boundary (environment); MRP, depreciation, and reporting runs complete (response) \textbf{within the overnight batch window, with a reconciled trial balance at 06:00} (response measure). A demand on the batch edge of the workload shape -- and on D6's reconciliation reading.
|
||||
\item \textbf{S3 (customising survival).} A new release of the core is installed (stimulus) in a system carrying years of customer-specific extensions (environment); the extensions continue to function (response) with \textbf{zero core modifications required and all extension contracts verified before rollout} (response measure) -- the survival condition of 20--30-year life cycles, and the D7 scenario.
|
||||
\end{itemize}
|
||||
|
||||
$K(\text{C4})$: financial-reporting law (Swiss CO, HGB, IFRS), audit-proof archiving duties (GoBD in Germany, GeB{\"u}V in Switzerland), the GDPR for the HR module \citep{eu2016dsgvo}, and SOX control requirements for US-listed groups. Auditability of posting chains is an obligation, not an option: a candidate structure that cannot demonstrate an unbroken, tamper-evident chain from source document to ledger entry is knocked out before scoring.
|
||||
|
||||
\subsection{The requirements profile}
|
||||
|
||||
With the challenges in mind -- cross-module atomicity, audit chains, decades under customising pressure -- the weights follow; every H is a veto trigger (Part~\ref{part:foundations}). Table~\ref{tab:req-c4} is the C4 column of the consolidated table.
|
||||
|
||||
\begin{table}[htbp]
|
||||
\centering
|
||||
\footnotesize
|
||||
\caption{Requirements profile of C4 (ERP / enterprise core system) -- column C4 of Table~\ref{tab:requirements}, cell-identical.}
|
||||
\label{tab:req-c4}
|
||||
\begin{tabular}{@{}p{3.4cm}cp{8.3cm}@{}}
|
||||
\toprule
|
||||
\textbf{Dimension} & \textbf{Weight} & \textbf{Why} \\
|
||||
\midrule
|
||||
D1 Read scalability & L & hundreds to thousands of internal users; load rarely binds \\
|
||||
D2 Write scalability \& elasticity & L & batch peaks are deterministic and planned into the window \\
|
||||
D3 Latency & M & 1--2\,s interactive turnaround suffices; the batch window is the hard boundary \\
|
||||
D4 Consistency \& integrity & \textbf{H} & cross-module ACID postings (order $\to$ stock $\to$ ledger) \emph{are} the product (S1) \\
|
||||
D5 Availability \& fault isolation & M & planned maintenance windows are an accepted ERP norm \\
|
||||
D6 Security \& auditability & \textbf{H} & unbroken, tamper-evident chains from source document to ledger entry (GoBD/GeB{\"u}V, SOX) \\
|
||||
D7 Evolvability & \textbf{H} & 20--30-year lifetimes under permanent customising pressure; the extension mechanism is the survival condition (S3) \\
|
||||
D8 Simplicity \& TTM & M & nobody expects an ERP overnight, but complexity still costs \\
|
||||
D9 Testability \& deployability & M & release trains with extension contracts verified before rollout \\
|
||||
D10 Operating cost & M & material, but never the deciding dimension \\
|
||||
D11 Team scaling & M & several module teams coordinate inside one release \\
|
||||
D12 AI integrability & L & AI assists at the edges; the posting core is untouched \\
|
||||
\midrule
|
||||
Workload shape $S(a)$ & \multicolumn{2}{l}{interactive (+ batch runs)} \\
|
||||
Hard constraints $K(a)$ & \multicolumn{2}{p{9.0cm}}{GoBD/GeB{\"u}V; SOX; IFRS audit chains} \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\subsection{What real systems chose -- and why}
|
||||
|
||||
The open-source references are living proof of the pattern--class alignment. \textbf{Odoo} is a modular Python monolith over PostgreSQL: every business domain (sales, purchasing, accounting, manufacturing) is a module over one shared ORM data model, and modules extend models, views, and logic by inheritance \citep{odoo2024docs}. \textbf{ERPNext}, built on the Frappe framework (Python, MariaDB), is metadata-driven: DocTypes generate schema, forms, and REST APIs \citep{frappe2024erpnext}. Both exhibit strict module boundaries, one deployment, one database, shared transactions -- the modular monolith in its purest industrial form \citep{richards2025fundamentals, su2024modular}. Read against the capability tables: the modular-monolith column (Table~\ref{tab:cap-mm}) answers the D4 veto with one ACID quantum, answers D7 with domain modules and a disciplined extension mechanism -- exactly scenario S3 -- and its $-$ on D5 is absorbed because the class itself weights D5 only Medium (maintenance windows are the accepted norm): a rare case where a pattern's weak cell meets a class that does not care.
|
||||
|
||||
The trade-off analysis (Assumption A2) is starkest in this class in the opposite direction: decomposing an ERP into independently deployable services turns cross-module atomicity into distributed sagas -- microservices' $--$ on D4 (Table~\ref{tab:cap-ms}) meets the class's hardest High, the structurally strongest anti-fit in the whole grid. The occasional community attempts to cut such systems into microservices have remained marginal; the near-absence of viable microservice ERPs after a decade of microservices enthusiasm is itself empirical evidence that integration wins in this class. The mitigation for the survivors runs through the edges: hexagonal ports at the integration peripheries (EDI, banking, tax services) keep customising out of the core, and period-end closing, MRP, and payroll are canonical pipes-and-filters runs inside the batch window.
|
||||
|
||||
\begin{keypoint}
|
||||
C4 sharpens the difference between C3 and itself: both are ACID, interactive, evolution-dominated classes, but C4's value proposition is \emph{integration across modules}, which binds the class to a single transactional quantum. Where C3 could plausibly be several small systems, C4 by definition cannot -- decomposing it into independently deployable services converts its core feature (cross-module atomic postings) into its hardest problem (distributed sagas) \citep{richardson2018microservices}.
|
||||
\end{keypoint}
|
||||
|
||||
\begin{thinkbox}
|
||||
SAP's maintenance extension to 2027/2030 \citep{sap2020maintenance} means thousands of enterprises run an ERP generation older than most of this course's students. Is that an architecture failure, an architecture success, or both? Formulate your answer as a statement about D7 (evolvability): what precisely ossified -- the pattern, the customisations, or the organisation's ability to re-derive its own requirements profile?
|
||||
\end{thinkbox}
|
||||
|
||||
In one sentence: the primary recommendation for C4 is a modular monolith (MM at $++$) -- the strongest pattern--class alignment in the matrix -- with hexagonal discipline within it for the extension ecosystem as secondary; Part~\ref{part:fit} computes this verdict through the three-stage procedure.
|
||||
|
||||
% ============================================
|
||||
% SECTION: C5 E-COMMERCE PLATFORMS
|
||||
% ============================================
|
||||
\section{C5 -- E-Commerce Platforms}
|
||||
\label{sec:c5}
|
||||
|
||||
\emph{A hundred milliseconds of delay costs one per cent of sales, and Black Friday brings fifty times the load: what survives both at once?} The class comprises online retail platforms: catalogue, search, cart, checkout, payment, fulfilment. Its defining property is that downtime and slowness convert \emph{directly} into revenue loss -- and, equally defining, that C5 is the only class in the catalogue whose consistency profile is \emph{hybrid by definition}: the catalogue and recommendations may be stale, inventory is negotiable (oversell compensation), but checkout and payment are strictly ACID.
|
||||
|
||||
\subsection{The challenges it brings}
|
||||
|
||||
The first challenge carries a price tag, which is rare enough to be the class's signature. Two classical calibrations quantify it: Amazon's internal experiment attributing roughly $-1\,\%$ of sales to $+100$\,ms of latency \citep{linden2006data}, and Akamai's 2017 retail study measuring up to $-7\,\%$ conversion per 100\,ms of delay \citep{akamai2017retail}. Latency and availability are revenue variables here -- direct demands on D3 (latency) and D5 (availability), with documented conversion rates as the response measures. The read side is equally commercial: browse-to-buy ratios often exceed 100:1, so the catalogue is a read product -- a demand on D1.
|
||||
|
||||
The second challenge is the most extreme seasonality of all classes: Black Friday/Cyber Monday produces load factors of 10--50$\times$ over normal operation; Shopify reported peaks of roughly 280 million requests per minute and terabytes of traffic per minute for BFCM~2024 \citep{shopify2024bfcm}. Peaks of that shape must be absorbed, not survived -- the D2 (write scalability and elasticity) demand, rehearsed in advance: peak readiness is load-tested at 10$\times$ baseline before the season, which is simultaneously a demand on D9 (testability). The third challenge is the split personality of the data: the checkout must never lie, the catalogue may -- the hybrid consistency that Table~\ref{tab:requirements} encodes as D4 Medium with footnote~6. Data are heterogeneous (semi-structured catalogue, structured orders, media blobs); the business change rate is high (promotions, checkout experiments -- D7), and the integration surface is very wide -- payment service providers, logistics, tax, search, recommendations. The platform lives 10+ years; frontends are short-lived. The binding scenarios:
|
||||
|
||||
\begin{itemize}
|
||||
\item \textbf{S1 (peak elasticity).} Black-Friday traffic arrives at 10--50$\times$ the normal load (stimulus) at the seasonal peak (environment); browsing and checkout continue (response) with \textbf{p95 checkout latency within budget and zero uncompensated oversells at 10$\times$ baseline in the pre-peak load test} (response measure) \citep{shopify2024bfcm}. A joint demand on D2, D5, and D9.
|
||||
\item \textbf{S2 (page latency).} A customer opens a product page (stimulus) in normal operation (environment); the page renders (response) in \textbf{under 1--2\,s, with API calls under 100--300\,ms} (response measure) -- the budgets behind the revenue calibrations above \citep{linden2006data, akamai2017retail}. The D1/D3 scenario.
|
||||
\item \textbf{S3 (payment-scope containment).} A security assessor audits the cardholder-data environment (stimulus); the audit scope (response) is demonstrably \textbf{confined to the tokenised payment subsystem, with third-party scripts on checkout pages inventoried and controlled} (response measure) -- PCI~DSS v4.0 read as a scenario \citep{pcissc2022pcidss}. The D6 scenario.
|
||||
\end{itemize}
|
||||
|
||||
$K(\text{C5})$ turns the third scenario into a knock-out: PCI~DSS v4.0 governs cardholder data -- v3.2.1 was retired on 31~March 2024, and the future-dated requirements became mandatory on 31~March 2025, including MFA for all access to the cardholder-data environment and the control of third-party scripts on checkout pages \citep{pcissc2022pcidss}. The direct architectural implication is \emph{payment-scope minimisation} through tokenisation and outsourcing: the audit scope is a function of the structure, so the structure is chosen to shrink it -- regulation acting on D6 as a structural force. PSD2 governs payment initiation and strong customer authentication \citep{eu2015psd2}; the GDPR governs customer data \citep{eu2016dsgvo}.
|
||||
|
||||
\subsection{The requirements profile}
|
||||
|
||||
With the challenges in mind -- revenue-rated latency, 10--50$\times$ peaks, the designed consistency split, PCI scope -- the weights follow, and this class carries more Highs than any other; each one is a veto trigger (Part~\ref{part:foundations}). Table~\ref{tab:req-c5} is the C5 column of the consolidated table.
|
||||
|
||||
\begin{table}[htbp]
|
||||
\centering
|
||||
\footnotesize
|
||||
\caption{Requirements profile of C5 (e-commerce platform) -- column C5 of Table~\ref{tab:requirements}, cell-identical; note numbers refer to that table's footnotes.}
|
||||
\label{tab:req-c5}
|
||||
\begin{tabular}{@{}p{3.4cm}cp{8.3cm}@{}}
|
||||
\toprule
|
||||
\textbf{Dimension} & \textbf{Weight} & \textbf{Why} \\
|
||||
\midrule
|
||||
D1 Read scalability & \textbf{H} & browse-to-buy ratios beyond 100:1 -- the catalogue is a read product (S2) \\
|
||||
D2 Write scalability \& elasticity & \textbf{H} & 10--50$\times$ seasonal peaks (BFCM) must be absorbed, not survived (S1) \\
|
||||
D3 Latency & \textbf{H} & $+100$\,ms $\approx -1\,\%$ sales: latency carries a documented price tag \\
|
||||
D4 Consistency \& integrity & M & hybrid by definition: catalogue eventual, checkout/payment strictly ACID (note~6) \\
|
||||
D5 Availability \& fault isolation & \textbf{H} & downtime converts to revenue loss at documented rates \\
|
||||
D6 Security \& auditability & \textbf{H} & PCI~DSS v4.0 makes payment-scope minimisation an architecture requirement (S3) \\
|
||||
D7 Evolvability & \textbf{H} & promotions, checkout experiments, and provider churn arrive weekly \\
|
||||
D8 Simplicity \& TTM & M & speed to market matters, but not at the checkout's expense \\
|
||||
D9 Testability \& deployability & \textbf{H} & peak readiness is rehearsed: load tests at 10$\times$ baseline gate the season (S1) \\
|
||||
D10 Operating cost & M & fleet cost matters; the revenue stakes dominate it \\
|
||||
D11 Team scaling & M & organisation-size dependent -- the Shopify-versus-Amazon contrast (note~17) \\
|
||||
D12 AI integrability & M & recommendations and search ranking serve off precomputed stores \\
|
||||
\midrule
|
||||
Workload shape $S(a)$ & \multicolumn{2}{l}{interactive, seasonal} \\
|
||||
Hard constraints $K(a)$ & \multicolumn{2}{p{9.0cm}}{PCI DSS v4.0 scope minimisation; PSD2/SCA} \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\subsection{What real systems chose -- and why}
|
||||
|
||||
\textbf{Shopify} is the canonical case study of the modular monolith at scale: a Ruby-on-Rails core -- one of the largest Rails codebases in existence, roughly 2.8 million lines restructured from 2017 onward into business components with enforced boundaries -- with the \textbf{Packwerk} tool enforcing dependency and visibility rules between components statically, and scaling achieved by \emph{pod sharding} (tenant-wise partitioning of whole application instances) rather than service decomposition \citep{westeinde2019deconstructing, shopify2020under}. In dimension terms: pod sharding lifts the modular monolith's weak D2 cell (Table~\ref{tab:cap-mm}) to carry 280-million-requests-per-minute peaks while the single transactional quantum preserves checkout ACID against the D4 boundary -- a documented mitigation of exactly the two cells where the pattern and the profile rub. Shopify's stated rationale is developer productivity plus transactional consistency.
|
||||
|
||||
The contrast case is \textbf{Amazon} itself, the founding pioneer of service orientation with two-pizza team ownership: the same application class, the opposite structure, driven by organisational scale -- microservices' $++$ on D11 (Table~\ref{tab:cap-ms}) becomes decisive only when team count makes D11 bind, which is precisely what footnote~17 of Table~\ref{tab:requirements} encodes; team size, not traffic, is the deciding variable (Assumption A2 resolved by an organisational constraint, as in C1). Open-source references document the current ``headless/composable'' trend as a \emph{layering} cut, not a microservice cut: \textbf{Saleor} (Python/Django, GraphQL-first API-centric monolith) and \textbf{Medusa} (Node.js, modular commerce modules behind a REST API) \citep{saleor2024github, medusa2024github}. The event-shaped edges -- order flows, inventory updates, search indexing, recommendation training -- are served by EDA and PF beside the core, and flash-sale spikes are the textbook serverless elasticity case, which is why those three columns all earn a $+$ in this row without ever owning the checkout.
|
||||
|
||||
\begin{examplebox}[Hybrid consistency as a designed boundary]
|
||||
The C5 consistency split is not an accident to be tolerated but a boundary to be \emph{designed and documented}: catalogue reads may be minutes stale (cache-friendly, eventually consistent), inventory may oversell within a compensable bound, and the checkout/payment path is ACID with idempotent order creation \citep{kleppmann2017designing, linden2006data}. The measurable contract from the class's central trade-off: p95 checkout latency within budget and zero \emph{uncompensated} oversells during peak-load tests at 10$\times$ baseline. Where exactly the boundary runs -- is the cart eventual or transactional? -- is a genuine ATAM tradeoff point and belongs in an ADR, not in folklore.
|
||||
\end{examplebox}
|
||||
|
||||
\begin{keypoint}
|
||||
C5 is the class where quality attributes carry price tags: latency and availability convert to revenue at documented rates \citep{linden2006data, akamai2017retail}, seasonality defines elasticity (10--50$\times$ peaks \citep{shopify2024bfcm}), and the consistency profile is hybrid \emph{by definition} -- the one class where ``ACID or eventual?'' is answered ``both, along a designed boundary''. Team size, not traffic, decides between the Shopify and the Amazon structure.
|
||||
\end{keypoint}
|
||||
|
||||
In one sentence: the primary recommendation for C5 is a modular monolith with the hybrid consistency profile designed inside it and event-driven edges (MM at $++$), with microservices as secondary at organisational scale and MS/EDA/SL earning their $+$ at the edges; Part~\ref{part:fit} computes this verdict through the three-stage procedure.
|
||||
|
||||
% ============================================
|
||||
% SECTION: C6 SCIENTIFIC SIMULATION / BATCH COMPUTE
|
||||
% ============================================
|
||||
\section{C6 -- Scientific Simulation / Batch Compute}
|
||||
\label{sec:c6}
|
||||
|
||||
\emph{The nightly risk run must reproduce, to the bit, on ten thousand cores by 06:00: what does that demand?} The class comprises compute-dominated batch systems: computational fluid dynamics, Monte-Carlo risk simulation, ML training runs, large-scale data transformation. Its cost function is CPU/GPU-hours; availability in the online sense is irrelevant -- an aborted job is restarted from a checkpoint, not mourned. And correctness has a specific meaning here: \emph{reproducibility}. A simulation whose result cannot be regenerated from versioned inputs, versioned code, and deterministic seeds is scientifically worthless and, for regulated risk models, unlawful to rely on \citep{glasserman2003monte, bcbs2013rdarr}.
|
||||
|
||||
\subsection{The challenges it brings}
|
||||
|
||||
The first challenge is that the interactive vocabulary simply does not apply. There is no read/write ratio; the pattern is read-input $\rightarrow$ compute $\rightarrow$ write-output over immutable datasets. Per-request latency is meaningless; the response measures are \emph{makespan} (hours to weeks) and \emph{batch-window adherence} -- the overnight risk run must publish before start of trading. Throughput therefore reappears in a new reading: as makespan and batch-window compute bursts, which is what D2 High means in this class (Table~\ref{tab:requirements}, footnote~2), while D3 (latency) drops to Low in its footnote-4 reading. Load is planned and queue-based with a utilisation target near 100\,\% -- the economic opposite of the elastic-headroom regimes of C2 and C5 -- and since the bill \emph{is} the compute, cost per simulation is a first-order concern: a direct demand on D10 (operating cost), which queue-based scheduling exists to serve \citep{yoo2003slurm}.
|
||||
|
||||
The second challenge is the reproducibility obligation from the leading question. Bit-identical reruns from versioned inputs, code, and seeds are a scientific duty and, for regulated risk models, a supervisory one -- the demand lands on D9 (testability) in its reproducibility reading (footnote~14) and on D4 (consistency) in the ``as of this run'' semantics that the definition below makes precise (footnote~8). The third challenge is physics: scaling has a measurable ceiling. In CFD practice with OpenFOAM, domain decomposition pays down to roughly 50{,}000--200{,}000 cells per core, below which communication overhead dominates -- a quantifiable instance of Amdahl's law as an architecture boundary \citep{openfoam2024guide, weller1998tensorial}. Monte-Carlo simulation, by contrast, is embarrassingly parallel -- the ideal pipeline case \citep{glasserman2003monte}. Data volumes are large (terabytes to petabytes of result data); the change rate is split -- model code changes research-driven, while numeric kernels are extremely long-lived (Fortran/C++ codes with 30+ years of history), which keeps D7 at Medium. The binding scenarios:
|
||||
|
||||
\begin{itemize}
|
||||
\item \textbf{S1 (batch-window adherence).} The overnight risk run starts (stimulus) after close of business (environment); the full portfolio revaluation completes (response) \textbf{within the batch window, results published before start of trading} (response measure). The D2 scenario in its makespan reading.
|
||||
\item \textbf{S2 (bit-level reproducibility).} A model validator re-executes a historical run (stimulus) months later (environment); the pipeline regenerates the results (response) \textbf{bit-identically from versioned inputs, code, and seeds} (response measure) \citep{glasserman2003monte}. The D9/D4 scenario.
|
||||
\item \textbf{S3 (cost efficiency).} The quarterly compute bill is reviewed (stimulus); cost per simulation and cluster utilisation (response) stay \textbf{within budget at a utilisation target near 100\,\%} (response measure) -- queue-based scheduling exists to meet exactly this measure \citep{yoo2003slurm}. The D10 scenario.
|
||||
\end{itemize}
|
||||
|
||||
\begin{definitionbox}[The third consistency semantics: reproducibility and refresh contracts]
|
||||
Beside ACID (``concurrent operations preserve invariants'') and eventual consistency (``replicas converge, staleness is bounded'' \citep{vogels2009eventually}), the batch world defines a third family of consistency semantics. \emph{Reproducibility} (C6): immutable inputs and idempotent, seeded stages guarantee that a rerun yields the identical result -- consistency ``as of this run''. \emph{Freshness by refresh contract} (C7): consumers see a complete, internally consistent state ``as of the last refresh'' (e.g.\ yesterday 24:00), never a half-updated one. Both are weaker than ACID and stronger than unqualified eventual consistency -- and both are \emph{contracts with response measures}, testable in CI like any other scenario.
|
||||
\end{definitionbox}
|
||||
|
||||
$K(\text{C6})$ in financial applications: internal models are subject to model validation and backtesting under the Basel framework, and the traceability of model runs is audit-relevant -- the BCBS~239 lineage obligation extends into the simulation stack \citep{bcbs2013rdarr}. The knock-out reading: any structure that cannot pin \emph{data version + code version + seed} per run is excluded for regulated risk computation, whatever its throughput. Deterministic seeds are thus a hard constraint, not a nicety.
|
||||
|
||||
\subsection{The requirements profile}
|
||||
|
||||
With the challenges in mind -- makespan and window, reproducibility as law, compute as the bill, communication as the ceiling -- the weights follow; each H is a veto trigger (Part~\ref{part:foundations}). Table~\ref{tab:req-c6} is the C6 column of the consolidated table.
|
||||
|
||||
\begin{table}[htbp]
|
||||
\centering
|
||||
\footnotesize
|
||||
\caption{Requirements profile of C6 (scientific simulation / batch compute) -- column C6 of Table~\ref{tab:requirements}, cell-identical; note numbers refer to that table's footnotes.}
|
||||
\label{tab:req-c6}
|
||||
\begin{tabular}{@{}p{3.4cm}cp{8.3cm}@{}}
|
||||
\toprule
|
||||
\textbf{Dimension} & \textbf{Weight} & \textbf{Why} \\
|
||||
\midrule
|
||||
D1 Read scalability & L & no interactive readers; outputs are files and tables \\
|
||||
D2 Write scalability \& elasticity & \textbf{H} & throughput as makespan and batch-window compute bursts (S1; note~2) \\
|
||||
D3 Latency & L & per-request latency is meaningless; the window is the measure (note~4) \\
|
||||
D4 Consistency \& integrity & M & consistency ``as of this run'': bit-level reproducibility from versioned inputs and seeds (note~8) \\
|
||||
D5 Availability \& fault isolation & L & an aborted job is restarted from a checkpoint, not mourned \\
|
||||
D6 Security \& auditability & M & lineage of regulated model runs is audit-relevant, but there is no online attack surface \\
|
||||
D7 Evolvability & M & model code churns research-driven; numeric kernels live 30+ years \\
|
||||
D8 Simplicity \& TTM & M & orchestration should stay simple; the kernels never are \\
|
||||
D9 Testability \& deployability & \textbf{H} & reproducibility is the operative meaning of testability (S2; note~14) \\
|
||||
D10 Operating cost & \textbf{H} & the cost function \emph{is} CPU/GPU-hours at near-100\,\% utilisation (S3) \\
|
||||
D11 Team scaling & L & small research and engineering teams \\
|
||||
D12 AI integrability & M & training and simulation pipelines host ML natively, at batch cadence \\
|
||||
\midrule
|
||||
Workload shape $S(a)$ & \multicolumn{2}{l}{scheduled batch} \\
|
||||
Hard constraints $K(a)$ & \multicolumn{2}{p{9.0cm}}{Model validation and backtesting (finance); deterministic seeds} \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\subsection{What real systems chose -- and why}
|
||||
|
||||
The dominant form is pipes-and-filters on HPC or batch infrastructure -- and the pipeline column of Part~\ref{part:patterns} (Table~\ref{tab:cap-pf}) reads like a transcript of this class's Highs: immutable inputs and deterministic, idempotent stages give reproducibility (D9) \emph{by construction}, batch scheduling drives utilisation towards the D10 target, and the shape matches the gate that eliminates every interactive pattern outright. \textbf{OpenFOAM} decomposes computational domains via graph partitioning, communicates over MPI, and is scheduled by \textbf{Slurm} as the batch resource manager \citep{openfoam2024guide, yoo2003slurm}; \textbf{OpenMC} is a modern, parallel Monte-Carlo transport code of the same architectural family \citep{romano2015openmc}; data-parallel engines (\textbf{Spark} \citep{zaharia2012resilient}) and DAG orchestrators (\textbf{Airflow} \citep{beauchemin2015airflow}) are the cloud-native incarnations, with Dask/Ray as Python-native alternatives.
|
||||
|
||||
Where the trade-off bites (Assumption A2) is data affinity: distributing a tightly coupled numeric dataflow across expensive boundaries multiplies communication cost. The Amazon Prime Video case from Part~\ref{part:foundations} is this class's cautionary tale in miniature: a tightly coupled processing flow distributed across orchestrator transitions and S3 round-trips per frame, until consolidation into one process cut cost by over 90\,\% \citep{kolny2023primevideo, cockcroft2023prime} -- when inter-stage communication dominates, consolidate, do not distribute. The same logic explains why serverless fan-out earns only a conditional role: embarrassingly parallel, communication-light bursts (Monte-Carlo) fit FaaS elasticity, data-heavy stages recreate the Prime Video cost trap.
|
||||
|
||||
\begin{keypoint}
|
||||
C6 replaces the interactive vocabulary wholesale: the response measures are makespan, batch-window adherence, and cost per simulation; correctness means bit-level reproducibility from versioned inputs and seeds; consistency means ``as of this run''. A structure is a good fit for this class exactly to the degree that it makes these three measurable by construction -- which is why immutable-input pipelines dominate it \citep{glasserman2003monte, yoo2003slurm}.
|
||||
\end{keypoint}
|
||||
|
||||
\begin{projektbox}
|
||||
The course project inherits this class wholesale: the ingestion pipeline (chunking, embedding, indexing) and the \emph{eval pipeline} of the Portfolio Intelligence Platform are C6-shaped subsystems. The C6 discipline transfers literally -- versioned inputs, idempotent stages, deterministic reruns, golden datasets -- and footnote~14 of Table~\ref{tab:requirements} is the bridge: for batch pipelines, \emph{reproducibility is the operative meaning of testability}. When your eval scores change, you must be able to prove whether the model, the prompt, the data, or the pipeline changed. That proof is a C6 property.
|
||||
\end{projektbox}
|
||||
|
||||
In one sentence: the primary recommendation for C6 is pipes-and-filters on HPC/batch infrastructure (PF at $++$), with serverless fan-out as secondary for bursty, communication-light parallel sections; Part~\ref{part:fit} computes this verdict through the three-stage procedure.
|
||||
|
||||
% ============================================
|
||||
% SECTION: C7 DECISION SUPPORT / BI ANALYTICS
|
||||
% ============================================
|
||||
\section{C7 -- Decision Support / BI Analytics}
|
||||
\label{sec:c7}
|
||||
|
||||
\emph{Monday, 08:00: the management dashboard must be complete as of yesterday 24:00 -- and every number must prove where it came from. What delivers that, night after night?} The class comprises data warehouses, BI platforms, and reporting systems. It is an \emph{integration product} over classes C1--C5: it owns almost no data of its own but integrates everyone else's, which makes data quality, lineage, and governance first-class concerns \citep{kimball2013warehouse}. Its consistency semantics are the refresh contract defined in Section~\ref{sec:c6}: ``consistent as of yesterday 24:00'' is a deliberate design choice, not a deficiency.
|
||||
|
||||
\subsection{The challenges it brings}
|
||||
|
||||
The first challenge is the shape of the reads. The load is almost pure read -- but of a specific kind: heavy OLAP scans by \emph{few} users, not point reads by many (Table~\ref{tab:requirements}, footnote~7). That is still a D1 (read scalability) demand, but in a reading of its own -- scan capacity, typically \emph{delegated} to the warehouse engine, a division of labour that shapes the class's whole architecture. Writes are bundled into ELT/ETL windows (D2 Low); load follows office hours with Monday-morning and month-start peaks; the dashboard must render in seconds (D3 Medium), while an hour of downtime is an annoyance, not a loss event (D5 Low).
|
||||
|
||||
The second challenge is the contract from the leading question: the marts must be refreshed within the window and become visible \emph{atomically} -- consumers must never see a half-updated state. That is the freshness-by-refresh-contract semantics (D4 Medium, footnote~10), and its adherence is tracked as a fitness function -- a D9 concern. The third challenge is provenance under interrogation: when a regulator questions a reported risk figure, the platform must trace it back through every transformation to the source systems -- a D6 demand that BCBS~239 hardens into a hard constraint where banking data are involved \citep{bcbs2013rdarr}. And because the warehouse bill is the dominant run cost, cost discipline is the operative FinOps concern -- D10 High. Data volumes are large (terabytes to petabytes), dimensionally modelled -- Kimball's star schema remains the reference methodology \citep{kimball2013warehouse}; the change rate is high at report level, moderate in the core data model (D7 Medium). The binding scenarios:
|
||||
|
||||
\begin{itemize}
|
||||
\item \textbf{S1 (dashboard latency).} A controller opens the standard management dashboard (stimulus) on Monday morning (environment); it renders (response) \textbf{in under 5 seconds} (response measure), with ad-hoc analytical queries in seconds to minutes. The D1/D3 scenario in the class's OLAP reading.
|
||||
\item \textbf{S2 (refresh contract).} The nightly ELT run executes (stimulus); all marts are refreshed (response) \textbf{within the refresh window, atomically visible, with refresh-window adherence tracked as a fitness function} (response measure). The D4/D9 scenario.
|
||||
\item \textbf{S3 (lineage on demand).} A regulator or auditor questions a reported risk figure (stimulus); the platform traces it (response) \textbf{back through every transformation to the source systems, on demand} (response measure) -- BCBS~239 lineage where banking data are involved \citep{bcbs2013rdarr}. The D6 scenario, hardened into $K(a)$ for banks.
|
||||
\end{itemize}
|
||||
|
||||
$K(\text{C7})$: BCBS~239 for banks (risk reporting: accuracy, completeness, timeliness, and demonstrable lineage) \citep{bcbs2013rdarr}; the GDPR (purpose limitation, anonymisation in analyses) \citep{eu2016dsgvo}; sector-specific reporting duties. The knock-out reading: a pipeline whose transformations are not versioned and traceable cannot serve regulated reporting -- lineage is a structural property, retrofitting it is a rebuild.
|
||||
|
||||
\subsection{The requirements profile}
|
||||
|
||||
With the challenges in mind -- OLAP scans, the refresh contract, lineage on demand, the warehouse bill -- the weights follow; each H is a veto trigger (Part~\ref{part:foundations}). Table~\ref{tab:req-c7} is the C7 column of the consolidated table.
|
||||
|
||||
\begin{table}[htbp]
|
||||
\centering
|
||||
\footnotesize
|
||||
\caption{Requirements profile of C7 (decision support / BI analytics) -- column C7 of Table~\ref{tab:requirements}, cell-identical; note numbers refer to that table's footnotes.}
|
||||
\label{tab:req-c7}
|
||||
\begin{tabular}{@{}p{3.4cm}cp{8.3cm}@{}}
|
||||
\toprule
|
||||
\textbf{Dimension} & \textbf{Weight} & \textbf{Why} \\
|
||||
\midrule
|
||||
D1 Read scalability & \textbf{H} & heavy OLAP scans by few users, delegated to the warehouse engine (S1; note~7) \\
|
||||
D2 Write scalability \& elasticity & L & writes are bundled into the nightly ELT window \\
|
||||
D3 Latency & M & dashboards in under 5\,s; ad-hoc queries in seconds to minutes \\
|
||||
D4 Consistency \& integrity & M & freshness by refresh contract -- ``consistent as of yesterday 24:00'' (S2; note~10) \\
|
||||
D5 Availability \& fault isolation & L & a dashboard down for an hour is an annoyance, not a loss event \\
|
||||
D6 Security \& auditability & M & lineage and purpose limitation; BCBS~239 hardens them into $K(a)$ where banking data flow (S3) \\
|
||||
D7 Evolvability & M & report-level churn is high; the core dimensional model moves slowly \\
|
||||
D8 Simplicity \& TTM & M & thin serving keeps the estate simple; the pipeline carries the complexity \\
|
||||
D9 Testability \& deployability & M & refresh-window adherence is tracked as a fitness function (S2) \\
|
||||
D10 Operating cost & \textbf{H} & warehouse compute is the bill; cost discipline is the operative FinOps concern \\
|
||||
D11 Team scaling & L & a data team, not a fleet of feature teams \\
|
||||
D12 AI integrability & M & text-to-SQL docks onto the governed semantic layer, not onto raw tables \\
|
||||
\midrule
|
||||
Workload shape $S(a)$ & \multicolumn{2}{l}{batch + thin serving} \\
|
||||
Hard constraints $K(a)$ & \multicolumn{2}{p{9.0cm}}{BCBS 239 lineage (banks)} \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\subsection{What real systems chose -- and why}
|
||||
|
||||
The documented modern form is a batch/ELT pipeline in front of a thin serving layer: sources $\rightarrow$ orchestrated DAGs (\textbf{Apache Airflow}: scheduler, executor, workers, metadata database; DAGs as code \citep{beauchemin2015airflow, airflow2024docs}) $\rightarrow$ warehouse $\rightarrow$ BI frontend. The ``modern data stack'' is thus architecturally a layered application over a batch pipeline -- and the capability tables of Part~\ref{part:patterns} explain both halves: the pipeline column (Table~\ref{tab:cap-pf}) serves the refresh contract and lineage by construction (versioned transformations, immutable stage outputs -- the D4-footnote-10 and D6 demands), while the layered column (Table~\ref{tab:cap-l}) serves the thin serving tier exactly because that tier delegates the D1-High scans to the warehouse and keeps its own D8/D10 virtues.
|
||||
|
||||
The open-source serving references make the class's low operational demands visible in their own packaging: \textbf{Apache Superset} (Python/Flask, originating at Airbnb) is deliberately a \emph{thin} visualisation layer with no data storage of its own, connecting directly to SQL engines \citep{superset2024platform, airbnb2021superset}; \textbf{Metabase} ships as a single JAR -- a literal monolith, mirroring how little serving infrastructure the class needs \citep{metabase2024docs}. Both delegate scaling to the database: division of labour as an architectural principle. Where the trade-off bites (Assumption A2) is freshness: streaming ingestion (EDA) earns its broker-operations complexity only when the freshness contract measurably tightens below the batch window -- tightening it towards real time is not a tuning exercise but a class change into C8 economics.
|
||||
|
||||
\begin{keypoint}
|
||||
C7 is an integration product over classes C1--C5 whose consistency semantics -- freshness by refresh contract -- is a \emph{designed} third option beside ACID and eventual. The ADR to write is the freshness contract itself; the fitness functions are refresh-window adherence and p95 dashboard latency; and tightening the contract toward real time is not a tuning exercise but a class change -- it drags the system into C8 economics.
|
||||
\end{keypoint}
|
||||
|
||||
\begin{ailinse}[Natural-language analytics (Axis B)]
|
||||
The visible AI frontier in C7 is the natural-language query: ``show me revenue by region, last four quarters'' compiled by an LLM into SQL against the semantic layer. The class profile dictates the containment: the LLM \emph{proposes} a query; the semantic layer's schema and access-control contracts \emph{validate and execute} it -- text-to-SQL against governed models rather than raw tables, so that lineage (scenario~S3) and purpose limitation survive the convenience. The failure mode to design against is silent plausibility: a syntactically valid, semantically wrong query returns confident nonsense. The eval harness of Part~\ref{part:ai} -- golden question/answer sets over a frozen warehouse state -- is the class-appropriate test instrument, and footnote~10's refresh contract is what makes such golden sets stable enough to test against.
|
||||
\end{ailinse}
|
||||
|
||||
\begin{projektbox}
|
||||
The Portfolio Intelligence Platform contains a C7 subsystem: portfolio analytics, exposure aggregation, and report generation over the deterministic data store. Its refresh contract (``analysis as of last completed ingestion'') bounds what the advisory layer may claim -- an answer must never cite data fresher than the index actually is. The freshness contract therefore appears twice in the project's measurement contract: as a pipeline fitness function (C7 discipline) and as a grounding rule for generated answers (C10 discipline).
|
||||
\end{projektbox}
|
||||
|
||||
In one sentence: the primary recommendation for C7 is pipes-and-filters (ELT) feeding a thin layered serving tier -- the canonical hybrid of the row (PF at $++$, with L, MM, and SL at $+$) -- and EDA ingestion as secondary where the freshness contract demands it; Part~\ref{part:fit} computes this verdict through the three-stage procedure.
|
||||
|
||||
% ============================================
|
||||
% SECTION: C8 REAL-TIME / IOT STREAMING
|
||||
% ============================================
|
||||
\section{C8 -- Real-Time / IoT Streaming}
|
||||
\label{sec:c8}
|
||||
|
||||
\emph{The sensors never stop: what ingests the world at the world's own rate, indefinitely -- and stays exactly right when a node dies mid-window?} The class comprises systems that process continuously arriving event data: sensor telemetry, clickstreams, vehicle positions, market data. Its defining property is that data are produced by the world at the world's own rate, and lose value quickly: the system must sustain ingest at the production rate \emph{indefinitely}, master backpressure, and guarantee state correctness across failures.
|
||||
|
||||
\subsection{The challenges it brings}
|
||||
|
||||
The first challenge is the sheer, unending inflow. The verified magnitudes: \textbf{LinkedIn}, Kafka's birthplace \citep{kreps2011kafka}, operates more than seven trillion Kafka messages per day across roughly 100 clusters, over 4{,}000 brokers, about 100{,}000 topics and seven million partitions \citep{lee2019kafka}; \textbf{Uber} moves trillions of messages and petabytes per day through an integrated real-time stack of Kafka (transport), Flink (stream processing), and Pinot (OLAP serving), documented in a SIGMOD paper \citep{fu2021realtime}. Ingest at that rate, around the clock, with bounded consumer lag and mastered backpressure, is the class's defining demand on D2 (write scalability) -- the inversion of C2's read-heavy profile -- and running it 24/7 without pause is a demand on D5 (availability and fault isolation): the world does not stop producing while a node recovers. Value decay adds D3 (latency): an anomaly alert is worth something within milliseconds to seconds, and little after.
|
||||
|
||||
The second challenge is the genuinely hard one: \emph{declared correctness semantics under failure}. Correctness here has stream-specific meanings -- event time versus processing time, windowing, watermarks -- and the trade-off between correctness, latency, and cost is formalised in the Dataflow model \citep{akidau2015dataflow}; exactly-once state across failures is achievable via distributed snapshots and checkpointing \citep{carbone2017state}, but it is bought with machinery and permanent operational competence. That is the D4 demand in its stream reading (Table~\ref{tab:requirements}, footnote~11) -- and a warning on D8 (simplicity), which the class weights Low because nobody chooses streaming for its ease. The third challenge is longevity of the plumbing: topologies change moderately, but \emph{schema evolution is a permanent concern} (D7 Medium); data volume is the largest of all classes (append-only logs), retention often TTL-bounded, and the infrastructure long-lived even where the data are not. The binding scenarios:
|
||||
|
||||
\begin{itemize}
|
||||
\item \textbf{S1 (sustained ingest).} Sensors emit at full production rate (stimulus) around the clock (environment); the platform ingests and processes (response) with \textbf{consumer lag bounded and no data loss, indefinitely} (response measure). The D2/D5 scenario.
|
||||
\item \textbf{S2 (exactly-once state).} A processing node fails mid-window (stimulus) under load (environment); the system recovers (response) with \textbf{state restored to exactly-once semantics via checkpointing, zero duplicated or lost aggregate updates} (response measure) \citep{carbone2017state}. The D4 scenario in its footnote-11 reading.
|
||||
\item \textbf{S3 (end-to-end latency).} An anomalous reading arrives (stimulus); the alert fires (response) \textbf{within milliseconds to a few seconds end-to-end, with per-key ordering preserved} (response measure) \citep{akidau2015dataflow}. The D3 scenario.
|
||||
\end{itemize}
|
||||
|
||||
$K(\text{C8})$ is technical rather than statutory: per-key ordering guarantees and exactly-once semantics \emph{where declared} are contractual knock-outs -- a billing stream that double-counts under failure is not ``mostly correct'', it is wrong \citep{carbone2017state, akidau2015dataflow}. Where the streams carry personal data (vehicle telemetry, wearables), the GDPR adds purpose limitation and retention duties \citep{eu2016dsgvo}. The pragmatic industry norm -- at-least-once delivery plus idempotent consumers -- is legitimate exactly where the scenario says so, and the decision is taken \emph{per stream, per scenario}, never platform-wide.
|
||||
|
||||
\subsection{The requirements profile}
|
||||
|
||||
With the challenges in mind -- the unending inflow, correctness under failure, value decay -- the weights follow; each H is a veto trigger (Part~\ref{part:foundations}). Table~\ref{tab:req-c8} is the C8 column of the consolidated table.
|
||||
|
||||
\begin{table}[htbp]
|
||||
\centering
|
||||
\footnotesize
|
||||
\caption{Requirements profile of C8 (real-time / IoT streaming) -- column C8 of Table~\ref{tab:requirements}, cell-identical; note numbers refer to that table's footnotes.}
|
||||
\label{tab:req-c8}
|
||||
\begin{tabular}{@{}p{3.4cm}cp{8.3cm}@{}}
|
||||
\toprule
|
||||
\textbf{Dimension} & \textbf{Weight} & \textbf{Why} \\
|
||||
\midrule
|
||||
D1 Read scalability & M & consumers read the log at their own pace; serving is delegated to OLAP sinks \\
|
||||
D2 Write scalability \& elasticity & \textbf{H} & ingest at the world's production rate, indefinitely, with backpressure mastered (S1) \\
|
||||
D3 Latency & \textbf{H} & alerts fire within milliseconds to seconds, end to end (S3) \\
|
||||
D4 Consistency \& integrity & M & stream semantics: exactly-once state, event-time windows, watermarks (S2; note~11) \\
|
||||
D5 Availability \& fault isolation & \textbf{H} & the world does not pause when a node fails; recovery must preserve state \\
|
||||
D6 Security \& auditability & L & low relative to the ledger classes; GDPR applies where streams carry personal data \\
|
||||
D7 Evolvability & M & topologies change moderately; schema evolution is the permanent concern \\
|
||||
D8 Simplicity \& TTM & L & nobody chooses this class for its simplicity \\
|
||||
D9 Testability \& deployability & M & correctness under failure is verified by chaos experiments, not unit suites alone \\
|
||||
D10 Operating cost & M & broker fleets cost, but the class's economics absorb them \\
|
||||
D11 Team scaling & M & platform and stream teams coordinate around shared topics \\
|
||||
D12 AI integrability & M & models score events in the stream as checkpointed operators \\
|
||||
\midrule
|
||||
Workload shape $S(a)$ & \multicolumn{2}{l}{continuous stream} \\
|
||||
Hard constraints $K(a)$ & \multicolumn{2}{p{9.0cm}}{Per-key ordering; exactly-once where stated} \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\subsection{What real systems chose -- and why}
|
||||
|
||||
The documented form is event-driven architecture plus pipes-and-filters over a durable log: producers $\rightarrow$ Kafka (durable, partitioned, replayable) $\rightarrow$ stream processors (Flink) $\rightarrow$ sinks (OLAP, alerting, data lake) \citep{kreps2011kafka, fu2021realtime}. The EDA column of Part~\ref{part:patterns} (Table~\ref{tab:cap-eda}) is this class's mirror: a durable, partitioned, replayable log with decoupled producers and consumers serves D2 and D5 at $++$ -- the two demands that eliminate every single-quantum interactive pattern at the shape gate -- and the streaming incarnation of pipes-and-filters supplies the processing layer whose checkpointing answers S2 \citep{carbone2017state}. \textbf{Netflix} is the consumer-scale EDA reference, with event-driven telemetry pipelines and resilience institutionalised through chaos engineering \citep{evans2016netflix, basiri2016chaos} -- chaos experiments being exactly how this class tests its D4/D5 claims.
|
||||
|
||||
The counter-lessons both come from \emph{this} class's neighbourhood and were introduced in Part~\ref{part:foundations}: \textbf{Segment} -- a customer-data pipeline -- retreated in 2018 from over 140 per-destination microservices to a monolith with a central queueing system because operational and test complexity crushed a small team \citep{noonan2018goodbye, infoq2020segment}; \textbf{Prime Video} consolidated a serverless orchestration into a single process for a tightly coupled A/V monitoring flow \citep{kolny2023primevideo, cockcroft2023prime}. The shared pattern -- and the Assumption-A2 lesson: both cut \emph{one} coherent dataflow along technical rather than domain seams, and the interaction costs (queues, orchestrator transitions, storage round-trips, test matrices) consumed the benefit \citep{newman2021building}. Open-source references: Apache \textbf{Kafka}, Apache \textbf{Flink}, MQTT brokers (Mosquitto, EMQX) at the IoT edge, Apache Pinot/Druid for real-time OLAP serving.
|
||||
|
||||
\begin{keypoint}
|
||||
C8 must keep pace with the production rate of the world -- indefinitely. Its genuinely hard requirement is not throughput but \emph{declared correctness semantics under failure}: exactly-once state and event-time correctness are bought with checkpointing machinery and permanent operational competence, so the pragmatic norm is at-least-once plus idempotence -- decided per stream, per scenario, and recorded as such \citep{carbone2017state, akidau2015dataflow}.
|
||||
\end{keypoint}
|
||||
|
||||
\begin{ailinse}[Online inference and drift on streams (Axis B)]
|
||||
C8 is where ML meets its hardest operational constraint: models score events \emph{in the stream} (fraud, anomaly, predictive maintenance) at millisecond budgets, which rules out per-event LLM calls entirely and demands pre-trained, locally served models. The stream is simultaneously the monitoring instrument: input-distribution statistics computed in the pipeline detect data and concept drift \citep{gama2014drift}, and production-readiness rubrics such as the ML Test Score assume exactly this telemetry \citep{breck2017mltest}. Architecturally, the model is one more stateful stream operator -- checkpointed, versioned, and replayable like any other, so that scenario~S2's exactly-once discipline extends to inference results.
|
||||
\end{ailinse}
|
||||
|
||||
In one sentence: the primary recommendation for C8 is EDA over a durable log with streaming pipes-and-filters as the processing layer -- the documented Uber stack (EDA at $++$, PF and MS at $+$) -- with microservice processors as secondary where team ownership demands it; Part~\ref{part:fit} computes this verdict through the three-stage procedure.
|
||||
|
||||
% ============================================
|
||||
% SECTION: C9 COLLABORATION / MESSAGING
|
||||
% ============================================
|
||||
\section{C9 -- Collaboration / Messaging}
|
||||
\label{sec:c9}
|
||||
|
||||
\emph{Five million people are connected at this moment, and every message must reach its channel within half a second: what holds the connections?} The class comprises chat, team-collaboration, and messaging applications. Its peculiarity is a resource profile that classical request/response never modelled: the system holds \emph{millions of long-lived, stateful connections} (WebSockets) and pushes every message to all channel members immediately. Latency must feel instantaneous; ordering must be causal \emph{per channel} -- global ordering is unnecessary, a deliberate weakening that buys scalability (Table~\ref{tab:requirements}, footnote~12).
|
||||
|
||||
\subsection{The challenges it brings}
|
||||
|
||||
The first challenge is the connections themselves. \textbf{Slack} holds more than five million simultaneous WebSocket sessions at peak; when a morning peak rolls across a timezone, millions of clients connect and boot within minutes, and the boot storm -- not the message rate -- is what threatens the core databases. Slack's application-level edge cache \textbf{Flannel}, deployed at global points of presence, reduced p99 latency for channel-membership queries from roughly 2{,}000\,ms to roughly 200\,ms while shielding the core from exactly these storms \citep{slack2017flannel}. The binding load is thus \emph{connection fan-out and push}, not raw read/write rates -- which is why D1 and D2 sit at Medium with footnote~9 while the crux lands on D3 (latency) and D5 (availability): a message must reach its channel in 100--500\,ms, and a disconnected messenger is a dead messenger. Every message is one write and $N$ push-deliveries; load arrives as office-hour waves travelling around the globe with the timezones (Slack) or as evening peaks (Discord).
|
||||
|
||||
The second challenge is the history tail. Message histories are enormous -- \textbf{Discord} stores trillions of messages -- and users scroll deep into them expecting low-tens-of-milliseconds reads: Discord's storage migrations (MongoDB $\rightarrow$ Cassandra $\rightarrow$ ScyllaDB, behind Rust data services performing request coalescing) cut p99 read latency from 40--125\,ms to roughly 15\,ms \citep{ingram2023discord} -- a D3 demand on the read path. The third challenge is that consistency can be \emph{relaxed by design}: causal order per channel suffices (D4 Medium, footnote~12), the deliberate weakening that makes the fan-out scalable. Feature churn is high while the core protocol stays stable (D7 Medium); lifetimes exceed ten years. The binding scenarios:
|
||||
|
||||
\begin{itemize}
|
||||
\item \textbf{S1 (delivery latency).} A user sends a channel message (stimulus) in normal global operation (environment); all online channel members receive it (response) \textbf{within 100--500\,ms, in causal order per channel} (response measure). The D3/D4 scenario.
|
||||
\item \textbf{S2 (connection fan-out).} Morning peak rolls across a timezone (stimulus); millions of clients connect and boot (environment/response) with \textbf{connection establishment and initial payload within budget while protecting the core databases} (response measure) -- the exact scenario for which Slack built its edge cache \citep{slack2017flannel}. The D5 scenario in the class's connection reading (note~9).
|
||||
\item \textbf{S3 (history read tail).} A user scrolls deep into channel history (stimulus); the store serves the read (response) with \textbf{p99 read latency in the low tens of milliseconds} (response measure) -- the target of Discord's storage migrations \citep{ingram2023discord}. A D3 demand on the storage tier.
|
||||
\end{itemize}
|
||||
|
||||
$K(\text{C9})$: the GDPR, with data residency as an explicit selling argument in the self-hosted market segment \citep{eu2016dsgvo}; in enterprise deployments, compliance archiving obligations (MiFID~II and FINRA record-keeping rules for trader communication) make exportable, tamper-evident message archives a hard requirement. The knock-out reading: for regulated enterprise customers, an architecture that cannot guarantee complete capture and retention of business communication is excluded -- which is precisely the market logic behind Mattermost's single-binary, self-hostable design.
|
||||
|
||||
\subsection{The requirements profile}
|
||||
|
||||
With the challenges in mind -- connection storms, push fan-out, the history tail, per-channel ordering -- the weights follow; each H is a veto trigger (Part~\ref{part:foundations}). Table~\ref{tab:req-c9} is the C9 column of the consolidated table.
|
||||
|
||||
\begin{table}[htbp]
|
||||
\centering
|
||||
\footnotesize
|
||||
\caption{Requirements profile of C9 (collaboration / messaging) -- column C9 of Table~\ref{tab:requirements}, cell-identical; note numbers refer to that table's footnotes.}
|
||||
\label{tab:req-c9}
|
||||
\begin{tabular}{@{}p{3.4cm}cp{8.3cm}@{}}
|
||||
\toprule
|
||||
\textbf{Dimension} & \textbf{Weight} & \textbf{Why} \\
|
||||
\midrule
|
||||
D1 Read scalability & M & the binding load is connection fan-out and push, not raw reads (note~9) \\
|
||||
D2 Write scalability \& elasticity & M & one write becomes $N$ push deliveries -- amplification, not raw write rate (note~9) \\
|
||||
D3 Latency & \textbf{H} & delivery within 100--500\,ms or the conversation dies (S1, S3) \\
|
||||
D4 Consistency \& integrity & M & causal order per channel suffices; global order is deliberately waived (note~12) \\
|
||||
D5 Availability \& fault isolation & \textbf{H} & presence is the product: a disconnected messenger is a dead messenger (S2) \\
|
||||
D6 Security \& auditability & M & enterprise segments harden archiving duties into $K(a)$; consumer segments do not \\
|
||||
D7 Evolvability & M & feature churn is high while the core protocol stays stable \\
|
||||
D8 Simplicity \& TTM & M & a small install must stay operable -- the self-hosted market demands it \\
|
||||
D9 Testability \& deployability & M & staged rollouts across a heterogeneous client fleet \\
|
||||
D10 Operating cost & M & connection infrastructure costs scale with concurrency, not usage \\
|
||||
D11 Team scaling & M & platform teams for gateway and storage, feature teams above \\
|
||||
D12 AI integrability & L & assistants and summarisation decorate the edges; the fan-out core is untouched \\
|
||||
\midrule
|
||||
Workload shape $S(a)$ & \multicolumn{2}{l}{interactive, connection-stateful} \\
|
||||
Hard constraints $K(a)$ & \multicolumn{2}{p{9.0cm}}{Compliance archiving (MiFID/FINRA) in enterprise segments} \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\subsection{What real systems chose -- and why}
|
||||
|
||||
The class spans the full structural spectrum with one business domain. \textbf{Mattermost} ships deliberately as \emph{one} Go binary with PostgreSQL -- the monolith as a \emph{feature} for self-hosting and compliance customers \citep{mattermost2024docs}: the modular-monolith column's D8/D10 strengths (Table~\ref{tab:cap-mm}) are precisely what the enterprise $K(a)$ segment buys, and its D5 weakness is mitigated by replicated instances. \textbf{Rocket.Chat}, built on Node.js and MongoDB, sits in the middle \citep{rocketchat2024github}. \textbf{Slack}'s documented shape is a hybrid: a PHP/Hack monolithic core for persistence and business logic with a specialised distributed real-time push layer in front \citep{slack2017flannel} -- and the push layer is publish/subscribe fan-out, which is why the EDA column (Table~\ref{tab:cap-eda}) owns this row: message delivery \emph{is} event fan-out with causal per-channel ordering; the domain semantics and the pattern coincide. \textbf{Discord} represents polyglot specialisation per quality attribute -- BEAM for connection concurrency, Rust for tail latency \citep{ingram2023discord} -- targeted microservices exactly where the D3 tail demands them. Matrix/Synapse adds a federated counter-model.
|
||||
|
||||
Same domain, four structures: the trade-off (Assumption A2) is resolved by scale and business model, not by the domain -- below roughly $10^5$ concurrent connections a specialised push layer is premature optimisation, and the measured concurrent-connection count is the tiebreaker.
|
||||
|
||||
\begin{keypoint}
|
||||
C9's binding load is connection fan-out and push, not raw read/write rates -- a resource profile request/response never modelled. The same business domain spans Mattermost's single, deliberately monolithic binary and Discord's polyglot specialised cluster \citep{mattermost2024docs, ingram2023discord}: the profile's core is stable, but scale and business model move the weights at its edges -- measured concurrent-connection count is the tiebreaker.
|
||||
\end{keypoint}
|
||||
|
||||
\begin{thinkbox}
|
||||
Mattermost and Discord implement substantially the same user-visible functionality. Using the twelve dimensions of Table~\ref{tab:dimensions}: which \emph{three} dimensions differ most strongly between the requirements profile of a self-hosted compliance deployment (500 users, banking client) and a global consumer platform (150 million users)? Would any weight flip from L to H? What does that imply for the claim that ``the application class determines the profile''?
|
||||
\end{thinkbox}
|
||||
|
||||
In one sentence: the primary recommendation for C9 is a hybrid -- a monolithic persistence and business core with a specialised event-driven push layer, Slack's documented shape (EDA at $++$ at the fan-out crux, MM and MS at $+$) -- with a modular monolith alone as secondary for the self-hosted market segment; Part~\ref{part:fit} computes this verdict through the three-stage procedure.
|
||||
|
||||
% ============================================
|
||||
% SECTION: C10 AI-NATIVE ANALYSIS / ADVISORY PLATFORMS
|
||||
% ============================================
|
||||
\section{C10 -- AI-Native Advisory Platforms}
|
||||
\label{sec:c10}
|
||||
|
||||
\emph{The component your product is built around is non-deterministic, priced per call, and deprecated within months: what structure contains it?} The class comprises platforms whose core value is generated by LLM agents cooperating with deterministic services: research and analysis assistants, financial advisory platforms, domain copilots. It is the youngest class in the catalogue, the profile of the course project, and the reason this course exists in its present form. Its defining properties follow from the component it is built around: the AI component is non-deterministic, fallible, latency-heavy, and priced per call \citep{sculley2015hidden, amershi2019software}. The architecture must therefore \emph{contain} it: deterministic services for everything deterministic, LLM calls only where determinism cannot reach, and every generated statement grounded in retrievable sources.
|
||||
|
||||
\subsection{The challenges it brings}
|
||||
|
||||
The first challenge is accountability for probabilistic output. An advisory answer is only defensible if every factual claim carries a resolvable provenance reference and every agent step is logged -- observability is not an operations concern here but \emph{domain functionality} \citep{lewis2020rag}. That is a demand on D6 (security and auditability) with statutory force behind it: the EU AI Act (Regulation (EU) 2024/1689) imposes risk-based duties -- transparency, technical documentation, logging, human oversight, robustness -- and an advisory application in a financial context can fall into the high-risk class, at which point logging and oversight acquire legal force \citep{eu2024aiact}.
|
||||
|
||||
The second challenge is the cost model, and it is genuinely new. Requests are rare but heavy: seconds to minutes of latency, with per-request cost orders of magnitude above classical API calls (LLM inference plus multiple tool invocations). Users accept seconds-to-minutes for advisory answers, so the High-grade concern is \emph{cost per request, not speed} -- D10 High in the footnote-16 reading, with D3 relaxed to Medium (footnote~5). Two cost-model facts anchor the economics: asynchronous batch processing is priced roughly 50\,\% below synchronous calls \citep{openai2024batch}, and routing across cheap and expensive models is a first-order cost lever -- LLM cascades reach up to 98\,\% cost reduction at comparable quality \citep{chen2023frugalgpt}, and learned routers better than halve cost without measured quality loss \citep{ong2025routellm}.
|
||||
|
||||
The third challenge is churn at the core's edge: models, prompts, and frameworks turn over in months -- the most extreme change rate in the catalogue, and the strongest argument for ports and adapters, with the LLM as a swappable adapter behind a port, never as the core \citep{cockburn2024hexagonal, sculley2015hidden}. That is D7 (evolvability) High -- and it drags D9 (testability) with it in a new reading: \emph{evals} are the operative meaning of testability (footnote~15), because only a versioned golden set with statistical thresholds can tell whether a model migration preserved quality \citep{zheng2023judging}. The workload mix underneath is hybrid: read-heavy against knowledge stores (retrieval), write-heavy into audit and trace logs, consistency hybrid (footnote~13: the knowledge index eventually consistent through re-indexing cycles, the transaction and audit path ACID), load irregular and user-driven, with batch components (embedding and index pipelines) shaped like C6/C7. The binding scenarios:
|
||||
|
||||
\begin{itemize}
|
||||
\item \textbf{S1 (grounded answer).} A client asks for a portfolio recommendation (stimulus) in normal operation (environment); the platform generates an answer (response) in which \textbf{every factual claim carries a resolvable provenance reference, and answers failing validation are blocked and escalated to a human -- detection rate $\geq 99\,\%$ at $<2$\,s added latency} (response measure) \citep{lewis2020rag}. The D6 scenario -- and D12's containment discipline in action.
|
||||
\item \textbf{S2 (cost per request).} A user session triggers a multi-step agent workflow (stimulus); the request completes (response) \textbf{within a per-request token-cost budget (e.g.\ CHF~0.40 at p95) and a p95 end-to-end latency budget (e.g.\ 20\,s)} (response measure), both enforced as CI-gated fitness functions \citep{ford2022evolutionary}. The D10 scenario in its footnote-16 reading.
|
||||
\item \textbf{S3 (model migration).} The provider deprecates the production model (stimulus) with months of notice (environment) \citep{openai2026deprecations}; the platform migrates (response) with \textbf{eval-harness pass rate $\geq$ threshold on the golden set before rollout, and rollback available} (response measure) \citep{zheng2023judging}. The D7/D9 scenario.
|
||||
\end{itemize}
|
||||
|
||||
$K(\text{C10})$ extends beyond the AI Act: the GDPR governs personal data in prompts and indexes \citep{eu2016dsgvo}; financial-advisory deployments additionally face supervisory governance expectations for AI use \citep{finma2023oprisk}. Security is a distinct knock-out family: prompt injection cannot be fully solved in the model because instructions and data share one channel, so system-level defence in depth -- least-privilege tools, output validation, human-in-the-loop, consumption limits -- is constitutive \citep{owasp2025llmtop10}. Knock-out reading: an architecture in which agent steps are not loggable, tool privileges not boundable, or provenance not reconstructable is excluded before scoring -- the same veto logic that ACID exercises in C1, transposed to accountability.
|
||||
|
||||
\subsection{The requirements profile}
|
||||
|
||||
With the challenges in mind -- accountability with legal force, cost per request, model churn -- the weights follow; each H is a veto trigger (Part~\ref{part:foundations}). Table~\ref{tab:req-c10} is the C10 column of the consolidated table -- the only column with an H on D12.
|
||||
|
||||
\begin{table}[htbp]
|
||||
\centering
|
||||
\footnotesize
|
||||
\caption{Requirements profile of C10 (AI-native advisory platform -- the course-project class) -- column C10 of Table~\ref{tab:requirements}, cell-identical; note numbers refer to that table's footnotes.}
|
||||
\label{tab:req-c10}
|
||||
\begin{tabular}{@{}p{3.4cm}cp{8.3cm}@{}}
|
||||
\toprule
|
||||
\textbf{Dimension} & \textbf{Weight} & \textbf{Why} \\
|
||||
\midrule
|
||||
D1 Read scalability & M & retrieval reads against knowledge stores; user concurrency stays modest \\
|
||||
D2 Write scalability \& elasticity & L & requests are rare; the batch pipelines are scheduled, not elastic \\
|
||||
D3 Latency & M & users accept seconds-to-minutes for advisory answers (note~5) \\
|
||||
D4 Consistency \& integrity & M & hybrid: knowledge index eventual, transaction/audit path ACID (note~13) \\
|
||||
D5 Availability \& fault isolation & M & degraded answers beat no answers; provider outages are survivable \\
|
||||
D6 Security \& auditability & \textbf{H} & provenance per claim and a log per agent step -- observability as domain functionality, with EU AI Act force (S1) \\
|
||||
D7 Evolvability & \textbf{H} & models, prompts, and frameworks turn over in months (S3) \\
|
||||
D8 Simplicity \& TTM & M & start with the simplest structure -- but never simpler than the audit path \\
|
||||
D9 Testability \& deployability & \textbf{H} & evals are the operative meaning of testability (S3; note~15) \\
|
||||
D10 Operating cost & \textbf{H} & cost per \emph{request} (tokens, GPU) -- a run-cost class no classical profile contains (S2; note~16) \\
|
||||
D11 Team scaling & L & small product teams; the platform premium is unaffordable \\
|
||||
D12 AI integrability & \textbf{H} & definitional: the class exists to contain the probabilistic component \\
|
||||
\midrule
|
||||
Workload shape $S(a)$ & \multicolumn{2}{l}{hybrid: interactive + batch/async} \\
|
||||
Hard constraints $K(a)$ & \multicolumn{2}{p{9.0cm}}{EU AI Act 2024/1689 (logging, oversight; potentially high-risk); GDPR} \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\subsection{What real systems chose -- and why}
|
||||
|
||||
Three documented building blocks define the reference shape. (a) \textbf{Retrieval-augmented generation} as the grounding layer: retriever plus generator, introduced by \citet{lewis2020rag}, surveyed across its naive/advanced/modular variants by \citet{gao2023survey}; the canonical pipeline -- ingestion (chunking, embedding) $\rightarrow$ vector index $\rightarrow$ retrieval $\rightarrow$ context construction $\rightarrow$ generation with citations -- is structurally a pipes-and-filters pipeline plus an online serving layer, with seven documented failure points along it \citep{barnett2024seven}: the PF column (Table~\ref{tab:cap-pf}) serving the class's C6-shaped batch inheritance. (b) \textbf{Agent orchestration}: Anthropic's engineering guidance distinguishes \emph{workflows} (predefined chains: prompt chaining, routing, parallelisation, orchestrator--workers, evaluator--optimizer) from \emph{agents} (the model steers its own loop and tool use) and explicitly recommends starting with the simplest structure \citep{anthropic2024agents}; the quantified restraint case is Anthropic's own multi-agent research system -- 90.2\,\% better than a single agent on the internal eval at roughly \emph{fifteen times} the token consumption of a chat \citep{anthropic2025multiagent} -- the D10-High trade-off measured. (c) \textbf{Compound AI systems}: state-of-the-art results increasingly come from systems of retrievers, models, tools, and verifiers rather than from single models -- the system architecture becomes the differentiator \citep{zaharia2024compound}.
|
||||
|
||||
The deterministic services -- data access, computation, persistence -- form a conventional C3/C7-profiled system, and the capability tables explain the host choice: the modular-monolith column (Table~\ref{tab:cap-mm}) hosts them cheaply within one ACID quantum (the D4-footnote-13 audit path) while giving the AI subsystem a hard, CI-verifiable module boundary; the hexagonal column (Table~\ref{tab:cap-hx}) answers the class's two hardest Highs directly -- the LLM as a swappable adapter behind a port serves D7 under model churn, and the port is where the eval harness and the cost gateway dock, serving D9 and D10. Where the trade-off bites (Assumption A2): synchronous service chains would multiply seconds-scale LLM latency and failure rates, which is what keeps microservices at $\circ$ despite their blast-radius appeal; the mitigation for the monolith's weaker cells is asynchronous edges -- queues absorb LLM latency, rate limits, and outages, and create natural batching points for cost control. Open-source references: vector stores (Qdrant, Weaviate, and pgvector as the monolith-friendly option inside PostgreSQL), orchestration frameworks (LangChain/LangGraph \citep{langchain2024langgraph}, LlamaIndex), serving (vLLM), and eval harnesses (Ragas, promptfoo) \citep{cockburn2024hexagonal}.
|
||||
|
||||
\begin{projektbox}
|
||||
The Portfolio Intelligence Platform \emph{is} a C10 instance, and its profile is best understood as an inheritance diagram plus one genuinely new element. \textbf{Inherited:} the ingestion and eval pipelines are C6 (versioned, seeded, reproducible batch -- Section~\ref{sec:c6}); the analytics and reporting subsystem is C7 (refresh contracts, lineage -- Section~\ref{sec:c7}); the deterministic services (portfolio data access, computation, audit journal) are C3 (ACID, four-eyes, boring on purpose -- Section~\ref{sec:c3}). \textbf{New:} the cost model. Classical profiles price capacity per user or per infrastructure-hour; C10 is \emph{expensive per request} -- footnote~16 of Table~\ref{tab:requirements} -- so D10 = H acquires a meaning no classical class carries: a token-cost budget per request, per feature, enforced in CI and monitored per tenant. \textbf{Also new:} D12 = H for the platform itself, and D9 = H in its footnote-15 reading -- \emph{evals are the operative meaning of testability}: a versioned golden set with statistical thresholds gates every prompt change, model update, and provider migration, exactly as the test pyramid gates deterministic code. When you design your project architecture, start from the inherited disciplines -- they are solved problems -- and spend your design budget on the two new ones.
|
||||
\end{projektbox}
|
||||
|
||||
\begin{keypoint}
|
||||
C10 does not overthrow the method; it stress-tests it. The class adds one dimension weighted High that no classical class weights High (D12), one cost semantics (per request, not per user), and one test-artefact class (the eval harness) -- and otherwise \emph{inherits} its profile from C6, C7, and C3. This is Assumption A6 made concrete: the theory absorbs AI as a tenth application class rather than being reinvented for it.
|
||||
\end{keypoint}
|
||||
|
||||
In one sentence: the primary recommendation for C10 is a hexagonal modular monolith -- deterministic core, AI adapters at ports, an LLM gateway as the single measurement point -- plus pipes-and-filters for ingestion and evals (MM and HX at $++$), with EDA for the AI job and audit spine as secondary; Part~\ref{part:fit} computes this verdict through the three-stage procedure.
|
||||
|
||||
% ============================================
|
||||
% SECTION: STEPPING BACK: TEN PROFILES SIDE BY SIDE
|
||||
% ============================================
|
||||
\section{Stepping Back: Ten Profiles Side by Side}
|
||||
\label{sec:requirements-table}
|
||||
|
||||
Ten times over, this part has run the same movement: a leading question, the documented challenges with their dimensions, a twelve-row profile derived from them, and the structures real systems chose. Each section stood on its own. What no single section could deliver is the view \emph{across} the ten -- and that is what this closing section supplies: the consolidated requirements table, the reading rules that keep it honest, and the cross-class observations that prepare the matching in Part~\ref{part:fit}.
|
||||
|
||||
Table~\ref{tab:requirements} consolidates the ten requirements profiles: the twelve dimension weights $w_i(a)$, the dominant workload shape $S(a)$, and the hard constraints $K(a)$ per class -- the ten explanation views you have just walked through, assembled into one comparison view. It is the demand-side counterpart of the capability table (Table~\ref{tab:capability}) and one of the two inputs to the fit matrix of Part~\ref{part:fit}. Three reading rules apply. First, read \emph{columns} to see a class: each column repeats the per-class table of its section (Tables~\ref{tab:req-c1}--\ref{tab:req-c10}) cell for cell, and every H in it is backed by a binding scenario with a response measure. Second, read \emph{rows} to see what a dimension discriminates: D7 (evolvability) is High in six classes and Low in none -- long life is the norm, not the exception -- whereas D12 is High only in C10, the definitional case. Third, and critically: \textbf{the seventeen footnotes are part of the table's semantics, not decoration}. Several cells carry a class-specific \emph{meaning} of their dimension -- testability as reproducibility in C6 (footnote~14), testability as eval pass rate in C10 (footnote~15), read scalability as OLAP scan capacity in C7 (footnote~7) -- and using the bare letter without its footnote produces wrong matches in Part~\ref{part:fit}.
|
||||
|
||||
\begin{keypoint}
|
||||
An H in Table~\ref{tab:requirements} is a veto trigger backed by a scenario with a response measure; an L is a licence to not pay for that dimension. The footnotes carry class-specific semantics that the letters alone cannot: whoever matches profiles by letters without footnotes has not read the table.
|
||||
\end{keypoint}
|
||||
|
||||
\begin{sidewaystable}[p]
|
||||
\centering
|
||||
\caption{Consolidated requirements table: priority weights of the twelve profile dimensions (H = High, exercising veto power per the formal model of Part~\ref{part:foundations}; M = Medium; L = Low), dominant workload shape $S(a)$, and hard constraints $K(a)$ for the ten application classes. Superscripts refer to the footnotes below the table, which are integral to the cell semantics.}
|
||||
\label{tab:requirements}
|
||||
\scriptsize
|
||||
\setlength{\tabcolsep}{2.5pt}
|
||||
\begin{tabular}{@{}p{2.3cm}*{10}{p{1.72cm}}@{}}
|
||||
\toprule
|
||||
\textbf{Dimension} & \textbf{C1 Core banking} & \textbf{C2 Social/ content} & \textbf{C3 Back-office} & \textbf{C4 ERP} & \textbf{C5 E-com\-merce} & \textbf{C6 Simulation/ batch} & \textbf{C7 DSS/BI} & \textbf{C8 IoT streaming} & \textbf{C9 Collab/ messaging} & \textbf{C10 AI-native advisory} \\
|
||||
\midrule
|
||||
D1 Read scalability & M & \textbf{H} & L & L & \textbf{H} & L & \textbf{H}\textsuperscript{7} & M & M\textsuperscript{9} & M \\
|
||||
D2 Write scalability \& elasticity & M & M\textsuperscript{1} & L & L & \textbf{H} & \textbf{H}\textsuperscript{2} & L & \textbf{H} & M\textsuperscript{9} & L \\
|
||||
D3 Latency & M\textsuperscript{3} & \textbf{H} & M & M & \textbf{H} & L\textsuperscript{4} & M & \textbf{H} & \textbf{H} & M\textsuperscript{5} \\
|
||||
D4 Consistency \& integrity & \textbf{H} & L & \textbf{H} & \textbf{H} & M\textsuperscript{6} & M\textsuperscript{8} & M\textsuperscript{10} & M\textsuperscript{11} & M\textsuperscript{12} & M\textsuperscript{13} \\
|
||||
D5 Availability \& fault isolation & \textbf{H} & \textbf{H} & L & M & \textbf{H} & L & L & \textbf{H} & \textbf{H} & M \\
|
||||
D6 Security \& auditability & \textbf{H} & M & \textbf{H} & \textbf{H} & \textbf{H} & M & M & L & M & \textbf{H} \\
|
||||
D7 Evolvability & \textbf{H} & \textbf{H} & \textbf{H} & \textbf{H} & \textbf{H} & M & M & M & M & \textbf{H} \\
|
||||
D8 Simplicity \& TTM & L & M & \textbf{H} & M & M & M & M & L & M & M \\
|
||||
D9 Testability \& deployability & \textbf{H} & \textbf{H} & M & M & \textbf{H} & \textbf{H}\textsuperscript{14} & M & M & M & \textbf{H}\textsuperscript{15} \\
|
||||
D10 Operating cost & L & M & \textbf{H} & M & M & \textbf{H} & \textbf{H} & M & M & \textbf{H}\textsuperscript{16} \\
|
||||
D11 Team scaling & M & \textbf{H} & L & M & M\textsuperscript{17} & L & L & M & M & L \\
|
||||
D12 AI integrability & M & M & L & L & M & M & M & M & L & \textbf{H} \\
|
||||
\midrule
|
||||
Dominant workload shape $S(a)$ & interactive (+ batch edges) & interactive read-heavy & interactive & interactive (+ batch runs) & interactive, seasonal & scheduled batch & batch + thin serving & continuous stream & interactive, connection-stateful & hybrid: interactive + batch/async \\
|
||||
\midrule
|
||||
\textbf{Hard constraints $K(a)$} & BCBS 239; FINMA 2023/1; DORA (EU 2022/2554); ACID booking core; 10+ yr retention & DSA; GDPR & Retention law (e.g.\ OR 958\emph{f}); internal control systems; GDPR & GoBD/ GeB{\"u}V; SOX; IFRS audit chains & PCI DSS v4.0 scope minimisation; PSD2/SCA & Model validation and backtesting (finance); deterministic seeds & BCBS 239 lineage (banks) & Per-key ordering; exactly-once where stated & Compliance archiving (MiFID/ FINRA) in enterprise segments & EU AI Act 2024/1689 (logging, oversight; potentially high-risk); GDPR \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
|
||||
\vspace{2.5mm}
|
||||
\begin{flushleft}
|
||||
\tiny
|
||||
\textbf{Footnotes:}
|
||||
\textsuperscript{1}~Raw write rate is modest (Twitter: ca.\ 6\,k tweet writes/s vs.\ ca.\ 300\,k timeline reads/s \citep{krikorian2013timelines}); fan-out amplification is real but is absorbed by the fan-out subsystem, not the write path proper -- hence M with the amplification noted.
|
||||
\textsuperscript{2}~Throughput as makespan and batch-window compute bursts, not requests/s.
|
||||
\textsuperscript{3}~Class-internal spread of orders of magnitude: batch clearing hours, instant payments $<10$\,s end-to-end, card authorisation 1--2\,s, trading microseconds.
|
||||
\textsuperscript{4}~Per-request latency irrelevant; makespan and batch window are the measures.
|
||||
\textsuperscript{5}~Users accept seconds-to-minutes for advisory answers; the High-grade concern is cost per request, not speed.
|
||||
\textsuperscript{6}~The class-defining hybrid: catalogue eventual, checkout/payment strictly ACID \citep{linden2006data}.
|
||||
\textsuperscript{7}~``Read'' here means heavy OLAP scans by few users; serving is typically delegated to the warehouse.
|
||||
\textsuperscript{8}~As bit-level reproducibility (seeds, versioned inputs), a scientific and -- for risk models -- regulatory duty \citep{bcbs2013rdarr, glasserman2003monte}.
|
||||
\textsuperscript{9}~Connection fan-out and push, not raw read/write rates, are the binding load (Slack: $>$5\,M concurrent WebSockets \citep{slack2017flannel}); hence M with the crux carried by D3/D5.
|
||||
\textsuperscript{10}~A third semantics beside ACID and eventual: freshness by refresh contract (``as of yesterday 24:00'').
|
||||
\textsuperscript{11}~Stream semantics: exactly-once state, event-time windows, watermarks \citep{akidau2015dataflow, carbone2017state}.
|
||||
\textsuperscript{12}~Causal order per channel suffices; global order unnecessary.
|
||||
\textsuperscript{13}~Hybrid: knowledge index eventual, transaction/audit path ACID.
|
||||
\textsuperscript{14}~Reproducibility (golden datasets, versioned pipelines) is the operative meaning of testability here.
|
||||
\textsuperscript{15}~Evals are the operative meaning of testability here (Part~\ref{part:ai}).
|
||||
\textsuperscript{16}~Cost per \emph{request} (tokens, GPU) -- a run-cost class no classical profile contains.
|
||||
\textsuperscript{17}~Organisation-size dependent: the Shopify-vs-Amazon contrast \citep{westeinde2019deconstructing}.
|
||||
\end{flushleft}
|
||||
\end{sidewaystable}
|
||||
|
||||
\subsection{Reading the catalogue as a whole}
|
||||
\label{sec:catalogue-synthesis}
|
||||
|
||||
Five cross-class observations fall out of the catalogue and prepare the matching in Part~\ref{part:fit}.
|
||||
|
||||
\textbf{The strongest discriminators are the read/write ratio and the consistency semantics.} C1 (write-critical, strict ACID) and C2 (roughly 50:1 read-heavy, deliberately eventual \citep{krikorian2013timelines}) are mirror images across both variables at once -- the fastest diagnostic pair in the catalogue, and the didactic anchor of this part. C5 is the only class \emph{defined} by a hybrid consistency profile \citep{linden2006data}, and C6/C7 contribute the third semantics family -- reproducibility and freshness by refresh contract -- that neither ACID nor eventual consistency captures (Section~\ref{sec:c6}). When classifying an unknown system, ask these two questions first; they eliminate more patterns via the shape gate and the D4 row than any other pair.
|
||||
|
||||
\textbf{Scale does not force microservices.} The documented monolith-at-scale cases span four classes: Instagram serves a global consumer platform from a horizontally replicated Django monolith \citep{woodruff2019static}; Stack Overflow serves on the order of 1.3 billion page views per month, at more than 6{,}000 requests per second, from roughly nine on-premise web servers running a monolithic .NET application \citep{craver2016stackoverflow, milanovic2023stackoverflow}; Shopify carries ca.~280 million requests per minute at BFCM peak on a pod-sharded modular Rails monolith \citep{westeinde2019deconstructing, shopify2024bfcm}; LMAX processes six million orders per second on one thread \citep{fowler2011lmax}. Stateless replication, sharding, and mechanical sympathy scale monoliths far. What microservices primarily solve is an \emph{organisational} scaling problem -- deployments per developer as team count grows \citep{forsgren2018accelerate, conway1968committees, skelton2019team} -- which is why Monzo's 2{,}800 services are viable only with extreme homogeneity and central migration automation \citep{sewell2024monzo}. In profile terms: D1/D2 rarely force distribution; D11 = H is what does.
|
||||
|
||||
\textbf{The rollback case studies share one pattern.} Segment \citep{noonan2018goodbye, infoq2020segment} and Prime Video \citep{kolny2023primevideo, cockcroft2023prime} both cut \emph{one} coherent dataflow along technical rather than domain seams -- one service per integration destination, one function per processing step -- and the interaction costs (queues, orchestrator state transitions, storage round-trips, the test matrix) consumed the benefit. Granularity must follow the coupling structure of the domain \citep{newman2021building}. For the catalogue this means: a class's workload shape is not merely a gate for pattern \emph{selection}, it also predicts where the expensive boundaries lie \emph{within} a pattern.
|
||||
|
||||
\textbf{Regulation is a first-class architectural requirement.} Across the catalogue, the constraint sets $K(a)$ translate directly into structure: BCBS~239 and FINMA 2023/1 into immutable journals, lineage, and resilience testing \citep{bcbs2013rdarr, finma2023oprisk}; DORA into incident-reporting and third-party risk machinery \citep{eu2022dora}; PCI~DSS v4.0 into cardholder-data zoning and scope minimisation \citep{pcissc2022pcidss}; the EU AI Act into logging and human-oversight duties for AI components \citep{eu2024aiact}. None of these can be bolted on late at reasonable cost -- they are Booch-significant decisions in the sense of Part~\ref{part:foundations}, which is exactly why they live in $K(a)$ as knock-outs rather than in the weights.
|
||||
|
||||
\textbf{The AI-native class inherits before it innovates.} C10 inherits the disciplines of C6/C7 (batch index and eval pipelines), and C3 (deterministic transactional services), and adds exactly two genuinely new elements: a cost model that is expensive per request rather than per user, and evals as the operative meaning of testability \citep{zaharia2024compound, anthropic2024agents}. For the course project this is the design instruction in one sentence: solve the inherited profiles with the inherited, well-understood structures, and concentrate the architectural attention on the two novelties.
|
||||
|
||||
\begin{keypoint}
|
||||
The ten requirements profiles are derivable, not arbitrary: every weight traces to binding scenarios with response measures, every constraint to a statute or a contract, every workload signature to documented production numbers. The other operand is ready: Part~\ref{part:fit} can now match these profiles against the capability profiles of Part~\ref{part:patterns} cell by cell (Table~\ref{tab:fitmatrix}), and every cell can be traced back to $R(a) \times C(p)$ rather than to fashion or taste.
|
||||
\end{keypoint}
|
||||
|
||||
\begin{thinkbox}
|
||||
The catalogue contains ten classes -- why not nine, why not fourteen? Propose a candidate eleventh class (for example: computer games, embedded control, blockchain ledgers) and test it against the definition of Section~\ref{sec:appclass-intro}: does it have a \emph{recurring} ASR bundle with typical response measures, a characteristic workload shape, and a regulatory frame -- and does its profile differ from all ten columns of Table~\ref{tab:requirements} on at least two High weights? If it does not differ, it is an instance, not a class.
|
||||
\end{thinkbox}
|
||||
794
skript/chapters/part4_fit.tex
Normal file
@ -0,0 +1,794 @@
|
||||
\part{The Fit: Matching, Decision Procedure, and Measurement}
|
||||
\label{part:fit}
|
||||
|
||||
Ten times Part~\ref{part:applications} ended with a verdict and a promise: a one-sentence primary and secondary recommendation, and the assurance that Part~\ref{part:fit} computes this verdict through the three-stage procedure. This part keeps that promise. You own both operands -- the requirements profiles $R(a)$ of Part~\ref{part:applications} and the capability profiles $C(p)$ of Part~\ref{part:patterns} -- and you have watched the \emph{architecture--application fit} $\mathrm{fit}(a,p)$, the ordinal aggregate of their dimension-wise comparison defined in Part~\ref{part:foundations}, run once at small scale in the C10 mini-match (Table~\ref{tab:minimatch}). What you have not yet seen is the machine at full load. The part proceeds the way Parts~\ref{part:patterns} and~\ref{part:applications} worked -- cases first, generalisation after: three matches computed end to end, each exposing one stage of the procedure (Section~\ref{sec:threecases}); the general procedure they instantiate (Section~\ref{sec:fit-computation}); all seventy pairs at once -- the matching matrix with its per-class rationales (Sections~\ref{sec:fitmatrix}--\ref{sec:matrix-reading}); what the matrix cannot say -- hybrids and evolution paths (Section~\ref{sec:hybrids}); the eight-step decision procedure (Section~\ref{sec:procedure}); and how a decision stays honest for years -- the measurement contract with its organisational and reflexive complements (Sections~\ref{sec:contract}--\ref{sec:limits}).
|
||||
|
||||
% ============================================
|
||||
% SECTION: THREE MATCHES, THREE STAGES
|
||||
% ============================================
|
||||
\section{Three Matches, Three Stages}
|
||||
\label{sec:threecases}
|
||||
|
||||
\emph{What does the three-stage procedure actually do when it runs?} Usually far less than students expect -- most of the work happens before anything is scored. The three cases of this section make that visible: each runs one class from Part~\ref{part:applications} against real candidates, lands on exactly the verdict that class's section promised, and is chosen because a different stage does the decisive work in it -- the knock-out screening and shape gate for C6, the veto rule with its documented mitigations for C1, the holistic ordinal reading with its built-in sensitivity alarm for C2. (C10, the course-project class, was Part~\ref{part:foundations}'s introductory match; the three classes here complement it.)
|
||||
|
||||
\subsection{Case 1 -- C6 against all seven candidates: Stage 1 does almost all the work}
|
||||
\label{subsec:case-c6}
|
||||
|
||||
\emph{The nightly risk run must finish by 06:00, reproduce to the bit, and cost as little as possible: which of the seven patterns can even apply for the job?} Recall the C6 profile (Table~\ref{tab:req-c6}): High on D2 in its makespan reading, on D9 in its reproducibility reading, and on D10; dominant workload shape \emph{scheduled batch}; deterministic seeds as a hard constraint. Before comparing a single rating, hold that shape against the native-shape row $S(p)$ of the capability table (Table~\ref{tab:capability}).
|
||||
|
||||
\begin{examplebox}[Computing the C6 row: one gate, six casualties]
|
||||
\textbf{Stage 1 -- knock-out and shape gate.} $S(\text{C6})$ is scheduled batch, and exactly one candidate is natively batch-shaped: PF. The gate caps every other cell at $\circ$ -- a subsystem role at best -- before any rating above the shape row is compared (Table~\ref{tab:case-c6} names the roles), and its harm clause takes two candidates further down: L has no answer to makespan, checkpointing, or CPU-hour cost and carries $--$ against High-weighted D2, so $\mathrm{fit}(\text{C6}, \text{L}) = {--}$; MS would multiply communication cost across service boundaries against High-weighted D10 -- the Prime Video lesson at HPC scale \citep{kolny2023primevideo} -- so $\mathrm{fit}(\text{C6}, \text{MS}) = {--}$.
|
||||
|
||||
\textbf{Stages 2 and 3 -- one survivor.} Only PF reaches the veto stage, and no veto fires: against the High set $\{$D2, D9, D10$\}$ it rates $+$, $+$, $++$ (Table~\ref{tab:cap-pf}) -- throughput from data-parallel frameworks, reproducibility by construction, utilisation-driven cost \citep{zaharia2012resilient, yoo2003slurm, glasserman2003monte}; its $--$ on D3 sits on a Low weight and is inert. The holistic reading ranks a field of one. \textbf{Result: $\mathrm{fit}(\text{C6}, \text{PF}) = {++}$, every other pattern at $\circ$ or below} -- the C6 row of Table~\ref{tab:fitmatrix}, computed almost entirely at Stage~1.
|
||||
\end{examplebox}
|
||||
|
||||
\begin{table}[!htbp]
|
||||
\centering
|
||||
\footnotesize
|
||||
\caption{Case 1 -- the C6 row decided at Stage~1: the workload-shape gate against $S(\text{C6}) = $ scheduled batch. Only PF proceeds to Stages~2--3; the verdict column is identical to the C6 row of Table~\ref{tab:fitmatrix}.}
|
||||
\label{tab:case-c6}
|
||||
\begin{tabular}{@{}llp{7.2cm}c@{}}
|
||||
\toprule
|
||||
\textbf{Pattern} & \textbf{Native shape $S(p)$} & \textbf{Stage-1 outcome} & \textbf{Verdict} \\
|
||||
\midrule
|
||||
L & interactive & gate caps at $\circ$; harm clause -- no answer to makespan or checkpointing, $--$ against High D2 & $--$ \\
|
||||
MM & interactive & gate caps at $\circ$: orchestration codebase around monolithic kernels & $\circ$ \\
|
||||
HX & (host's) & gate caps at $\circ$: ports touch no binding dimension & $\circ$ \\
|
||||
MS & interactive & gate caps; harm clause -- communication cost multiplied against High D10 & $--$ \\
|
||||
EDA & stream / async & gate caps at $\circ$: job-status glue beside scheduler and DAG & $\circ$ \\
|
||||
PF & scheduled batch & \textbf{gate passed} -- proceeds to Stages 2--3; no veto on $\{$D2, D9, D10$\}$ & $++$ \\
|
||||
SL & event-trig., short-lived & gate caps at $\circ$: burst fan-out for communication-light sections only & $\circ$ \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
The didactic point generalises: \emph{run the cheapest test first} -- six of seven candidates died before a single rating was weighed. The knock-outs of $K(a)$ belong to the same stage and work the same way: recall from Part~\ref{part:applications} that $K(\text{C1})$ eliminates any structure that cannot guarantee an ACID booking core, an immutable audit journal, and ten-plus-year retention -- before scoring, however well it scales \citep{bcbs2013rdarr}. The verdict is the one Section~\ref{sec:c6} promised: pipes-and-filters on HPC/batch infrastructure as primary, serverless fan-out for bursty, communication-light parallel sections as secondary -- with the honest subsystem roles (the $\circ$ cells) stated, not hidden.
|
||||
|
||||
\subsection{Case 2 -- C1: the veto rule and its documented mitigations}
|
||||
\label{subsec:case-c1}
|
||||
|
||||
\emph{Two candidates pass the gate, both natively interactive -- and one of them cannot commit a transaction across its own internal boundaries: how does the procedure decide core banking?} Where Case~1 was settled by shape, C1 is settled by the veto rule, because its gate lets several serious candidates through. Recall the profile (Table~\ref{tab:req-c1}): High on D4, D5, D6, D7, and D9; hard constraints including an ACID booking core and BCBS~239 / FINMA auditability \citep{bcbs2013rdarr, finma2023oprisk}; dominant workload shape interactive with batch edges. The contested pair is the modular monolith against microservices -- Tables~\ref{tab:cap-mm} and~\ref{tab:cap-ms} side by side.
|
||||
|
||||
\begin{examplebox}[Computing the cells C1/MS and C1/MM step by step]
|
||||
\textbf{Stage 1 -- knock-out and shape gate.} Both microservices (MS) and the modular monolith (MM) are natively interactive patterns, so the shape gate passes for both. No hard constraint in $K(\text{C1})$ eliminates either outright: the ACID-core constraint does not name a pattern, and both patterns can in principle be operated under FINMA-grade audit obligations. Both survive to Stage~2.
|
||||
|
||||
\textbf{Stage 2 -- veto rule for MS.} From Table~\ref{tab:capability}, $c_{4}(\text{MS}) = {--}$: no ACID transactions across service boundaries; sagas trade atomicity for choreography complexity \citep{richardson2018microservices}. D4 is High-weight in C1, so the veto fires and caps the cell at $-$. Note the kind of fact the veto has seized on: a \emph{structural} one. No mitigation \emph{restores} ACID across service boundaries -- sagas buy coordination with compensating actions, not atomicity -- so a mitigation can only show that living without the property is survivable in this class. Is there one? Yes, but conditional: Monzo operates roughly 2{,}800 microservices in production banking -- under the condition of organisational scale plus extreme technological homogeneity (one language, one monorepo, central migration automation) \citep{sewell2024monzo}. The mitigation is real but bound to a condition most organisations do not meet, and the microservice premium is paid in platform staffing with no gain for typical team sizes \citep{fowler2015premium}. The cap is therefore lifted only to $\circ$, with the condition stated in the cell rationale. MS also rates $--$ on D8 and D10, but both are Low-weight in C1 -- no further veto fires. \textbf{Result: $\mathrm{fit}(\text{C1}, \text{MS}) = \circ$.}
|
||||
|
||||
\textbf{Stage 2 -- veto rule for MM.} $c_{4}(\text{MM}) = {++}$ (cross-module ACID transactions) -- no veto. But $c_{5}(\text{MM}) = {-}$ on High-weight D5, which caps the cell at $\circ$ -- unless a documented mitigation exists. It does: hot-standby replication of whole monolith instances is the classical banking high-availability tactic, in production at Fineract-class core-banking systems \citep{fineract2024core}. The cap is lifted.
|
||||
|
||||
\textbf{Stage 3 -- holistic reading.} MM now stands at $++$ on D4, $+$ on D6, $+$ on D7, and $+$ on D9 -- support on every High-weight dimension of the class, with the one structural weakness mitigated. \textbf{Result: $\mathrm{fit}(\text{C1}, \text{MM}) = {++}$.} The ranking MM $\succ$ MS for the C1 core is stable under plausible weight variation: it would flip only if D11 (team scaling) rose to High \emph{and} the Monzo homogeneity condition held -- which is exactly what the cell rationale in Section~\ref{subsec:fit-c1} records as the escalation condition.
|
||||
\end{examplebox}
|
||||
|
||||
The division of labour generalises: the veto rule does the heavy lifting, and the ``documented mitigation'' clause is where engineering knowledge -- not arithmetic -- enters the computation. The asymmetry between the two mitigations is the lesson: an \emph{operational} weakness (MM's one-process blast radius) is repaired outright by a standard tactic -- hot standby, pod replication \citep{westeinde2019deconstructing} -- while a \emph{structural} one (atomicity surrendered at the boundary) can only be made survivable, under a condition most organisations do not meet. The rest of the row follows the same mechanics (Section~\ref{sec:rationales}); in particular HX -- a delta discipline, not a competitor -- joins MM at $++$ by isolating the long-lived booking core from volatile channels and providers \citep{cockburn2024hexagonal}. The verdict is the one Section~\ref{sec:c1} promised: a hexagonal modular monolith for the booking core (MM and HX at $++$), EDA at the edges and PF for the batch runs as secondary, and microservices only when organisation size forces D11 to High -- the Monzo condition -- exactly the C1 row of Table~\ref{tab:fitmatrix}.
|
||||
|
||||
\subsection{Case 3 -- C2: the holistic reading and its built-in alarm}
|
||||
\label{subsec:case-c2}
|
||||
|
||||
\emph{Two finalists carry $++$ where it matters and neither dominates: what does the procedure return when scoring cannot separate the survivors?} The social/content platform is that case. Recall the profile (Table~\ref{tab:req-c2}): the widest High set in the catalogue -- D1, D3, D5, D7, D9, D11 -- and a constraint set that knocks out almost nothing; the discrimination work is done by the weights, not the constraints.
|
||||
|
||||
\textbf{Stage 1} requires one honest observation about shape: the class core has two constitutive paths -- the interactive read path that serves the feed, and the asynchronous fan-out path that delivers posts (the five-second delivery scenario is binding for the class). Neither MS (natively interactive) nor EDA (natively stream/async) is shape-foreign to the path it would carry, so the gate passes both. \textbf{Stage 2} fires one veto against each, and documented practice lifts both: MS's $-$ on High-weighted D3 (mitigation: edge caching, precomputed timelines \citep{krikorian2013timelines}); EDA's $-$ on High-weighted D9 (mitigation: schema/contract tests, progressive delivery). Both reach Stage~3 intact.
|
||||
|
||||
\textbf{Stage 3} must now rank two survivors, and the comparison refuses to close. Across the High set, MS reads $++$, (mitigated), $++$, $++$, $+$, $++$ and EDA reads $++$, $+$, $++$, $++$, (mitigated), $+$. Neither dominates: MS leads where teams multiply (D9, D11 -- independent deployments), EDA where consumers multiply (D3 on the asynchronous path; D7 in its attach-new-consumers reading). The mandatory sensitivity analysis flips the ordering under entirely plausible variation: weight D11 the way a several-hundred-team organisation must, and MS wins; frame the feed as what it technically is -- an eventually consistent, precomputed product of an event flow -- and EDA wins. By Stage~3's own rule, that instability is not noise: it marks a genuine tradeoff point in the ATAM sense, to be escalated to scenario-based analysis rather than smoothed over \citep{kazman2000atam}.
|
||||
|
||||
And here the documented record refuses the either/or. Twitter's timeline architecture is both patterns at once -- fan-out-on-write \emph{is} publish/subscribe, an event flow whose product, the precomputed timeline, is served by independently scaled services \citep{krikorian2013timelines}. The honest reading of the instability is therefore not ``the procedure failed to pick a winner'' but ``the class genuinely needs both patterns, \emph{placed}'' -- the bridge to Section~\ref{sec:hybrids}, where hybrids turn out to be the normal case, not the exception. The verdict is the one Section~\ref{sec:c2} promised: an EDA + microservices hybrid at organisational scale (MS and EDA at $++$), a modular monolith as secondary until that scale is \emph{measured}, not assumed (Mastodon runs the full fan-out mechanics in a Rails monolith \citep{mastodon2024docs}) -- exactly the C2 row of Table~\ref{tab:fitmatrix}.
|
||||
|
||||
\begin{keypoint}
|
||||
Three cases, three stages, one division of labour: the knock-out screening and shape gate kill most candidates before any scoring (C6 -- the cheapest test runs first), the veto rule disciplines the High set and prices every mitigation as documented engineering rather than optimism (C1), and the holistic ordinal reading ranks the survivors while flagging its own instability as a finding, not an error (C2). Every one of the seventy cells in Section~\ref{sec:fitmatrix} was produced by exactly this division of labour.
|
||||
\end{keypoint}
|
||||
|
||||
% ============================================
|
||||
% SECTION: THE PROCEDURE IN GENERAL
|
||||
% ============================================
|
||||
\section{The Procedure in General}
|
||||
\label{sec:fit-computation}
|
||||
|
||||
\emph{What rule were the three matches following?} Three matches have run end to end; this section states what they instantiated -- briefly, because every element has already done visible work.
|
||||
|
||||
\subsection{The formal statement}
|
||||
|
||||
\begin{sloppypar}
|
||||
Recall the operands. Each application class $a \in A$ carries a requirements profile $R(a) = (w_1(a), \dots, w_{12}(a);\, S(a);\, K(a))$: utility-tree-derived priority weights $w_i(a) \in \{\text{High},\allowbreak\ \text{Medium},\allowbreak\ \text{Low}\}$ \citep{kazman2000atam}, the dominant workload shape $S(a)$, and the hard constraints $K(a)$ -- derived ten times over in Part~\ref{part:applications}. Each pattern $p \in P$ carries a capability profile $C(p) = (c_1(p), \dots, c_{12}(p);\, S(p))$ with ordinal ratings $c_i(p) \in \{++, +, \circ, -, --\}$, justified through tactics \citep{bachmann2003deriving, bass2021software} and calibrated against the star ratings of \citet{richards2025fundamentals} where those exist -- derived seven times over in Part~\ref{part:patterns}.
|
||||
\end{sloppypar}
|
||||
|
||||
\begin{definitionbox}[Architecture--application fit]
|
||||
The \emph{architecture--application fit} $\mathrm{fit}(a, p)$ is an ordinal aggregate of the dimension-wise comparison of $R(a)$ and $C(p)$, expressed on the same five-step scale $\{++, +, \circ, -, --\}$ and computed under a deliberately \emph{non-compensatory, three-stage procedure}:
|
||||
\begin{enumerate}
|
||||
\item \textbf{Knock-out screening and workload-shape gate.} Hard constraints $K(a)$ eliminate patterns \emph{before} any scoring; a violated constraint cannot be averaged away \citep{keeney1993decisions}. If $S(p)$ does not match the dominant $S(a)$, the pattern cannot be the dominant structure of the class's core: its cell is capped at $\circ$ (subsystem role), may reach $+$ only where it carries a \emph{constitutive} subsystem of an explicitly shape-hybrid class, and falls to $-$/$--$ where it would actively harm the class's binding scenarios. The gate is read per constitutive path: a pattern is \emph{not} shape-foreign to a class one of whose binding scenarios constitutes a path of the pattern's native shape -- the reading Case~3 (Section~\ref{subsec:case-c2}) applied to C2's fan-out delivery scenario (S2 of Table~\ref{tab:req-c2}).
|
||||
\item \textbf{Veto rule on High-weight dimensions.} If $c_i(p) = {--}$ on any dimension that $a$ weights High, $\mathrm{fit}(a,p)$ is capped at $-$; if $c_i(p) = {-}$, the cap is $\circ$ -- \emph{unless a documented mitigation exists} (a tactic or hybrid composition with production evidence), in which case the cell says so explicitly and the cap is lifted.
|
||||
\item \textbf{Holistic ordinal reading with mandatory sensitivity analysis.} The surviving candidates are ranked by their support of the High-weight dimensions; clustered conflicts on Medium-weight dimensions can downgrade a rating by one step. The result is a \emph{ranking with exclusions}, never ``pattern A is 12\,\% better''. If the ranking flips under plausible weight variation, that instability marks a genuine tradeoff point in the ATAM sense and must be escalated to scenario-based analysis \citep{kazman2000atam}.
|
||||
\end{enumerate}
|
||||
\end{definitionbox}
|
||||
|
||||
The three stages are ordered by decreasing hardness, and each now has a worked face. Stage~1 encodes facts no merit elsewhere can compensate -- a violated BCBS~239 obligation, an interactive pattern asked to carry a scheduled-batch core \citep{bcbs2013rdarr, keeney1993decisions}: Case~1 (Section~\ref{subsec:case-c6}) was this stage running the show, emptying six of the C6 row's seven cells on shape alone. Stage~2 encodes Assumption~A4: the High weights come from the $(H,H)$ leaves of a utility tree, so a structural failure on such a dimension fails precisely the scenarios that define the class -- unless engineering practice has produced a documented way around it \citep{westeinde2019deconstructing, richardson2018microservices}; Case~2 (Section~\ref{subsec:case-c1}) showed both halves of the rule, a mitigation that repairs (MM's hot standby) and one that merely makes survivable under condition (MS's Monzo condition). Stage~3 is deliberately the softest: it produces an ordering, and it carries a built-in alarm for its own instability -- the alarm that fired in Case~3 (Section~\ref{subsec:case-c2}) and returned a hybrid rather than a false winner.
|
||||
|
||||
\subsection{Why the fit is not a weighted sum}
|
||||
|
||||
Part~\ref{part:foundations} (Section~\ref{subsec:nomcdm}) established the formal case against the obvious formula $V(p) = \sum_i w_i \cdot v_i(p)$: additive value functions presuppose cardinal scales, preferential independence, and weights as trade-off rates \citep{keeney1993decisions} -- all three violated by ordinal profiles whose trade-offs are the very definition of preferential dependence (Assumption~A2) -- and the best-known repair, AHP, inherits rank reversal and unlicensed scale reinterpretation \citep{saaty1980analytic, belton1983shortcoming, dyer1990remarks, banaecosta2008critical}. What the three cases add is a demonstration of what the formula would have destroyed: it would have averaged the C6 shape gate away under good scores elsewhere, let MS's missing cross-service ACID be compensated by team scaling in C1, and manufactured a decimal-point winner in C2 exactly where the honest output is a flagged tradeoff point. The theory keeps the \emph{explication discipline} of multi-criteria decision analysis -- criteria, weights, and assumptions forced into the open -- and drops its arithmetic pretensions: the matrix of Section~\ref{sec:fitmatrix} is an \emph{explication and communication instrument}, not a computation that determines decisions; the rigorous method behind every contested cell is ATAM \citep{kazman2000atam, clements2002evaluating}, and, where money decides, its economic extension CBAM with utility-response curves and return on investment \citep{kazman2002making}.
|
||||
|
||||
\begin{keypoint}
|
||||
The fit computation is non-compensatory by design: constraints knock out before anything is scored, structural failures on High-weight dimensions veto unless a documented mitigation exists, and only then does a holistic ordinal ranking follow -- with mandatory sensitivity analysis. A weighted sum over ordinal profiles would be formally illegitimate and would average away exactly the failures that matter most.
|
||||
\end{keypoint}
|
||||
|
||||
% ============================================
|
||||
% SECTION: THE MATCHING MATRIX
|
||||
% ============================================
|
||||
\section{The Matching Matrix}
|
||||
\label{sec:fitmatrix}
|
||||
|
||||
\subsection{Cell semantics}
|
||||
|
||||
\emph{What does one cell of a seventy-cell grid actually claim?} A matrix cell answers one precisely delimited question, and misreading that question is the most common student error with this instrument.
|
||||
|
||||
\begin{definitionbox}[Cell semantics of the matching matrix]
|
||||
A cell $\mathrm{fit}(a, p)$ states the fit of pattern $p$ \emph{as the dominant structure of the core} of application class $a$ -- the pattern that owns the class's binding quality attribute scenarios. It does \emph{not} state whether $p$ is useful anywhere in a system of class $a$: hybrid roles at the edges (an event journal beside an ACID core, a batch pipeline beside an interactive product) are stated in the cell rationale, not in the cell value.
|
||||
\end{definitionbox}
|
||||
|
||||
Two consequences follow. First, a $-$ cell is not a prohibition: EDA rates $-$ as the dominant structure of a banking core, yet the same rationale names the immutable event journal as the natural regulatory audit trail at that core's edges \citep{kleppmann2017designing}. Second, the hexagonal column needs a special reading: HX is a delta pattern of dependency organisation, not a distribution style \citep{cockburn2005hexagonal, cockburn2024hexagonal}; it composes with a host (typically MM), and its cells read ``as the internal discipline of the class's core''.
|
||||
|
||||
\subsection{The \texorpdfstring{$7 \times 10$}{7 x 10} grid}
|
||||
|
||||
Table~\ref{tab:fitmatrix} shows the complete matrix -- the three cases of Section~\ref{sec:threecases}, done seventy times. Rows C6, C1, and C2 are the rows you have already computed; the remaining seven were produced by exactly the same three stages per Section~\ref{sec:fit-computation} -- knock-out and shape gate, then the H-dimension veto with documented mitigations, then the holistic ordinal reading -- and every cell is traceable to $R(a) \times C(p)$ through the rationales in Section~\ref{sec:rationales}.
|
||||
|
||||
\begin{sidewaystable}
|
||||
\centering
|
||||
\small
|
||||
\caption{The matching matrix: architecture--application fit of seven patterns (columns) as the dominant structure of the core of ten application classes (rows). Ratings on the ordinal scale $++$ (excellent fit) to $--$ (structural misfit); bold marks the cells underlying the primary recommendation of each class. Cells are computed by the three-stage procedure of Section~\ref{sec:fit-computation}; the per-class rationales appear in Section~\ref{sec:rationales}.}
|
||||
\label{tab:fitmatrix}
|
||||
\begin{tabular}{@{}p{5.2cm}ccccccc@{}}
|
||||
\toprule
|
||||
\textbf{Application class} & \textbf{L} & \textbf{MM} & \textbf{HX}$^{\dagger}$ & \textbf{MS} & \textbf{EDA} & \textbf{PF} & \textbf{SL} \\
|
||||
\midrule
|
||||
C1 Core banking / transactions & $\circ$ & {\boldmath$++$} & {\boldmath$++$} & $\circ$ & $-$ & $\circ$ & $-$ \\
|
||||
C2 Social media / content platform & $\circ$ & $+$ & $\circ$ & {\boldmath$++$} & {\boldmath$++$} & $\circ$ & $\circ$ \\
|
||||
C3 Back-office / workflow & $+$ & {\boldmath$++$} & $+$ & $--$ & $-$ & $\circ$ & $\circ$ \\
|
||||
C4 ERP / enterprise core system & $\circ$ & {\boldmath$++$} & $+$ & $--$ & $-$ & $\circ$ & $--$ \\
|
||||
C5 E-commerce platform & $-$ & {\boldmath$++$} & $+$ & $+$ & $+$ & $\circ$ & $+$ \\
|
||||
C6 Simulation / batch compute & $--$ & $\circ$ & $\circ$ & $--$ & $\circ$ & {\boldmath$++$} & $\circ$ \\
|
||||
C7 Decision support / BI analytics & $+$ & $+$ & $\circ$ & $-$ & $\circ$ & {\boldmath$++$} & $+$ \\
|
||||
C8 Real-time / IoT streaming & $--$ & $-$ & $\circ$ & $+$ & {\boldmath$++$} & $+$ & $-$ \\
|
||||
C9 Collaboration / messaging & $\circ$ & $+$ & $\circ$ & $+$ & {\boldmath$++$} & $-$ & $--$ \\
|
||||
C10 AI-native analysis / advisory & $-$ & {\boldmath$++$} & {\boldmath$++$} & $\circ$ & $+$ & $+$ & $\circ$ \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
|
||||
\vspace{0.5em}
|
||||
\begin{minipage}{0.92\textwidth}
|
||||
\footnotesize $^{\dagger}$\,HX (hexagonal / ports and adapters) is a delta pattern: it composes with a host pattern (typically MM), and its cells read ``as the internal discipline of the class's core''. Note that the HX column is never negative: as a delta pattern its cost ($c_8 = -$) surfaces only as capped cells where the change rate is low (C6, C7) -- its one-sidedness is a property of its orthogonality to the distribution axis, not a free lunch \citep{cockburn2024hexagonal}. Pattern abbreviations: L = layered/3-tier, MM = modular monolith, MS = microservices, EDA = event-driven architecture, PF = pipes-and-filters/batch pipeline, SL = serverless/FaaS.
|
||||
\end{minipage}
|
||||
\end{sidewaystable}
|
||||
|
||||
\begin{keypoint}
|
||||
Read a matrix cell as the answer to one question only: \emph{how well does this pattern serve as the dominant structure of this class's core?} The edges of the same system routinely use patterns whose cell reads $\circ$ or $-$ -- the hybrid roles are stated in the rationales, and Section~\ref{sec:hybrids} shows that hybrids are the normal case, not the exception.
|
||||
\end{keypoint}
|
||||
|
||||
% ============================================
|
||||
% SECTION: CELL RATIONALES PER APPLICATION CLASS
|
||||
% ============================================
|
||||
\section{Cell Rationales: The Ten Rows in Detail}
|
||||
\label{sec:rationales}
|
||||
|
||||
This section records, for each application class, the stage-by-stage computation behind every cell of its row -- which gate or knock-out fired, which veto, which documented mitigation lifted which cap -- plus the primary and secondary recommendation and the central trade-off the class forces. Two recurring markers keep the tables compact: \emph{veto} names the High-weight dimension on which the veto rule of Section~\ref{sec:fit-computation} fired, and \emph{mitigation} names the documented tactic or hybrid composition that lifted (or partially lifted) the cap. The operands of each row are the class's requirements table in Part~\ref{part:applications} (Tables~\ref{tab:req-c1}--\ref{tab:req-c10}) and the pattern columns of Table~\ref{tab:capability}; the evidence -- the production systems, the measured numbers -- lives in the ``what real systems chose'' discussions of Part~\ref{part:applications} and is back-referenced here, not re-narrated. Nothing in this section is new evidence: it is the same evidence, now \emph{matched}.
|
||||
|
||||
% --------------------------------------------
|
||||
\subsection{C1 -- Core banking / transaction system}
|
||||
\label{subsec:fit-c1}
|
||||
|
||||
Case~2 (Section~\ref{subsec:case-c1}) computed this row's contested pair, MM against MS, stage by stage; Table~\ref{tab:fit-c1} completes the remaining cells (operands: Table~\ref{tab:req-c1} against the pattern columns of Table~\ref{tab:capability}).
|
||||
|
||||
\begin{table}[!htbp]
|
||||
\centering
|
||||
\footnotesize
|
||||
\caption{Cell rationales for C1 (core banking): fit of each pattern as the dominant structure of the booking core.}
|
||||
\label{tab:fit-c1}
|
||||
\begin{tabular}{@{}lcp{12.2cm}@{}}
|
||||
\toprule
|
||||
\textbf{Pattern} & \textbf{Fit} & \textbf{Rationale} \\
|
||||
\midrule
|
||||
L & $\circ$ & A single ACID database satisfies the consistency veto, but technical layering fails the decades-long evolvability requirement (veto D7) and the change-isolation needs of a banking core. \\
|
||||
MM & $++$ & Cross-module ACID transactions plus enforced domain boundaries match the ledger's consistency veto and the peripheral change rate (veto D5; mitigation: hot-standby replication, the classical banking HA tactic) -- Fineract's production architecture \citep{fineract2024core}. \\
|
||||
HX & $++$ & Ports isolate a long-lived booking core from volatile channels, providers, and AI scoring adapters, making the core hermetically testable -- the standard bank-backend discipline \citep{cockburn2024hexagonal}. \\
|
||||
MS & $\circ$ & Sagas replace ACID in the money path (veto D4; mitigation only under the documented Monzo condition: organisational scale plus extreme homogeneity \citep{sewell2024monzo}), and the premium is paid in platform staff with no gain for typical team sizes \citep{fowler2015premium}. \\
|
||||
EDA & $-$ & Eventual consistency is vetoed in the booking core (veto D4: High weight against $--$, uncapped as dominant structure); as an \emph{edge} pattern the immutable event journal is the natural regulatory audit trail and integration surface \citep{kleppmann2017designing}. \\
|
||||
PF & $\circ$ & Shape gate: end-of-day clearing, statements, and risk runs are genuine batch pipelines, but the pattern cannot carry the interactive account core. \\
|
||||
SL & $-$ & Stateful sequential ordering, strict guarantees, and auditable long-lived state conflict with ephemeral stateless functions (veto D4; weak on all remaining High-weight dimensions). \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\emph{Primary recommendation:} a hexagonal modular monolith for the booking core. \emph{Secondary:} EDA at the edges (journal, fraud streams, reporting feeds) and PF for the batch runs; microservices only when organisation size forces D11 to High -- the Monzo condition \citep{sewell2024monzo}. \emph{Central trade-off:} \textbf{consistency versus scalability}. Documented practice resolves the conflict not by choosing one pattern but by \emph{placing} patterns -- a strictly consistent, even single-threaded core (the LMAX extreme of Part~\ref{part:applications} \citep{fowler2011lmax}) with eventually consistent, event-fed peripheries, the consistency boundary documented as an ADR and guarded by reconciliation fitness functions. The hybrid answer for this class is therefore the canonical one of the whole matrix: \emph{ACID core, EDA edges}.
|
||||
|
||||
% --------------------------------------------
|
||||
\subsection{C2 -- Social media / content platform}
|
||||
\label{subsec:fit-c2}
|
||||
|
||||
Case~3 (Section~\ref{subsec:case-c2}) ran this row's Stage-3 finale between MS and EDA; Table~\ref{tab:fit-c2} records the full row (operands: Table~\ref{tab:req-c2}).
|
||||
|
||||
\begin{table}[!htbp]
|
||||
\centering
|
||||
\footnotesize
|
||||
\caption{Cell rationales for C2 (social media / content platform).}
|
||||
\label{tab:fit-c2}
|
||||
\begin{tabular}{@{}lcp{12.2cm}@{}}
|
||||
\toprule
|
||||
\textbf{Pattern} & \textbf{Fit} & \textbf{Rationale} \\
|
||||
\midrule
|
||||
L & $\circ$ & Instagram proves a layered monolith scales reads via stateless replication \citep{woodruff2019static}, but single-quantum releases and technical partitioning throttle the High-weighted feature velocity (veto D7, D11) as the organisation grows. \\
|
||||
MM & $+$ & Buys Instagram-style scaling plus domain-cut change isolation (veto D5; mitigation: replicated instances); the honest ceiling is release coordination once team count passes roughly five. \\
|
||||
HX & $\circ$ & Adds testability, but the class's binding constraints (read fan-out, team scaling) live elsewhere, and feed paths carry little long-lived domain logic. \\
|
||||
MS & $++$ & Independent scaling of feed, media, and graph services plus independent team deployments match D1, D7, and D11 simultaneously (veto D3; mitigation: edge caching and precomputed timelines \citep{krikorian2013timelines}); the $--$ on cost and simplicity is an accepted price at this scale. \\
|
||||
EDA & $++$ & Fan-out-on-write \emph{is} an event flow -- the Twitter timeline architecture \citep{krikorian2013timelines}; new consumers (recommendations, moderation) attach without touching producers (veto D9; mitigation: schema/contract tests plus progressive delivery). \\
|
||||
PF & $\circ$ & Shape gate: feed precomputation, ranking-model training, and media processing are pipelines beside the serving path, never the interactive product core. \\
|
||||
SL & $\circ$ & Viral spikes suit elastic functions (veto D3: cold starts), yet sustained baseline load makes per-execution pricing structurally expensive \citep{jonas2019berkeley}. \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\emph{Primary recommendation:} an EDA + microservices hybrid at organisational scale. \emph{Secondary:} a modular monolith until that scale is \emph{measured}, not assumed -- Mastodon demonstrates full fan-out mechanics in a Rails monolith \citep{mastodon2024docs}. \emph{Central trade-off:} \textbf{read scalability and team scaling versus simplicity and cost}. The deciding measurement is deployments per developer per day as teams multiply \citep{forsgren2018accelerate}; consistency is deliberately sacrificed (eventual feeds) -- the exact mirror image of C1, which is why the pair C1/C2 is the didactic anchor of the whole matrix.
|
||||
|
||||
% --------------------------------------------
|
||||
\subsection{C3 -- Back-office / workflow application}
|
||||
\label{subsec:fit-c3}
|
||||
|
||||
Table~\ref{tab:fit-c3} gives the cell-by-cell rationale for the C3 row (the back-office workflow application; operands: Table~\ref{tab:req-c3}).
|
||||
|
||||
\begin{table}[!htbp]
|
||||
\centering
|
||||
\footnotesize
|
||||
\caption{Cell rationales for C3 (back-office / workflow application).}
|
||||
\label{tab:fit-c3}
|
||||
\begin{tabular}{@{}lcp{12.2cm}@{}}
|
||||
\toprule
|
||||
\textbf{Pattern} & \textbf{Fit} & \textbf{Rationale} \\
|
||||
\midrule
|
||||
L & $+$ & CRUD over one ACID store at office-hours load is this pattern's native habitat, and the High weight on D8 rewards its five-star simplicity; but the $-$ on High-weighted evolvability is the documented legacy-rot risk of decade-old back-office systems (veto D7; mitigation only for small, stable scope -- the mitigation is scoping, hence $+$ rather than $++$). \\
|
||||
MM & $++$ & The same run cost with domain boundaries that pay off over the 10--20-year evolution horizon that dominates this class's cost \citep{glass2002facts} -- the Pareto choice when process change is frequent. \\
|
||||
HX & $+$ & Worth the indirection exactly where long-lived process logic meets volatile integrations -- LDAP, ERP, DMS, workflow engine as adapter \citep{camunda2024zeebe} (veto D8; mitigation: apply ports selectively at the integration seams). \\
|
||||
MS & $--$ & The premium buys scaling and team autonomy this class does not need, at simplicity and run costs vetoed twice (veto D8, D10) \citep{fowler2015premium}. \\
|
||||
EDA & $-$ & Asynchronous choreography destroys the traceable, sequential process semantics (four-eyes principle, audit trail) the class is built around (veto D8: $--$ on High); a workflow engine, not a broker, is the fit. \\
|
||||
PF & $\circ$ & Shape gate: nightly reporting jobs and imports are pipelines at the edge of an interactive forms-over-data core. \\
|
||||
SL & $\circ$ & Sporadic office-hours load fits scale-to-zero economics, but the operational skill investment rarely amortises for internal IT. \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\emph{Primary recommendation:} a modular monolith with externalised process logic (a Camunda-class workflow engine behind a port). \emph{Secondary:} layered 3-tier for small, stable scope. \emph{Central trade-off:} \textbf{day-one simplicity versus multi-decade evolvability}. The measurable tiebreaker is change dispersion per process change: if a reorganisation touches every layer, the layering was wrong.
|
||||
|
||||
% --------------------------------------------
|
||||
\subsection{C4 -- ERP / enterprise core system}
|
||||
\label{subsec:fit-c4}
|
||||
|
||||
Table~\ref{tab:fit-c4} gives the cell-by-cell rationale for the C4 row (the ERP core; operands: Table~\ref{tab:req-c4}).
|
||||
|
||||
\begin{table}[!htbp]
|
||||
\centering
|
||||
\footnotesize
|
||||
\caption{Cell rationales for C4 (ERP / enterprise core system).}
|
||||
\label{tab:fit-c4}
|
||||
\begin{tabular}{@{}lcp{12.2cm}@{}}
|
||||
\toprule
|
||||
\textbf{Pattern} & \textbf{Fit} & \textbf{Rationale} \\
|
||||
\midrule
|
||||
L & $\circ$ & One schema, one transaction scope fits the integration mandate, but technical layers offer no discipline against permanent customising pressure at ERP scale (veto D7, with no scoping mitigation available -- ERP scope is never small). \\
|
||||
MM & $++$ & Modules over a shared ACID data model with a disciplined extension mechanism is \emph{literally} the Odoo/ERPNext architecture, matched in Part~\ref{part:applications} (Section~\ref{sec:c4}) \citep{odoo2024docs, frappe2024erpnext}; no veto fires -- the $-$ on D5 is Medium-weight: planned maintenance windows are an accepted ERP norm. \\
|
||||
HX & $+$ & Ports pay off at the integration peripheries (EDI, banking, tax services) and keep customising out of the core -- the survival condition for 20--30-year life cycles \citep{sap2020maintenance}. \\
|
||||
MS & $--$ & Cross-module ACID postings (order $\to$ stock $\to$ ledger) are the product's value and become distributed sagas (veto D4) -- structurally the strongest anti-fit in the grid \citep{richardson2018microservices}. \\
|
||||
EDA & $-$ & Eventual consistency between ledger and inventory contradicts the class's defining integrity guarantee (veto D4); events serve only outbound integration. \\
|
||||
PF & $\circ$ & Shape gate: period-end closing, MRP, and payroll runs are canonical scheduled pipelines inside the batch window -- a subordinate, well-fitting component. \\
|
||||
SL & $--$ & Long transactions, batch windows, stateful sessions, and a monolithic data model contradict short-lived stateless functions on every axis (veto D4, plus the sustained-load cost inversion). \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\emph{Primary recommendation:} a modular monolith. \emph{Secondary:} hexagonal discipline within it for the extension ecosystem; layered only for very small scope. \emph{Central trade-off:} \textbf{one integrated data model versus independent module scaling and deployment} -- resolved by module boundaries \emph{inside} one transactional quantum, not by process boundaries. Decades of ERP practice, and the near-absence of viable microservice ERPs, are the empirical evidence that integration wins here.
|
||||
|
||||
% --------------------------------------------
|
||||
\subsection{C5 -- E-commerce platform}
|
||||
\label{subsec:fit-c5}
|
||||
|
||||
Table~\ref{tab:fit-c5} gives the cell-by-cell rationale for the C5 row (the e-commerce platform; operands: Table~\ref{tab:req-c5}).
|
||||
|
||||
\begin{table}[!htbp]
|
||||
\centering
|
||||
\footnotesize
|
||||
\caption{Cell rationales for C5 (e-commerce platform).}
|
||||
\label{tab:fit-c5}
|
||||
\begin{tabular}{@{}lcp{12.2cm}@{}}
|
||||
\toprule
|
||||
\textbf{Pattern} & \textbf{Fit} & \textbf{Rationale} \\
|
||||
\midrule
|
||||
L & $-$ & A small shop is served honestly, but the single write path is precisely what the class's defining 10--50$\times$ seasonal peaks break (veto D2: $--$ on High, no mitigation within the pattern), and full-regression releases fail D9. \\
|
||||
MM & $++$ & Shopify's Packwerk-enforced modular Rails core carries peaks of roughly 280 million requests per minute while preserving checkout ACID (veto D2; mitigation: pod-sharded replication; veto D5; mitigation: replicated pods) -- the class's canonical case study \citep{westeinde2019deconstructing, shopify2024bfcm}. \\
|
||||
HX & $+$ & Ports around payment, logistics, tax, and search providers localise the class's very high integration churn -- and shrink the PCI audit scope \citep{pcissc2022pcidss}. \\
|
||||
MS & $+$ & Amazon's founding case shows the fit at organisational scale (veto D3; mitigation: caching and edge delivery); below that scale the platform premium ($--$ on Medium-weight D10) eats margin -- the rating rises to $++$ only when D11 measurably binds. \\
|
||||
EDA & $+$ & Order flows, inventory updates, and saga-based checkout choreography are naturally event-shaped at the edges of an ACID checkout \citep{richardson2018microservices} (veto D9; mitigation: contract tests, progressive delivery). \\
|
||||
PF & $\circ$ & Shape gate: catalogue feeds, search indexing, and recommendation training are supporting pipelines, not the storefront. \\
|
||||
SL & $+$ & Flash-sale spikes are the textbook elastic-load case (veto D3; mitigation: provisioned concurrency and edge runtimes); sustained catalogue traffic and checkout latency SLOs keep it from primary status \citep{jonas2019berkeley}. \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\emph{Primary recommendation:} a modular monolith with a hybrid consistency profile inside (catalogue eventual, checkout ACID) and event-driven edges. \emph{Secondary:} microservices at organisational scale -- team size, not traffic, decides MM versus MS (the Shopify-versus-Amazon contrast). \emph{Central trade-off:} \textbf{seasonal elasticity versus checkout consistency}. The measurable contract: p95 checkout latency and zero uncompensated oversells during peak-load tests at ten times baseline.
|
||||
|
||||
% --------------------------------------------
|
||||
\subsection{C6 -- Scientific simulation / batch compute}
|
||||
\label{subsec:fit-c6}
|
||||
|
||||
Case~1 (Section~\ref{subsec:case-c6}) computed this row almost entirely at Stage~1; Table~\ref{tab:fit-c6} records the per-cell residue (operands: Table~\ref{tab:req-c6}).
|
||||
|
||||
\begin{table}[!htbp]
|
||||
\centering
|
||||
\footnotesize
|
||||
\caption{Cell rationales for C6 (scientific simulation / batch compute).}
|
||||
\label{tab:fit-c6}
|
||||
\begin{tabular}{@{}lcp{12.2cm}@{}}
|
||||
\toprule
|
||||
\textbf{Pattern} & \textbf{Fit} & \textbf{Rationale} \\
|
||||
\midrule
|
||||
L & $--$ & Shape gate plus veto D2: an interactive serving pattern has no answer to makespan, checkpointing, or CPU-hour cost -- a category error. \\
|
||||
MM & $\circ$ & Numeric kernels are monolithic \emph{code} (OpenFOAM-style), but the architecture class around them is the pipeline; the module system contributes nothing to throughput (cap via D2) \citep{openfoam2024guide}. \\
|
||||
HX & $\circ$ & Ports around solvers and data sources buy testability of orchestration code; the compute core and the binding cost dimension are untouched. \\
|
||||
MS & $--$ & Distributing a tightly coupled numeric dataflow across service boundaries multiplies communication cost (veto D10) -- the general form of the Prime Video lesson at HPC scale \citep{kolny2023primevideo}. \\
|
||||
EDA & $\circ$ & A replayable log is useful glue for job status, but continuous event semantics add machinery where a scheduler and a DAG already express the whole control flow (cap via D9). \\
|
||||
PF & $++$ & Immutable inputs $\to$ deterministic stages $\to$ versioned outputs under Slurm/Airflow/Spark is the class's dominant form, with reproducibility by construction \citep{yoo2003slurm, zaharia2012resilient, glasserman2003monte}. \\
|
||||
SL & $\circ$ & Embarrassingly parallel bursts (Monte-Carlo fan-out) fit FaaS elasticity, but data-heavy inter-stage communication through storage recreates the Prime Video cost trap -- the split D10 rating resolves against it for data-intensive stages \citep{kolny2023primevideo}. \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\emph{Primary recommendation:} pipes-and-filters on HPC/batch infrastructure. \emph{Secondary:} serverless fan-out for bursty, communication-light parallel sections. \emph{Central trade-off:} \textbf{elastic scale-out versus data affinity} -- measured as cost per simulation and communication share of runtime. When inter-node communication dominates (Amdahl's regime), consolidate; do not distribute.
|
||||
|
||||
% --------------------------------------------
|
||||
\subsection{C7 -- Decision support / BI analytics}
|
||||
\label{subsec:fit-c7}
|
||||
|
||||
Table~\ref{tab:fit-c7} gives the cell-by-cell rationale for the C7 row (BI analytics; operands: Table~\ref{tab:req-c7}).
|
||||
|
||||
\begin{table}[!htbp]
|
||||
\centering
|
||||
\footnotesize
|
||||
\caption{Cell rationales for C7 (decision support / BI analytics).}
|
||||
\label{tab:fit-c7}
|
||||
\begin{tabular}{@{}lcp{12.2cm}@{}}
|
||||
\toprule
|
||||
\textbf{Pattern} & \textbf{Fit} & \textbf{Rationale} \\
|
||||
\midrule
|
||||
L & $+$ & The serving tier is honestly a thin layered application that delegates heavy reads to the warehouse -- Metabase ships as one JAR for exactly this reason \citep{metabase2024docs}. \\
|
||||
MM & $+$ & The same fit with cleaner seams between semantic model, query, and visualisation concerns as the tool estate grows. \\
|
||||
HX & $\circ$ & Adapter isolation of warehouse dialects helps tool vendors more than in-house BI teams; the dominant contracts are data schemas, not code ports. \\
|
||||
MS & $-$ & Splitting a read-only analytical product into services adds network and platform cost against no High-weight dimension (veto D10: $--$ on High). \\
|
||||
EDA & $\circ$ & Streaming ingestion earns its broker-operations complexity only when the freshness contract measurably tightens below the batch window \citep{kreps2011kafka}. \\
|
||||
PF & $++$ & The modern data stack \emph{is} an ELT pipeline -- sources $\to$ orchestrated DAGs $\to$ warehouse $\to$ serving -- with lineage and refresh contracts as first-class audit artefacts (D1 is delegated to the output store by design) \citep{beauchemin2015airflow, kimball2013warehouse}. \\
|
||||
SL & $+$ & Scheduled, spiky transformation jobs are a natural fit for pay-per-run functions (the $++$ side of the split D10 rating), though warehouse-native scheduling often does the same more cheaply. \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\emph{Primary recommendation:} pipes-and-filters (ELT) feeding a layered serving tier -- the canonical hybrid of the row. \emph{Secondary:} EDA ingestion where freshness SLAs demand it. \emph{Central trade-off:} \textbf{data freshness versus cost and simplicity}. ``Consistency as of the last refresh'' is a deliberately chosen third consistency semantics beside ACID and eventual; the ADR to write is the freshness contract, the fitness functions are refresh-window adherence and p95 dashboard latency -- and tightening freshness towards real time drags the class into C8 economics.
|
||||
|
||||
% --------------------------------------------
|
||||
\subsection{C8 -- Real-time / IoT streaming}
|
||||
\label{subsec:fit-c8}
|
||||
|
||||
Table~\ref{tab:fit-c8} gives the cell-by-cell rationale for the C8 row (real-time streaming; operands: Table~\ref{tab:req-c8}).
|
||||
|
||||
\begin{table}[!htbp]
|
||||
\centering
|
||||
\footnotesize
|
||||
\caption{Cell rationales for C8 (real-time / IoT streaming).}
|
||||
\label{tab:fit-c8}
|
||||
\begin{tabular}{@{}lcp{12.2cm}@{}}
|
||||
\toprule
|
||||
\textbf{Pattern} & \textbf{Fit} & \textbf{Rationale} \\
|
||||
\midrule
|
||||
L & $--$ & Shape gate plus veto D2: a synchronous request/response monolith cannot sustain continuous ingest at the world's production rate with backpressure. \\
|
||||
MM & $-$ & Modularity helps the codebase, but the single quantum caps sustained ingest and fault isolation (veto D2, D5) and cannot provide the durable, partitioned, replayable transport the class is defined by. \\
|
||||
HX & $\circ$ & Ports isolate processing logic from broker APIs (easing Kafka-to-Pulsar-style migrations); the binding constraints are throughput semantics, not dependency direction. \\
|
||||
MS & $+$ & Stream processors deploy naturally as long-running services aligned with the dataflow (which keeps the D3 concern out of a request/response path) -- provided boundaries follow the flow, exactly where Segment's per-destination cut failed \citep{noonan2018goodbye}. \\
|
||||
EDA & $++$ & A durable, partitioned, replayable log with decoupled producers and consumers is the class's defining structure -- Kafka's origin story \citep{kreps2011kafka, lee2019kafka}. \\
|
||||
PF & $+$ & Stream processing is pipes-and-filters over a log -- the batch form's latency rating ($--$ on High-weighted D3, veto) is lifted by its documented streaming incarnation with exactly-once checkpointing \citep{carbone2017state, akidau2015dataflow}. \\
|
||||
SL & $-$ & Per-event function invocation at sustained millions of events per second is dominated economically (the $--$ side of the split D10 rating) and latency-wise (cold starts, veto D3) by long-running stream processors. \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\emph{Primary recommendation:} EDA (log-centric broker topology) with streaming pipes-and-filters as the processing layer -- Kafka + Flink + OLAP serving, the documented Uber stack \citep{fu2021realtime}. \emph{Secondary:} microservice processors where team ownership demands it. \emph{Central trade-off:} \textbf{delivery semantics versus operational complexity and cost}. Exactly-once and event-time correctness are bought with checkpointing machinery and a permanent operations competence; the pragmatic norm is at-least-once plus idempotence, decided per stream, per scenario. The measurement contract: consumer lag, watermark delay, and duplicate rate under chaos experiments.
|
||||
|
||||
% --------------------------------------------
|
||||
\subsection{C9 -- Collaboration / messaging}
|
||||
\label{subsec:fit-c9}
|
||||
|
||||
Table~\ref{tab:fit-c9} gives the cell-by-cell rationale for the C9 row (collaboration/messaging; operands: Table~\ref{tab:req-c9}).
|
||||
|
||||
\begin{table}[!htbp]
|
||||
\centering
|
||||
\footnotesize
|
||||
\caption{Cell rationales for C9 (collaboration / messaging).}
|
||||
\label{tab:fit-c9}
|
||||
\begin{tabular}{@{}lcp{12.2cm}@{}}
|
||||
\toprule
|
||||
\textbf{Pattern} & \textbf{Fit} & \textbf{Rationale} \\
|
||||
\midrule
|
||||
L & $\circ$ & Fine for small installations, but millions of long-lived stateful connections are a resource profile the pattern never modelled (cap via D5). \\
|
||||
MM & $+$ & No veto beyond D5 (mitigation: replicated instances); the single-binary-by-design fit is the Mattermost case of Part~\ref{part:applications} (Section~\ref{sec:c9}) \citep{mattermost2024docs}. \\
|
||||
HX & $\circ$ & Helps swap storage and push providers (Discord's MongoDB $\to$ Cassandra $\to$ ScyllaDB path); the class's crux -- connection fan-out -- is orthogonal to dependency direction \citep{ingram2023discord}. \\
|
||||
MS & $+$ & Discord's per-attribute specialisation (BEAM gateways, Rust data services) shows targeted services exactly where tail latency demands them (veto D3; mitigation: specialised low-latency services) \citep{ingram2023discord}. \\
|
||||
EDA & $++$ & Gate passed on the push path -- the class's binding fan-out delivery scenario (Table~\ref{tab:req-c9}); no veto on the High set, and the pattern--domain coincidence is the one Part~\ref{part:applications} records for the push layer (Section~\ref{sec:c9}) \citep{hohpe2003enterprise}. \\
|
||||
PF & $-$ & Shape gate plus veto D3 ($--$ on High): interactive bidirectional message flows are the opposite of unidirectional batch transformation (history exports aside). \\
|
||||
SL & $--$ & Structural knock-out: long-lived WebSocket connection state is the canonical anti-case for short-lived stateless functions \citep{jonas2019berkeley}. \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\emph{Primary recommendation:} a hybrid -- a monolithic persistence and business core with a specialised event-driven push layer, Slack's documented shape (PHP/Hack core plus the Flannel edge cache) \citep{slack2017flannel}. \emph{Secondary:} a modular monolith alone for the self-hosted market segment. \emph{Central trade-off:} \textbf{real-time fan-out at global scale versus deployability and simplicity}. The tiebreaker is the measured concurrent-connection count: below roughly $10^5$ connections the specialised push layer is premature. The same functionality spans Mattermost's single binary and Discord's polyglot cluster -- scale and business model, not the domain, decide.
|
||||
|
||||
% --------------------------------------------
|
||||
\subsection{C10 -- AI-native analysis / advisory platform}
|
||||
\label{subsec:fit-c10}
|
||||
|
||||
This is the course-project class, and its match has already run once: the mini-match of Part~\ref{part:foundations} (Table~\ref{tab:minimatch}) computed L, MM, and MS against its five High weights. Table~\ref{tab:fit-c10} extends the row to all seven candidates (operands: Table~\ref{tab:req-c10} -- rare-but-heavy requests, provenance and per-step audit duties with potential legal force \citep{eu2024aiact}, extreme model and prompt churn, per-request cost as a first-order concern).
|
||||
|
||||
\begin{table}[!htbp]
|
||||
\centering
|
||||
\footnotesize
|
||||
\caption{Cell rationales for C10 (AI-native analysis / advisory platform -- the course-project class).}
|
||||
\label{tab:fit-c10}
|
||||
\begin{tabular}{@{}lcp{12.2cm}@{}}
|
||||
\toprule
|
||||
\textbf{Pattern} & \textbf{Fit} & \textbf{Rationale} \\
|
||||
\midrule
|
||||
L & $-$ & Technical layers give the non-deterministic component no boundary, no queue, and no measurement point -- the three things it needs most (veto D7; $-$ on High-weighted D9). \\
|
||||
MM & $++$ & A domain-cut monolith hosts the deterministic services (data access, computation, audit) cheaply and gives the AI subsystem a hard module boundary that CI can verify \citep{drotbohm2023modulith} (the $-$ on D5 is Medium-weight and mitigated by replication). \\
|
||||
HX & $++$ & The LLM is an adapter on a port: swappable on provider deprecation, mockable in tests, guarded by contract validation -- the anti-corruption layer for a component that would otherwise corrupt the domain \citep{evans2003ddd, cockburn2024hexagonal, sculley2015hidden}. \\
|
||||
MS & $\circ$ & Per-service blast-radius control is welcome, but synchronous service chains multiply seconds-scale LLM latency and failure rates \citep{nygard2018release}; the D10-High veto targets per-request AI cost -- a gateway concern orthogonal to distribution -- so the platform-cost $--$ relaxes to $\circ$ rather than $-$. \\
|
||||
EDA & $+$ & Queues absorb LLM latency, rate limits, and outages, and create natural batching points for cost control -- asynchronous integration is the default for non-interactive AI work (veto D9; mitigation: the eval harness replaces end-to-end event testing as the correctness instrument). \\
|
||||
PF & $+$ & Ingestion $\to$ chunking $\to$ embedding $\to$ index, and the eval harness itself, are pipelines with versioned data contracts \citep{lewis2020rag, barnett2024seven}; $+$ rather than $++$ because the interactive advisory surface is not a pipeline ($--$ on Medium-weight D3). \\
|
||||
SL & $\circ$ & Event-glue around batch APIs fits (spiky advisory load hits the $++$ side of the split D10 rating); platform timeouts against minutes-long LLM/solver runs and opaque per-call cost stacking do not \citep{jonas2019berkeley}. \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\emph{Primary recommendation:} a hexagonal modular monolith -- deterministic core, AI adapters at ports, an LLM gateway as the single measurement point -- plus pipes-and-filters for ingestion and evals and an orchestrated agent workflow for the AI layer. This is a \emph{designed hybrid}, and saying so explicitly is part of the theory. \emph{Secondary:} EDA for the AI job and audit spine. \emph{Central trade-off:} \textbf{agent autonomy and capability versus cost, latency, and testability} -- governed by a token-cost budget and a p95 latency budget per use case as CI-gated fitness functions (Section~\ref{sec:contract}), and by the determinism boundary: \emph{LLM agents propose; deterministic services decide and book} (Part~\ref{part:ai}).
|
||||
|
||||
\begin{keypoint}
|
||||
Every cell of the ten rows is traceable to the same mechanics: $R(a)$ against $C(p)$, a veto where a High weight meets a deep deficit, and a documented mitigation wherever a cap was lifted. The recurring resolution across the rows is \emph{consistent core, asynchronous edges} -- hybrids arise by \emph{placing} patterns in different subsystems, never by averaging their scores.
|
||||
\end{keypoint}
|
||||
|
||||
% ============================================
|
||||
% SECTION: READING THE MATRIX AS A WHOLE
|
||||
% ============================================
|
||||
\section{Reading the Matrix as a Whole}
|
||||
\label{sec:matrix-reading}
|
||||
|
||||
\emph{What does the grid say as a whole that no single cell can?} The matrix rewards a second reading -- not cell by cell but by columns, rows, and boundaries.
|
||||
|
||||
\subsection{Column patterns: the unfashionable default and the earned premium}
|
||||
|
||||
Column-wise, the \textbf{modular monolith is primary or secondary in seven of ten classes} -- not because it is fashionable (it is conspicuously unfashionable) but because most requirements profiles weight consistency, evolvability, cost, and time-to-market higher than independent scaling, and MM is the only pattern rated $+$ or better on all four of those dimensions (Table~\ref{tab:capability}). This is the matrix-level restatement of Fowler's MonolithFirst argument: do not start with microservices even if you expect to need them, because stable service boundaries cannot be cut before the domain is understood, and refactoring \emph{between} services is far costlier than \emph{within} a monolith \citep{fowler2015monolith}.
|
||||
|
||||
\textbf{Microservices earn their premium in exactly two situations}, both visible in the grid: where High-weight read scalability, fault isolation, and team scaling coincide (C2, and conditionally C5 and C8), and nowhere else. The premium is real and quantified: the pattern rates $--$ on cost and simplicity \citep{richards2025fundamentals}, and the run-cost side materialises as platform staffing -- self-managed Kubernetes total cost of ownership runs roughly three times managed offerings, dominated by personnel \citep{fowler2015premium, portainer2024k8scost}. The two $--$ cells in the MS column (C3, C4) mark the classes that pay the premium and collect nothing.
|
||||
|
||||
\textbf{PF and EDA are workload-shaped columns.} Their $++$ cells sit precisely where the class's dominant workload shape matches the pattern's native shape -- scheduled batch for PF (C6, C7), continuous stream or fan-out for EDA (C8, C9, and the C2 fan-out) -- and the shape gate caps them at $\circ$ everywhere the class core is interactive. These two columns are the clearest demonstration that the gate of Stage~1 does real work: no amount of merit on other dimensions lets a batch pipeline carry an interactive core.
|
||||
|
||||
\textbf{The HX column is never negative} -- and that is not a free lunch but a property of orthogonality: as a delta pattern, hexagonal architecture composes with the host rather than competing with it, and its cost ($c_8 = -$) surfaces only as capped cells where the change rate is low (C6, C7) \citep{cockburn2024hexagonal}.
|
||||
|
||||
\subsection{Row patterns and the empirical support points}
|
||||
|
||||
Row-wise, \textbf{no class is served above $\circ$ by every pattern, and no pattern serves every class above $\circ$} -- Assumption~A2 made visible in a single glance at the grid. If a dominant pattern existed, its column would be uniformly positive, and this part of the module would be one page long.
|
||||
|
||||
Cell-wise, the five case-study systems of the module -- Prime Video, Segment, Shopify, Uber, and Stack Overflow -- each sit exactly on a cell boundary: they are the empirical support points at which fit and misfit have been \emph{measured in money}. Prime Video sits on the split serverless cost cell (over 90\,\% infrastructure cost reduction after consolidating a data-intensive flow into one process) \citep{kolny2023primevideo, cockcroft2023prime}; Segment sits on the MS evolvability cell read against a wrongly cut boundary (services per configuration instance, not per domain seam) \citep{noonan2018goodbye}; Shopify sits on the MM write-scalability mitigation (pod-sharded replication) \citep{westeinde2019deconstructing, shopify2024bfcm}; Uber's DOMA sits on the MS team-scaling cell at the point where service count itself became the problem \citep{gluck2020doma}; and Stack Overflow sits on the layered read-scalability deviation (cache-friendly read dominance served by roughly nine web servers) \citep{craver2016stackoverflow}.
|
||||
|
||||
\begin{keypoint}
|
||||
The modular monolith dominates the matrix as default not despite but because of its unfashionableness: most requirements profiles weight consistency, evolvability, cost, and time-to-market above independent scaling. Microservices earn their documented premium only where read scalability, fault isolation, and team scaling are simultaneously High -- and the premium is paid in platform staffing either way \citep{fowler2015premium, forsgren2018accelerate}.
|
||||
\end{keypoint}
|
||||
|
||||
\begin{thinkbox}
|
||||
Take the C5 row (e-commerce) and increase the organisation from 3 teams to 30 while holding traffic constant. Which cells change, through which dimension, and at which stage of the three-stage procedure? Now hold the organisation at 3 teams and multiply traffic by 50. Why does the second variation move the row so much less than the first -- and what does that say about the popular claim that ``we need microservices to scale''?
|
||||
\end{thinkbox}
|
||||
|
||||
% ============================================
|
||||
% SECTION: HYBRIDS AND EVOLUTION PATHS
|
||||
% ============================================
|
||||
\section{Hybrids and Evolution Paths}
|
||||
\label{sec:hybrids}
|
||||
|
||||
\emph{What happens when a fit that was right stops being right?} Four documented episodes set this section's agenda. In 2018, Segment -- whose per-destination microservice cut had grown into more than 140 services a small team could no longer test or operate -- consolidated them back into one deployable \citep{noonan2018goodbye}. In 2023, Amazon Prime Video moved its audio/video monitoring workflow from a serverless orchestration into a single process and cut infrastructure cost by over 90\,\% \citep{kolny2023primevideo, cockcroft2023prime}. Shopify chose the opposite of extraction: stay a monolith, enforce module boundaries with Packwerk, shard whole-monolith pods \citep{westeinde2019deconstructing, shopify2024bfcm}. And the classical outward move -- growing the new structure around a legacy core -- has carried its own name since 2004: the Strangler Fig \citep{fowler2004strangler}. None of these corrects a wrong initial decision; each is a fit that \emph{was} right decaying as profile, organisation, or measured load drifted -- Assumption~A5 in production. This section teaches the two instruments for exactly that situation, as rules rather than footnotes: hybrids, which place different patterns where one no longer serves all subsystems, and evolution paths, the documented, repeatable repairs between patterns.
|
||||
|
||||
\subsection{Hybrids are the normal case}
|
||||
|
||||
Eight of the ten primary recommendations in Section~\ref{sec:rationales} are compositions: a consistent core with event-driven edges (C1, C5), a pipeline feeding a serving layer (C7), a log with stream processors (C8), a monolith with a specialised push layer (C9), a hexagonal core with pipelines and orchestration (C10). Only C4 (the pure modular monolith) and C6 (the pure pipeline) come close to a single-pattern answer -- and even they carry subordinate pipelines and glue.
|
||||
|
||||
The unit of fit evaluation is therefore the \emph{subsystem with its own architecture quantum} -- its own unit of deployment, scaling, and failure. Applying the matrix to a whole enterprise in one stroke is a category error the theory explicitly forbids: the question is never ``is this company a microservices company?'' but ``what is the dominant structure of \emph{this} subsystem's core, and which patterns serve its edges?''. The composition itself must be recorded; a C4-model container diagram is the natural notation, since the seven patterns differ most visibly at container level \citep{brown2024c4}.
|
||||
|
||||
\subsection{Fit is a function of time}
|
||||
|
||||
Lehman's laws guarantee the drift the opening episodes displayed: a system embedded in the real world must continually change or become progressively less useful, and its complexity increases unless work is invested to reduce it \citep{lehman1980laws, lehman1996laws}. A fit established at design time therefore decays (Assumption~A5), and every recommendation must carry a migration strategy. Three documented strategies span the space:
|
||||
|
||||
\begin{itemize}
|
||||
\item \textbf{MonolithFirst.} The argument already met in Section~\ref{sec:matrix-reading}: stable service boundaries cannot be cut before the domain is understood, so do not start with microservices even if you expect to need them \citep{fowler2015monolith}. The matrix encodes this as the MM column's default dominance; the evolution path encodes it as the sanctioned starting state.
|
||||
\item \textbf{Strangler Fig.} Grow the new structure around the old, intercepting and capturing function by function, keeping the migration incremental and stoppable at any point \citep{fowler2004strangler}. The pattern works in both directions. Outward: extracting services from a monolith along verified module boundaries. Inward: the Segment and Prime Video consolidations that opened this section \citep{noonan2018goodbye, kolny2023primevideo}. Uber's DOMA shows a third direction: beyond roughly 2{,}200 services, a \emph{second} structuring level (about 70 domains with gateways) had to be re-introduced -- convergence back towards macro-modules \citep{gluck2020doma}.
|
||||
\item \textbf{Sacrificial architecture.} Consciously accept that the current structure will be replaced in a few years while keeping internal quality high \citep{fowler2014sacrificial} -- especially legitimate for AI-native components whose model and tool landscape turns over in months.
|
||||
\end{itemize}
|
||||
|
||||
Figure~\ref{fig:evolution} summarises the documented evolution paths between the patterns as a state diagram: states are patterns, transitions are named migration strategies with their documented cases.
|
||||
|
||||
\begin{figure}[htbp]
|
||||
\centering
|
||||
\resizebox{\textwidth}{!}{%
|
||||
\begin{tikzpicture}[
|
||||
sysbox/.style={rectangle, draw, rounded corners=4pt, minimum width=3.4cm, minimum height=1.2cm, align=center, font=\small\sffamily, line width=0.8pt},
|
||||
core/.style={sysbox, fill=bankblue!20, draw=bankblue, font=\small\sffamily\bfseries},
|
||||
comp/.style={sysbox, fill=bankgreen!15, draw=bankgreen},
|
||||
extern/.style={sysbox, fill=gray!15, draw=gray!60!black},
|
||||
arr/.style={-{Stealth[length=2.5mm]}, thick, gray!60!black},
|
||||
lbl/.style={font=\footnotesize\sffamily, align=center}
|
||||
]
|
||||
\node[extern] (L) at (0,0) {L\\Layered monolith};
|
||||
\node[core] (MM) at (8,0) {MM\\Modular monolith};
|
||||
\node[comp] (MS) at (16,0) {MS\\Microservices};
|
||||
\node[extern] (SL) at (0,-4.0) {SL\\Serverless orchestration};
|
||||
\node[comp] (DOM) at (16,-4.0) {Domain-bundled\\services (DOMA)};
|
||||
|
||||
\draw[arr] (L) -- node[lbl, above=1pt] {enforce domain boundaries\\(Packwerk, ArchUnit, Modulith)} (MM);
|
||||
\draw[arr] (MM) -- node[lbl, above=1pt] {Strangler-Fig extraction\\when D11 measurably binds} (MS);
|
||||
\draw[arr] (MS.south west) to[bend left=22] node[lbl, below=3pt] {consolidation (Segment 2018)} (MM.south east);
|
||||
\draw[arr] (MS) -- node[lbl, right=3pt] {re-bundle into $\sim$70 domains\\(Uber DOMA 2020)} (DOM);
|
||||
\draw[arr] (SL.east) -| node[lbl, above=2pt, pos=0.22] {process consolidation\\(Prime Video 2023, $-90\,\%$ cost)} (MM.south);
|
||||
\draw[arr, dashed] (L.north) to[out=55, in=125, looseness=1.1] node[lbl, above=2pt] {sacrificial rebuild (planned replacement)} (MM.north);
|
||||
\end{tikzpicture}}%
|
||||
\caption{Documented evolution paths between architectural patterns. States are patterns; labelled transitions are migration strategies with their documented cases \citep{fowler2004strangler, fowler2015monolith, fowler2014sacrificial, noonan2018goodbye, kolny2023primevideo, gluck2020doma}. The modular monolith is both the sanctioned starting state (MonolithFirst) and the documented consolidation target.}
|
||||
\label{fig:evolution}
|
||||
\end{figure}
|
||||
|
||||
\begin{keypoint}
|
||||
\textbf{Maxim 5.} Choose the pattern for the requirements profile you can verify today; buy options on the profile you expect tomorrow -- via module boundaries, ports, and a strangler-ready seam, not via speculative distribution. Every arrow in Figure~\ref{fig:evolution} is cheaper to traverse when the boundaries it needs were bought in advance as modules and ports rather than as processes.
|
||||
\end{keypoint}
|
||||
|
||||
\begin{ailinse}[Sacrificial architecture for AI-native components]
|
||||
Axis~B sharpens the evolution argument. LLM providers deprecate models on windows of months, not years \citep{openai2026deprecations}, and the agent-framework landscape turns over even faster. For the AI layer of a C10 system, sacrificial architecture is therefore not an admission of failure but the rational default \citep{fowler2014sacrificial}: design the AI subsystem to be replaced -- behind a port, with an eval harness as the acceptance gate for its successor -- while the deterministic core is designed to last. The port boundary converts a provider deprecation from an architecture revision (the steep part of the cost-of-change curve, Section~\ref{sec:contract}) into an adapter task.
|
||||
\end{ailinse}
|
||||
|
||||
% ============================================
|
||||
% SECTION: THE DECISION PROCEDURE
|
||||
% ============================================
|
||||
\section{The Decision Procedure}
|
||||
\label{sec:procedure}
|
||||
|
||||
\emph{How does a pre-filtered shortlist become a defensible decision?} The matrix pre-filters; it does not decide. The teachable, auditable procedure compresses the SEI method family \citep{bass2021software, barbacci2003quality, kazman2000atam} into eight steps, each with a defined artefact and a defined measurement, and continues into the life cycle per Assumption~A5.
|
||||
|
||||
\begin{enumerate}
|
||||
\item[\textbf{(i)}] \textbf{Identify the ASRs.} Mine business goals, stakeholder interviews, and the regulatory frame -- not the requirements document alone, which empirically under-specifies architecturally significant requirements \citep{chen2013characterizing}. Classify the system as an instance (or blend) of the ten application classes -- a \emph{hypothesis about its ASR bundle} to inherit and then correct.
|
||||
\item[\textbf{(ii)}] \textbf{Formulate quality attribute scenarios with response measures.} Six parts each; no scenario without a number \citep{bass2021software}. An unfalsifiable requirement cannot discriminate between patterns (Assumption~A4).
|
||||
\item[\textbf{(iii)}] \textbf{Prioritise in a utility tree.} Rate each leaf on (business importance, achievement difficulty) $\in \{H,M,L\}^2$; the $(H,H)$ leaves \emph{are} the weights of $R(a)$ -- this is where the matrix weights come from, so they are derivable, not arbitrary \citep{kazman2000atam}.
|
||||
\item[\textbf{(iv)}] \textbf{Pre-filter candidate patterns via the matrix.} Apply the knock-out constraints and shape gate first, then the veto rule (Section~\ref{sec:fit-computation}). Output: two to three candidate patterns or compositions, including the hybrid options named in the relevant class row.
|
||||
\item[\textbf{(v)}] \textbf{Trade-off analysis (ATAM-light).} Walk the $(H,H)$ scenarios against each candidate's tactic bundle; identify \emph{sensitivity points} (one decision, large effect on one attribute) and \emph{tradeoff points} (one decision, opposing effects on several attributes); classify each as risk or non-risk \citep{kazman2000atam, clements2002evaluating}. Where money decides, extend with CBAM utility-response curves -- what is 99.99\,\% availability \emph{worth}, versus 99.9\,\%? \citep{kazman2002making}. Sensitivity analysis is mandatory: vary the weights plausibly; if the recommendation flips, you have found a genuine tradeoff point that deserves stakeholder negotiation, not a formula.
|
||||
\item[\textbf{(vi)}] \textbf{Decide and record as an ADR.} Context, decision, consequences -- including the negative ones; superseded, never edited \citep{nygard2011documenting}. The MADR fields ``decision drivers / considered options'' carry the utility-tree weights and the matrix row into the record \citep{kopp2018markdown}; this fulfils ISO/IEC/IEEE 42010 Clause~6.10 by construction and counters architectural knowledge vaporisation \citep{iso2022architecture, jansen2005software}.
|
||||
\item[\textbf{(vii)}] \textbf{Define the measurement contract.} Every ADR ends with the fitness functions that would falsify it -- with thresholds (Section~\ref{sec:contract}).
|
||||
\item[\textbf{(viii)}] \textbf{Measure in operation and keep evolution paths open.} The DORA metrics and the quality-attribute-specific measures run continually; Lehman indicators (growth, complexity trend, debt stock) run quarterly \citep{lehman1980laws, cunningham1992wycash, kruchten2012techdebt}. When measurements falsify the decision, the sanctioned responses are the documented evolution paths of Section~\ref{sec:hybrids}. A revised decision is a new ADR that supersedes -- never silently overwrites -- the old one.
|
||||
\end{enumerate}
|
||||
|
||||
Note how much of this you have already done. Steps~(i)--(iii) are the pipeline Part~\ref{part:applications} ran ten times over -- challenges to binding scenarios to utility-tree weights -- so classifying and weighting a profile is inherited work, corrected against elicited scenarios rather than invented. Steps~(iv)--(vi) are the three cases of Section~\ref{sec:threecases} performed under governance: the same gate, veto, and ordinal reading, with the sensitivity analysis escalated to stakeholders and the outcome recorded. Steps~(vii) and~(viii) are the genuinely new obligations, and the remainder of this part belongs to them.
|
||||
|
||||
\begin{keypoint}
|
||||
\textbf{Maxim 6} (restated from Part~\ref{part:foundations}). An architecture decision without a response measure is an opinion; with a response measure and a fitness function it is a testable hypothesis. The eight steps exist to manufacture exactly that transformation -- from stakeholder concern to falsifiable, monitored commitment.
|
||||
\end{keypoint}
|
||||
|
||||
\subsection{A full worked example: the course-project decision run}
|
||||
\label{subsec:decision-example}
|
||||
|
||||
\begin{examplebox}[Decision run for the Portfolio Intelligence Platform (class C10) -- steps (i)--(iv)]
|
||||
\textbf{(i) ASRs.} The platform analyses client portfolios and generates advisory answers with LLM support. Stakeholder interviews and the regulatory frame yield the ASR bundle: grounded answers with provenance, complete per-step audit logging (EU AI Act duties may attach \citep{eu2024aiact}), per-request cost control, provider-migration robustness, and an extreme change rate for prompts and models. Classification: an instance of C10, inheriting C6/C7 traits (index and eval pipelines) and C3 traits (deterministic services).
|
||||
|
||||
\textbf{(ii) Scenarios.} The binding scenario: \emph{a customer (source) submits a request for which the LLM generates a factually wrong recommendation (stimulus) in normal operation (environment) of the advisory platform (artifact); the deterministic validation layer blocks the answer and escalates to a human (response); detection rate $\geq 99\,\%$ at $< 2$\,s added latency (response measure)} \citep{bass2021software}. Companion scenarios fix the cost budget (token cost per request $\leq$ CHF~0.40 at p95), the latency budget (advisory answer $< 20$\,s end-to-end), and the migration scenario (provider deprecation absorbed within one sprint, zero domain-code changes).
|
||||
|
||||
\textbf{(iii) Utility tree.} The $(H,H)$ leaves land on D6 (auditability), D7 (evolvability under model churn), D9 (testability, operationalised as eval pass rate), D10 (cost per request), and D12 (AI integrability) -- reproducing the High weights of the C10 column in Table~\ref{tab:requirements}, as the theory predicts.
|
||||
|
||||
\textbf{(iv) Matrix shortlist.} The C10 row (Table~\ref{tab:fit-c10}) yields MM $++$ and HX $++$ as core candidates, with EDA $+$ (job/audit spine) and PF $+$ (ingestion and eval pipelines) as named edge patterns; L is excluded by veto, MS and SL are capped at $\circ$. Shortlist: (a) hexagonal modular monolith with pipelines and an async job spine; (b) the same core with a fuller EDA backbone.
|
||||
\end{examplebox}
|
||||
|
||||
\begin{examplebox}[Decision run for the Portfolio Intelligence Platform (class C10) -- steps (v)--(viii)]
|
||||
\textbf{(v) ATAM-light.} Walking the $(H,H)$ scenarios against both candidates identifies one dominant \emph{sensitivity point} -- the placement of the LLM gateway, on which auditability, cost telemetry, and migration cost all hinge -- and one genuine \emph{tradeoff point}: LLM context length (answer quality up; cost and latency down) \citep{kazman2000atam}. The weight variation test flips nothing between (a) and (b) for the core; it does flip the job-spine choice when audit-log completeness is weighted maximally, which is recorded as a risk to be retired by a spike. CBAM reasoning settles the spine: the fuller EDA backbone buys availability the class only weights Medium, at an operations cost the class weights High \citep{kazman2002making} -- candidate (a) wins.
|
||||
|
||||
\textbf{(vi) ADR.} The decision is recorded as ADR-007 (Listing~\ref{lst:adr007}), whose decision drivers are the utility-tree weights and whose considered options are the matrix shortlist -- one matrix row, narrated.
|
||||
|
||||
\textbf{(vii) Measurement contract.} ADR-007 ends with the fitness functions of Table~\ref{tab:contract}: module-boundary verification, the determinism-boundary rule, latency and token budgets, eval pass rate, reconciliation, and chaos drills -- each with threshold and cadence.
|
||||
|
||||
\textbf{(viii) Operation.} The DORA four keys run per deployable unit; the eval harness gates every prompt and model change; Lehman indicators run quarterly. The declared evolution paths: extract the ingestion pipeline to its own quantum if batch load grows; replace the LLM adapter on deprecation (sacrificial by design); escalate to an EDA spine if audit volume demands it -- each a new, superseding ADR.
|
||||
\end{examplebox}
|
||||
|
||||
Listing~\ref{lst:adr007} shows the resulting record in MADR-style form \citep{kopp2018markdown, nygard2011documenting}. Note the two properties that make it more than paperwork: the considered options carry the matrix reasoning (auditable), and the final section carries the measurement contract (falsifiable). The gateway rule that the decision relies on is subsequently fixed in its own record, ADR-011 (Listing~\ref{lst:adr}, Part~\ref{part:foundations}).
|
||||
|
||||
\begin{lstlisting}[language={}, caption={ADR-007 of the course project: the architecture decision as a Markdown Architecture Decision Record, ending in its measurement contract.}, label={lst:adr007}]
|
||||
# ADR-007: Hexagonal modular monolith with LLM gateway
|
||||
Status: accepted (2026-10-12) | supersedes: ADR-003
|
||||
|
||||
## Context and problem statement
|
||||
The Portfolio Intelligence Platform (class C10) must deliver
|
||||
grounded advisory answers with full audit logging (EU AI Act),
|
||||
per-request cost control, and robustness against LLM provider
|
||||
deprecation. Change rate of prompts/models is extreme; the
|
||||
deterministic services (data access, portfolio computation,
|
||||
audit) have classical back-office profiles.
|
||||
|
||||
## Decision drivers (utility-tree (H,H) leaves)
|
||||
* D6 auditability: every agent step reconstructable
|
||||
* D7 evolvability under model churn
|
||||
* D9 testability = eval pass rate >= 95% in CI
|
||||
* D10 token cost per request <= CHF 0.40 (p95)
|
||||
* D12 AI integrability: queue, port, measurement point
|
||||
|
||||
## Considered options (matrix shortlist, Table fit-c10)
|
||||
1. Hexagonal modular monolith + PF pipelines + async jobs (++)
|
||||
2. Same core + full EDA backbone for jobs/audit (+)
|
||||
3. Microservices per capability (o)
|
||||
4. Layered monolith (-, veto D7)
|
||||
|
||||
## Decision
|
||||
Option 1. Deterministic core as Spring-Modulith-verified
|
||||
modules; all LLM access via one gateway port (adapter owns
|
||||
prompts, schema validation, retries, cost telemetry);
|
||||
ingestion/eval as versioned pipelines; agent workflow
|
||||
orchestrated, not autonomous: agents propose, deterministic
|
||||
services decide and book.
|
||||
|
||||
## Consequences
|
||||
+ Provider deprecation = adapter task, not architecture revision
|
||||
+ Single measurement point for cost, latency, audit
|
||||
- Release coordination across modules (accepted, 2 teams)
|
||||
- Async job spine limited; EDA escalation path documented
|
||||
|
||||
## Measurement contract (falsifies this ADR)
|
||||
* ArchUnit/Modulith verify: 0 undeclared cross-module deps
|
||||
* Static rule: no domain service imports the LLM gateway
|
||||
except via the declared port (0 violations)
|
||||
* p95 advisory answer < 20 s (CI gate + production SLO)
|
||||
* Eval harness pass rate >= 95% on golden set;
|
||||
0 ontology-violating outputs shipped
|
||||
* Token cost per request <= CHF 0.40 at p95 (continual)
|
||||
* Daily reconciliation booked vs. journaled: 0 discrepancies
|
||||
* DORA four keys per deployable unit; review quarterly
|
||||
\end{lstlisting}
|
||||
|
||||
% ============================================
|
||||
% SECTION: THE MEASUREMENT CONTRACT
|
||||
% ============================================
|
||||
\section{The Measurement Contract}
|
||||
\label{sec:contract}
|
||||
|
||||
\emph{How does a decision made this year stay honest in year five?} One case motivates the apparatus of this section. What actually triggered the Prime Video re-architecture was not an architecture review but a telemetry signal: infrastructure cost per stream, measured continuously, crossed what the team was willing to pay -- and that measurement, not an opinion, first forced and then vindicated the redesign \citep{kolny2023primevideo}. The cost dashboard was a fitness function in everything but name: an objective, continuously evaluated check on an architectural characteristic whose breach converted a running structure from ``accepted'' into ``falsified''. The empirical anchor for building such checks systematically is developed below: DORA's finding that loosely coupled architectures and teams are the strongest predictor of continuous delivery \citep{dora2017sodr, forsgren2018accelerate} -- coupling, this theory's leading dimension, is a \emph{measurable} property.
|
||||
|
||||
Step~(vii) generalises the observation into a concept, and it is where this course differs from a classical architecture lecture: the chosen fit is codified as a \emph{measurement contract} -- the set of executable invariants under which the architecture is allowed to keep evolving. \emph{The architecture may change freely as long as the contract stays green} \citep{ford2022evolutionary}.
|
||||
|
||||
\subsection{Fitness functions}
|
||||
|
||||
\begin{definitionbox}[Architectural fitness function]
|
||||
An \emph{architectural fitness function} is ``any mechanism that provides an objective integrity assessment of some architectural characteristic'' \citep{ford2022evolutionary}. Fitness functions turn quality attributes into executable, objective checks and thereby move architecture governance from review meetings into the CI/CD pipeline. They are classified along two primary dimensions: \textbf{scope} -- \emph{atomic} (one characteristic in isolation, e.g.\ a dependency rule as a unit test) versus \emph{holistic} (combined characteristics in interplay, e.g.\ security and data freshness under load) -- and \textbf{cadence} -- \emph{triggered} (event-based, on every build or deployment), \emph{continual} (running permanently in operation, e.g.\ chaos experiments), or \emph{temporal} (time-scheduled, e.g.\ dependency-freshness time bombs).
|
||||
\end{definitionbox}
|
||||
|
||||
Three worked instrument families recur throughout the module:
|
||||
|
||||
\begin{enumerate}
|
||||
\item \textbf{Dependency checks as CI gates.} ArchUnit (Java; analogues: NetArchTest for .NET, dependency-cruiser for JavaScript, import-linter for Python) formulates rules such as ``the domain layer imports no framework'', ``no cycles between modules'', or ``repositories are called only by services'' as unit tests that fail the build on violation \citep{archunit2024userguide}. Spring Modulith verification does the same for module boundaries declared in a modular monolith \citep{drotbohm2023modulith}. These are atomic, triggered fitness functions -- and they are what makes the MM ratings of the capability table \emph{enforceable} rather than aspirational: without automated boundary verification, boundary erosion is the documented failure mode of the pattern.
|
||||
\item \textbf{Performance and cost budgets as pipeline gates.} Latency thresholds, bundle sizes, or Lighthouse scores are declared in a budget file and gate the pipeline \citep{google2024lighthouseci, ford2022evolutionary}. The transfer to Axis~B is direct: token-cost budgets and p95 latency budgets per AI use case are the same mechanism with new units.
|
||||
\item \textbf{Chaos experiments as continual holistic fitness functions.} Netflix's Chaos Monkey terminates production instances to test resilience assumptions permanently; formalised as the principles of chaos engineering \citep{basiri2016chaos}, and cited by \citet{ford2022evolutionary} as the paradigm of a continual, holistic fitness function. For the matrix, chaos experiments are the instrument that verifies the D5 cells: a claimed blast radius is a hypothesis until an instance has actually been killed under load.
|
||||
\end{enumerate}
|
||||
|
||||
\subsection{DORA metrics: the delivery layer}
|
||||
|
||||
The four DORA metrics measure whether the delivery-relevant promises of a structure are being kept: \textbf{deployment frequency} and \textbf{lead time for changes} (tempo), \textbf{change failure rate} and \textbf{failed-deployment recovery time} (stability) \citep{forsgren2018accelerate, dora2023sodr}. The central empirical finding is that elite performers lead on \emph{all four} -- tempo and stability are not a trade-off. The strongest single result in the field supports coupling as the leading dimension of this entire theory: ``loosely coupled architectures and teams are the strongest predictor of continuous delivery'' -- in the 2017 analysis, the architecture characteristics testability and deployability contributed more to continuous delivery than test and deployment automation itself \citep{dora2017sodr, forsgren2018accelerate}. Two follow-on findings matter for the matrix: high performance is possible with all kinds of systems -- including mainframes -- provided systems and teams are loosely coupled (the label ``microservices'' is neither necessary nor sufficient); and as team count grows, deployments per developer per day \emph{rise} for high performers and \emph{fall} for low performers \citep{forsgren2018accelerate}.
|
||||
|
||||
Honesty requires the caveat, stated here and repeated in Section~\ref{sec:limits}: DORA's evidence is survey-based and analysed with structural equation models -- prediction, not experimental causal proof \citep{forsgren2018accelerate}. The theory treats it as the best available large-$n$ evidence, to be triangulated against case studies and the reader's own measurements, not as settled law.
|
||||
|
||||
\subsection{The four-layer measurement cascade}
|
||||
|
||||
The contract has four layers, forming a cascade from design time to evolution (Table~\ref{tab:cascade}). Each layer answers a different falsification question: is the structure intact (design time)? is the structure delivering (delivery)? is the structure keeping its runtime promises (operation)? is the structure ageing (evolution)?
|
||||
|
||||
\begin{table}[!htbp]
|
||||
\centering
|
||||
\small
|
||||
\caption{The four-layer measurement cascade of the measurement contract: instruments and example checks per layer.}
|
||||
\label{tab:cascade}
|
||||
\begin{tabular}{@{}p{2.2cm}p{5.6cm}p{6.2cm}@{}}
|
||||
\toprule
|
||||
\textbf{Layer} & \textbf{Instruments} & \textbf{Example checks} \\
|
||||
\midrule
|
||||
Design time & Dependency rules as CI gates (ArchUnit, Spring Modulith verify, dependency-cruiser); coupling and cohesion metrics \citep{chidamber1994metrics, martin2003agile}; complexity gates \citep{mccabe1976complexity} & ``The domain layer imports no framework''; ``no cycles between modules''; ``no domain service calls the LLM gateway except via the declared port'' \\
|
||||
\addlinespace
|
||||
Delivery & The four DORA metrics \citep{forsgren2018accelerate, dora2023sodr} & Deployment frequency, lead time, change failure rate, failed-deployment recovery time -- per architecture quantum \\
|
||||
\addlinespace
|
||||
Operation & SLOs and error budgets; latency and \emph{cost} budgets as pipeline gates; chaos experiments as continual holistic fitness functions \citep{basiri2016chaos, ford2022evolutionary} & p95 latency budget per scenario; token-cost budget per request; blast-radius drills \\
|
||||
\addlinespace
|
||||
Evolution & Lehman indicators \citep{lehman1980laws}; change scatter; technical-debt inventory \citep{cunningham1992wycash, kruchten2012techdebt} & Complexity trend per module; share of features touching more than two modules; debt-register review \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
Table~\ref{tab:contract} instantiates the cascade as the reference contract for the course-project class C10 -- the concrete table that ADR-007 (Listing~\ref{lst:adr007}) points to. For AI components the contract gains one artefact of the first rank: the \emph{eval harness} -- a versioned suite of test cases, scoring logic, and statistical thresholds that runs in CI like a test suite and gates every prompt change, model update, and provider migration \citep{zheng2023judging}; Part~\ref{part:ai} develops it in full.
|
||||
|
||||
\begin{table}[!htbp]
|
||||
\centering
|
||||
\small
|
||||
\caption{Reference measurement contract for the course project (application class C10): fitness functions with thresholds and cadences.}
|
||||
\label{tab:contract}
|
||||
\begin{tabular}{@{}p{2.6cm}p{5.0cm}p{3.4cm}p{2.6cm}@{}}
|
||||
\toprule
|
||||
\textbf{Concern} & \textbf{Fitness function} & \textbf{Threshold (example)} & \textbf{Cadence} \\
|
||||
\midrule
|
||||
Module boundaries & ArchUnit / Spring Modulith verify: no undeclared cross-module dependency \citep{archunit2024userguide, drotbohm2023modulith} & 0 violations & triggered (every build) \\
|
||||
Determinism boundary & Static rule: no domain service imports the LLM gateway except via the declared port & 0 violations & triggered \\
|
||||
Latency & p95 end-to-end per critical scenario & advisory answer $< 20$\,s & triggered + continual \\
|
||||
Consistency & Ledger/audit reconciliation job: booked vs.\ journaled & 0 discrepancies & temporal (daily) \\
|
||||
Delivery performance & DORA four keys per deployable unit \citep{forsgren2018accelerate} & e.g.\ change failure rate $< 15\,\%$; restore $< 1$ day & continual \\
|
||||
Resilience & Chaos experiment: kill one instance/broker under load \citep{basiri2016chaos} & SLO holds; blast radius $\leq$ declared & temporal \\
|
||||
AI correctness & Eval-harness pass rate on golden set plus domain axioms & $\geq 95\,\%$ pass; 0 ontology-violating outputs shipped & triggered (every prompt/model change) \\
|
||||
AI cost & Token cost per request, per feature & $\leq$ budget (e.g.\ CHF~0.40/request at p95) & continual \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\subsection{The cost of change: what is flat and what is still steep}
|
||||
\label{subsec:cost-of-change}
|
||||
|
||||
\emph{Why does the contract matter economically?} The classical answer is Boehm's cost-of-change escalation: on waterfall project data of the 1970s, fixing a problem after delivery is up to \emph{one hundred times} more expensive than fixing it during requirements and design -- with the honest qualification that for small, uncritical systems the factor is closer to 2:1 \citep{boehm1981economics, boehm2001top10}. Modern practice has empirically \emph{flattened} that curve for changes \emph{within} an architecture: the largest replication to date -- 171 projects from 2006--2014 -- found no consistent delayed-issue effect \citep{menzies2017delayed}. Version control, automated tests, and continuous delivery did exactly what the economic argument of Extreme Programming said they would \citep{beck2004xp, humble2010continuous}.
|
||||
|
||||
The nuance the module insists on: flattened is the curve for changes within an architecture. For changes \emph{of} the architecture -- splitting a monolith, changing the communication paradigm, moving a data-intensive flow across expensive distributed boundaries -- the curve remains steep, and the evidence is the case studies themselves: Segment's consolidation and Prime Video's rewrite were, at their core, expensive architecture revisions \citep{noonan2018goodbye, kolny2023primevideo}. This asymmetry is the economic justification of the whole apparatus: justify the fit up front (because architecture revision is the change class that still costs), and keep the architecture evolvable under a green contract (because everything else is now cheap to change). Maintenance and evolution consume roughly 40--80\,\% -- typically about 60\,\% -- of life-cycle cost, mostly for enhancement rather than repair \citep{glass2002facts}; the contract is how a structure earns the right to survive that phase.
|
||||
|
||||
\begin{keypoint}
|
||||
The measurement contract converts an architecture decision into a standing experiment: design-time gates verify the structure, DORA metrics verify the delivery, budgets and chaos experiments verify the runtime promises, and Lehman indicators verify the ageing. The cost-of-change curve is flat inside a green contract and steep across architecture boundaries -- which is why the contract, not the diagram, is the artefact that protects the investment \citep{ford2022evolutionary, menzies2017delayed, boehm2001top10}.
|
||||
\end{keypoint}
|
||||
|
||||
\begin{ailinse}[Fitness functions as the operating licence for AI -- both axes]
|
||||
\textbf{Axis A (AI as a tool in the SDLC).} An agentic coding tool iterating against a dense test suite and CI-enforced architecture rules is \emph{contained}: every generated change must pass the same dependency rules, budgets, and evals as a human change, so the blast radius of ``almost right'' code is bounded by the contract. Without those gates, every agent change is unpriced risk -- and the empirical record shows AI adoption \emph{amplifying} existing delivery dysfunction rather than fixing it \citep{dora2025aireport}. The measurement contract is therefore the prerequisite for raising the change rate by an order of magnitude safely: fitness functions are the operating licence for agents.
|
||||
|
||||
\textbf{Axis B (AI as a runtime component).} The contract absorbs AI components through two new fitness-function types with old mechanics: the \emph{eval-harness pass rate} (a triggered gate on every prompt and model change, statistically thresholded \citep{zheng2023judging}) and the \emph{token-cost budget per request} (a continual gate, exactly analogous to a performance budget \citep{ford2022evolutionary}). Cost per request is a runtime quality attribute with no counterpart in classical profiles; making it a fitness function is what turns FinOps from a monthly surprise into an architectural control loop.
|
||||
\end{ailinse}
|
||||
|
||||
\begin{projektbox}
|
||||
Your project submission must ship its measurement contract, not just its architecture. Concretely, the repository must contain, wired into CI: (1) module-boundary verification with \textbf{zero violations} (ArchUnit or Spring Modulith verify, including the determinism-boundary rule: no domain service reaches the LLM gateway except via its declared port); (2) an eval harness with a versioned golden set and a \textbf{pass rate $\geq 95\,\%$} gating every prompt or model change; (3) a \textbf{token-cost budget per request} enforced as a pipeline gate and reported per feature; (4) a p95 latency budget for the advisory scenario ($< 20$\,s end-to-end); and (5) the ADR (in MADR form) whose final section \emph{is} this contract. At the project review you will be asked to demonstrate one contract violation being caught by CI -- a contract that has never failed is a contract that has never been tested.
|
||||
\end{projektbox}
|
||||
|
||||
% ============================================
|
||||
% SECTION: CONWAY AND TEAM TOPOLOGIES
|
||||
% ============================================
|
||||
\section{The Third Fit Dimension: Conway's Law and Team Topologies}
|
||||
\label{sec:conway}
|
||||
|
||||
\emph{Why do correct matrix readings still fail in real organisations?} The matrix matches patterns to application classes; D11 (team scaling) has appeared throughout as one dimension among twelve. This section makes explicit why it is more than that: the organisation is a \emph{third} party to the fit, and ignoring it is the most common way correct matrix readings fail in practice.
|
||||
|
||||
The source is older than every pattern in the matrix. Conway observed in 1968: ``Any organization that designs a system (defined broadly) will produce a design whose structure is a copy of the organization's communication structure'' \citep{conway1968committees} -- named ``Conway's law'' by Brooks \citep{brooks1975mythical} and empirically supported by mirroring studies of organisation and product structure \citep{maccormack2012mirroring}. The consequence for this theory is direct: every architecture decision is simultaneously a team-structure decision, whether acknowledged or not. A microservices topology assigned to a single five-person team produces a distributed monolith -- many quanta, one communication structure, the worst cells of two columns at once \citep{newman2021building}. A modular monolith assigned to thirty independent teams produces a release-coordination bottleneck that no amount of code quality repairs.
|
||||
|
||||
Team Topologies turns the law from a hazard into a design instrument \citep{skelton2019team}. Its four fundamental team types -- \emph{stream-aligned} teams delivering end-to-end on one value stream, \emph{platform} teams that reduce the load of stream teams, \emph{enabling} teams that build missing capabilities, and \emph{complicated-subsystem} teams that encapsulate specialist knowledge (an ML inference subsystem is the canonical course-relevant example) -- and three interaction modes (collaboration, X-as-a-service, facilitating) give the vocabulary for matching team structure to pattern choice. Two of its concepts bind directly into the matrix. First, \emph{cognitive load as a design criterion}: team and software boundaries should be cut so that no team's cognitive load exceeds its capacity -- ``team-sized software'' is an architectural yardstick, and it explains why the MS column demands stream-aligned teams with full ownership as a precondition, not an outcome \citep{skelton2019team}. Second, the \emph{inverse Conway manoeuvre}: deliberately structure the organisation to mirror the \emph{target} architecture, so that Conway's law works for the design instead of against it \citep{skelton2019team, forsgren2018accelerate}.
|
||||
|
||||
The empirical anchor is the DORA scaling finding already cited in Section~\ref{sec:contract}: loose coupling of \emph{architectures and teams} -- measured jointly, which is itself a Conway statement -- is the strongest predictor of continuous delivery, and it is the mechanism that lets deployments per developer per day scale linearly with team count \citep{dora2017sodr, forsgren2018accelerate}. The matrix encodes the organisational variable in D11, and the class rationales repeatedly show it deciding contested rows: the same C1 profile admits LMAX's single-threaded core and Monzo's 2{,}800 services at different organisation sizes \citep{fowler2011lmax, sewell2024monzo}; the same C5 profile splits into Shopify's modular monolith and Amazon's microservices along team count, not traffic \citep{westeinde2019deconstructing}. No twelve-dimensional profile fully captures an organisation -- Section~\ref{sec:limits} lists this as a limit -- but the rule of thumb is teachable:
|
||||
|
||||
\begin{keypoint}
|
||||
The fit is three-way: pattern $\leftrightarrow$ application class $\leftrightarrow$ team structure. Check D11 last but veto on it first: a pattern whose team precondition is not met -- microservices without stream-aligned ownership, a monolith across too many coordinating teams -- will fail regardless of how well the other eleven dimensions match \citep{conway1968committees, skelton2019team, forsgren2018accelerate}. If the target architecture and the organisation disagree, either apply the inverse Conway manoeuvre or change the target -- Conway's law does not negotiate.
|
||||
\end{keypoint}
|
||||
|
||||
% ============================================
|
||||
% SECTION: LIMITS OF THE THEORY
|
||||
% ============================================
|
||||
\section{Limits of the Theory -- Applied to Itself}
|
||||
\label{sec:limits}
|
||||
|
||||
A theory whose declared standard is that unfalsifiable claims have no place in architecture decisions must state how it can itself mislead. Six limits, stated plainly.
|
||||
|
||||
\begin{enumerate}
|
||||
\item \textbf{Ordinal scales, no arithmetic.} The ratings support rankings and exclusions, never percentages. Any weighted-sum reading of the matrix imports the documented defects of additive multi-criteria methods over ordinal data: rank reversal \citep{belton1983shortcoming}, axiomatic conflict with utility theory \citep{dyer1990remarks}, scale misinterpretation \citep{banaecosta2008critical}, and pseudo-precision -- priorities with three decimal places derived from coarse verbal comparisons. We keep the explication discipline of multi-criteria decision analysis and drop its arithmetic pretensions. Sensitivity analysis is mandatory, not decorative; unstable rankings are findings (tradeoff points), not errors.
|
||||
\item \textbf{Context-dependence of ratings.} Every capability cell encodes a \emph{typical} workload. The serverless cost cell literally inverts with load shape (Prime Video) \citep{kolny2023primevideo}, and the layered read-scalability cell inverts with cache-friendliness (Stack Overflow) \citep{craver2016stackoverflow}. Skilled teams can move individual cells -- LMAX and Monzo both did \citep{fowler2011lmax, sewell2024monzo}. A rating is a \emph{default hypothesis} to be replaced by measurement in step~(viii); the matrix predicts the default, not the exceptional.
|
||||
\item \textbf{Hybrids are the normal case, not the exception.} Eight of ten class recommendations involve a core pattern plus different edge patterns (Section~\ref{sec:hybrids}). The matrix is defined over \emph{subsystems}; applying it to a whole enterprise in one stroke is a category error the theory explicitly forbids.
|
||||
\item \textbf{The evidence base is heterogeneous.} The star ratings of \citet{richards2025fundamentals} are expert judgement, not measurements; DORA is survey-based prediction, not causal proof \citep{forsgren2018accelerate}; the case studies are self-reported engineering blogs with selection and framing bias -- Prime Video in particular is routinely misquoted as ``Amazon abandons microservices'' when it documents one service with a data-intensive streaming workload \citep{cockcroft2023prime}; and hexagonal and serverless carry no star ratings at all. The theory compensates by triangulation -- ratings against cases against metrics -- and by the measurement contract, which converts every adopted claim into a testable one.
|
||||
\item \textbf{The organisation is a hidden variable.} Conway's law makes every architecture decision a team-structure decision \citep{conway1968committees, skelton2019team}; the same requirements profile admits opposite optimal patterns at different organisation sizes (LMAX versus Monzo; Shopify versus Amazon). D11 partially captures this; no twelve-dimensional profile fully does (Section~\ref{sec:conway}).
|
||||
\item \textbf{AI-era volatility.} The D12 ratings encode the 2025/26 state of a field whose tools deprecate in months \citep{openai2026deprecations}. The \emph{method} -- Assumption~A6: scenarios, tactics, trade-off analysis, ADRs, fitness functions -- is the stable part; the specific cells are perishable and carry, in effect, their own temporal fitness function: re-verify on every model generation. Lehman's laws apply to theories too \citep{lehman1980laws}.
|
||||
\end{enumerate}
|
||||
|
||||
\begin{hinweisbox}
|
||||
A student who cites the matrix as an \emph{authority} rather than as a \emph{hypothesis} has misunderstood the module. The matrix cannot tell you what to build; it can only force your criteria, weights, and assumptions into the open, pre-filter the candidates, and hand the contested cells to scenario-based analysis. Its numbers are ordinal, its ratings are context-typical defaults, its evidence is triangulated but partly survey-based and partly self-reported -- and it decays: every cell is a claim awaiting your measurement. The canonical exercise in this scepticism is reading contradictory study designs against each other (the METR-versus-Copilot contradiction of Part~\ref{part:ai} \citep{becker2025metr, peng2023copilot}); the assessment of this module tests the discipline, not the memorisation of the grid.
|
||||
\end{hinweisbox}
|
||||
|
||||
\begin{keypoint}
|
||||
\textbf{Maxim 9.} The matrix is the argument's skeleton, ATAM is its court of appeal, the ADR is its record, and the fitness function is its parole condition. The matrix, in short, is the lecture-hall form of a discipline whose engineering form is: scenarios with numbers, ATAM for the contested cells, ADRs for the decisions, fitness functions for the lifetime.
|
||||
\end{keypoint}
|
||||
|
||||
\begin{thinkbox}
|
||||
Limit~4 says the evidence base is heterogeneous, and limit~2 says skilled teams can move cells. Suppose your team measures, over a year, that its microservices system beats every prediction of the MS column for its class. Has the theory been falsified, or has your measurement contract done exactly what step~(viii) designed it to do? What would have to be true of your \emph{next} project for the difference to matter?
|
||||
\end{thinkbox}
|
||||
736
skript/chapters/part5_ai_dimension.tex
Normal file
@ -0,0 +1,736 @@
|
||||
\part{The AI Dimension: Tool and Component}
|
||||
\label{part:ai}
|
||||
|
||||
% ============================================
|
||||
% SECTION: TWO AXES, ONE METHOD
|
||||
% ============================================
|
||||
\section{Two Axes, One Method}
|
||||
\label{sec:twoaxes}
|
||||
|
||||
\emph{Four parts built a complete decision theory without ever making artificial intelligence its subject -- does the construction survive the technology that defines its decade?} That is not a rhetorical flourish but a promissory note falling due. Part~\ref{part:foundations} established the load-bearing assumptions, the formal model, and the twelve profile dimensions (Table~\ref{tab:dimensions}); Part~\ref{part:patterns} derived the capability profiles of the seven patterns (Table~\ref{tab:capability}); Part~\ref{part:applications} derived the requirements profiles of the ten application classes (Table~\ref{tab:requirements}); Part~\ref{part:fit} combined them into the matching matrix (Table~\ref{tab:fitmatrix}), the decision procedure, and the measurement contract. This final part redeems the promissory note issued in Part~\ref{part:foundations} as Assumption~A6: \emph{AI components extend the quality attribute space but do not change the method.}
|
||||
|
||||
That assumption is the module's central intellectual bet, and stating it takes two sentences. Everything AI does to software engineering can be absorbed by the apparatus the reader now owns -- quality attribute scenarios with response measures, tactics, capability and requirements profiles, trade-off analysis, ADRs, fitness functions. If AI-bearing systems turned out to require a genuinely different method, the bet would be lost -- and this part is where that claim must survive contact with the evidence. It does so the way every part of this script has worked: \textbf{cases first, generalisation after}. Two contradictory randomised experiments open Axis~A (Section~\ref{sec:axisa}); one concrete LLM call, wired wrongly and then rightly, opens Axis~B (Section~\ref{sec:axisb}); the verdict the reader has already computed three times opens the matrix reading (Section~\ref{sec:matrixshift}); and the course project's own advisory workflow opens the final, emergent pattern (Section~\ref{sec:agentpattern}).
|
||||
|
||||
\begin{definitionbox}[The two axes of the AI dimension]
|
||||
The module analyses AI along two strictly separated axes:
|
||||
\begin{itemize}
|
||||
\item \textbf{Axis A -- AI as a tool in the SDLC (software development life cycle).} AI systems (code assistants, agentic coding tools, review bots) participate in \emph{building} the software: they generate code, tests, documentation, and draft design artefacts. The software that ships may contain no AI at all. The unit of analysis is the \emph{development process} and its economics.
|
||||
\item \textbf{Axis B -- AI as a runtime component.} AI systems (LLM services, trained ML models, optimisation solvers) are \emph{part of the delivered system} and execute in production. The unit of analysis is the \emph{running system} and its quality attributes.
|
||||
\end{itemize}
|
||||
The axes are independent: a team can build a classical payroll system with heavy agent support (A without B), or hand-craft an AI-native advisory platform (B without A). In practice, and in the course project, both apply simultaneously -- which is precisely why they must be kept conceptually apart.
|
||||
\end{definitionbox}
|
||||
|
||||
Figure~\ref{fig:twoaxes} summarises the two axes and their distinct attack points: the development process and the delivered system.
|
||||
|
||||
\begin{figure}[htbp]
|
||||
\centering
|
||||
\resizebox{0.95\textwidth}{!}{%
|
||||
\begin{tikzpicture}[
|
||||
node distance=0.9cm and 1.6cm,
|
||||
sysbox/.style={rectangle, draw, rounded corners=4pt, minimum width=3.4cm, minimum height=1.1cm, align=center, font=\small\sffamily, line width=0.8pt},
|
||||
tool/.style={sysbox, fill=violet!15, draw=aiviolet},
|
||||
comp/.style={sysbox, fill=violet!15, draw=aiviolet},
|
||||
core/.style={sysbox, fill=bankblue!20, draw=bankblue, font=\small\sffamily\bfseries},
|
||||
proc/.style={sysbox, fill=bankgreen!15, draw=bankgreen},
|
||||
arr/.style={-{Stealth[length=2.5mm]}, thick, gray!60!black}
|
||||
]
|
||||
\node[proc, minimum width=4.6cm] (sdlc) {Development process\\(specify, build, verify, operate)};
|
||||
\node[core, minimum width=4.6cm, right=2.6cm of sdlc] (system) {Delivered system\\(structure, quality attributes)};
|
||||
\node[tool, above=of sdlc] (axisa) {\textbf{Axis A}\\AI as tool: agents, assistants};
|
||||
\node[comp, above=of system] (axisb) {\textbf{Axis B}\\AI as component: LLM, ML, solver};
|
||||
\draw[arr] (axisa) -- node[right, font=\scriptsize\sffamily, align=left]{shifts SDLC\\economics} (sdlc);
|
||||
\draw[arr] (axisb) -- node[right, font=\scriptsize\sffamily, align=left]{stretches quality\\attribute space} (system);
|
||||
\draw[arr] (sdlc) -- node[above, font=\scriptsize\sffamily]{produces} (system);
|
||||
\end{tikzpicture}%
|
||||
}%
|
||||
\caption{The two axes of the AI dimension. Axis A changes how systems are built; Axis B changes what the built system contains. Both are absorbed by the same method: scenarios, tactics, profiles, ADRs, fitness functions.}
|
||||
\label{fig:twoaxes}
|
||||
\end{figure}
|
||||
|
||||
\begin{keypoint}
|
||||
Two axes, one method: Axis~A changes \emph{how} systems are built, Axis~B \emph{what} they contain. The axes are independent and must be kept apart -- and both are analysed with the apparatus of Parts~\ref{part:foundations}--\ref{part:fit}, nothing new.
|
||||
\end{keypoint}
|
||||
|
||||
% ============================================
|
||||
% SECTION: AXIS A -- AI AS TOOL
|
||||
% ============================================
|
||||
\section{Axis A: AI as a Tool Shifts the Economics of the SDLC}
|
||||
\label{sec:axisa}
|
||||
|
||||
\emph{AI makes developers 55.8\,\% faster -- or 19\,\% slower. Which study is wrong?} Both numbers come from randomised controlled trials (RCTs), and both are methodologically sound; few topics in software engineering carry a larger gap between headline and evidence. As everywhere in this script, the cases come first: read the two experiments as experiments, and let the contradiction pose the question the rest of the section answers.
|
||||
|
||||
\subsection{Case 1 -- the Copilot RCT: +55.8\,\% on a greenfield task}
|
||||
\label{subsec:case-copilot}
|
||||
|
||||
\emph{What exactly did the most-cited experiment measure?} In an experiment published in 2023, 95 professional developers were randomly split into two groups and given the same task: implement an HTTP server in JavaScript. One group worked with GitHub Copilot, the other without; the clock measured time to completion. The treatment group finished 55.8\,\% faster \citep{peng2023copilot}. Three qualifications matter for an honest reading. First, the confidence interval (21--89\,\%) is very wide: the headline number is a point estimate, not a natural constant. Second, the task was a bounded, well-defined \emph{greenfield} exercise -- no legacy context, no architectural constraints, no review process. Third, speed was measured, not quality; completion rates did not differ significantly. Within those bounds the result is real -- and it is the origin of the ``AI doubles productivity'' headline genre.
|
||||
|
||||
\subsection{Case 2 -- the METR RCT: 19\,\% slower in your own mature codebase}
|
||||
\label{subsec:case-metr}
|
||||
|
||||
\emph{What happens when the same technology meets experts on their own terrain?} The most important single study for a critical course is the METR randomised controlled trial \citep{becker2025metr}. Sixteen experienced open-source maintainers worked on 246 real issues in repositories they had maintained for years -- large, mature codebases (over a million lines) with high implicit quality standards. Each issue was randomly assigned to an AI-allowed condition (predominantly Cursor with frontier models of early 2025) or an AI-forbidden condition. With AI, the developers took 19\,\% \emph{longer}. The perception data are the didactic core: before the study, the same developers forecast a 24\,\% speed-up; after the study -- having been measurably slowed down -- they estimated that AI had accelerated them by 20\,\%. Even experts cannot validly introspect their own AI-assisted productivity. METR's own explanation maps the boundary conditions rather than refuting Case~1: the developers' deep familiarity with their repositories left little for AI-supplied context to add, the codebases were large and conventionally dense, and substantial time went into checking, repairing, and discarding AI proposals.
|
||||
|
||||
So which study is wrong? Neither -- and resolving the contradiction \emph{is} the lesson. The two experiments measured different populations (task novices versus domain experts in their own code), different codebases (greenfield versus mature), different tasks (bounded versus real issues) -- settings so far apart that the results never actually compete. This apparent contradiction is the single most instructive fact in the entire Axis-A literature, and resolving it requires reading \emph{study designs}, not abstracts: the full record first, then the moderator variables that reconcile it, then the structural conclusion underneath.
|
||||
|
||||
\subsection{The full empirical record}
|
||||
\label{subsec:evidence}
|
||||
|
||||
The two cases are the extreme corners of a larger record (Table~\ref{tab:aievidence}): seven strands of evidence, 2023--2025, from randomised experiments to organisational telemetry and longitudinal code analysis. Read every row as the cases were read -- setting first, finding second.
|
||||
|
||||
\begin{table}[!htb]
|
||||
\centering
|
||||
\caption{The empirical record on AI-assisted development, 2023--2025. The findings diverge because the studies measure different populations, tasks, and levels of analysis -- the reconciliation is given in Table~\ref{tab:moderators}.}
|
||||
\label{tab:aievidence}
|
||||
\small
|
||||
\begin{tabular}{@{}p{3.3cm}p{4.6cm}p{6.0cm}@{}}
|
||||
\toprule
|
||||
\textbf{Evidence} & \textbf{Setting} & \textbf{Finding} \\
|
||||
\midrule
|
||||
Copilot RCT \citep{peng2023copilot} & 95 professional developers; well-defined greenfield task (HTTP server in JavaScript) & \textbf{+55.8\,\%} task speed (95\,\% CI: 21--89\,\%); completion rate not significantly different \\
|
||||
\addlinespace
|
||||
Three field experiments \citep{cui2025effects} & 4{,}867 developers at Microsoft, Accenture, and a Fortune-100 firm & \textbf{+26.1\,\%} completed tasks (s.e.\ 10.3\,\%); less experienced developers gain most \\
|
||||
\addlinespace
|
||||
METR RCT \citep{becker2025metr} & 16 expert open-source maintainers; 246 real issues in their own mature repositories & \textbf{19\,\% slower} with AI -- while estimating afterwards that AI had made them 20\,\% faster \\
|
||||
\addlinespace
|
||||
DORA 2024 \citep{dora2024report} & $\sim$3{,}000 respondents; organisational delivery level & +25\,\% AI adoption associated with \textbf{$-$1.5\,\% throughput} and \textbf{$-$7.2\,\% delivery stability} \\
|
||||
\addlinespace
|
||||
DORA 2025 \citep{dora2025aireport} & $\sim$5{,}000 respondents & Throughput association now positive; \textbf{instability persists}; AI acts as an \emph{amplifier} of existing strengths and dysfunctions \\
|
||||
\addlinespace
|
||||
GitClear longitudinal \citep{harding2025gitclear} & 211 million changed code lines, 2020--2024 & \textbf{4$\times$} growth in code duplication; moved-code share (the refactoring signature) collapsed from $\sim$25\,\% to below 10\,\% \\
|
||||
\addlinespace
|
||||
Stack Overflow survey \citep{stackoverflow2025survey} & $>$49{,}000 developers & 84\,\% use or plan to use AI; \textbf{46\,\% actively distrust} its output; top frustration: ``almost right'' code \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\paragraph{Field experiments at scale.} The largest field study to date -- randomised experiments across Microsoft, Accenture, and a Fortune-100 firm with 4{,}867 developers -- found a 26.1\,\% increase in completed tasks, with the strongest gains among less experienced developers \citep{cui2025effects}. The pattern already visible in Case~1 recurs throughout the literature: juniors and task novices benefit most. A further methodological caution comes from GitHub's own telemetry-plus-survey study: the best predictor of \emph{perceived} productivity is the suggestion acceptance rate, not the persistence of accepted code in the repository \citep{ziegler2024measuring} -- much vendor-reported ``productivity'' evidence measures perception, not verified output. Case~2's perception gap is the controlled-trial demonstration of the same fact.
|
||||
|
||||
\paragraph{The system level: DORA 2024 and 2025.} The DORA research programme measures neither task times nor perceptions but delivery performance at the level of the organisation -- throughput and stability -- which is exactly the level at which architecture acts. The 2024 report ($\sim$3{,}000 respondents) found 75.9\,\% of respondents using AI for at least part of their work and roughly three quarters reporting productivity gains, yet estimated that a 25\,\% increase in AI adoption was associated with +7.5\,\% documentation quality, +3.4\,\% code quality, and +3.1\,\% review speed -- but $-$1.5\,\% delivery throughput and $-$7.2\,\% delivery stability \citep{dora2024report}. DORA's proposed mechanism is classical: AI makes it easy to produce more code per change, and larger batch sizes have been a documented risk driver for years \citep{forsgren2018accelerate}. The 2025 report ($\sim$5{,}000 respondents) shows adoption near saturation (90\,\%, with a median of about two hours of daily use), more than 80\,\% reporting productivity gains, and 30\,\% still expressing little or no trust in AI-generated code. The throughput association has turned positive as tools and practices matured -- but the negative association with delivery stability \emph{persists}. The report's central metaphor is that AI is an amplifier: it magnifies the strengths of well-run organisations and the dysfunctions of badly run ones \citep{dora2025aireport}. Individual acceleration and system-level performance are different quantities, and only the second one pays salaries.
|
||||
|
||||
\paragraph{Code structure in the longitudinal record.} The GitClear analysis of 211 million changed lines (2020--2024) documents the structural residue: the frequency of duplicated code blocks (five or more lines) reached four times its pre-AI level in 2024; the share of copy-pasted lines rose from 8.3\,\% (2021) to 12.3\,\% (2024); and the share of \emph{moved} lines -- the fingerprint of refactoring and modularisation -- fell from roughly 25\,\% to under 10\,\%, so that 2024 was the first year in which copy-paste exceeded code movement \citep{harding2025gitclear}. Churn -- code reworked or discarded within two weeks of commit -- rose from a pre-AI baseline of roughly 3--4\,\% to 5.7\,\% in 2024, with the follow-up report showing the trend continuing \citep{harding2026gitclear}. Two caveats are obligatory: GitClear is a commercial analytics vendor, and the analysis is correlational -- AI's causal share of the trend is plausible but not isolated. The findings nonetheless converge with DORA's stability data: more code, produced faster, structurally worse maintained. Reuse by abstraction is being displaced by reuse by duplication -- the exact opposite of what Parnas-style modularisation (Part~\ref{part:patterns}) works to achieve.
|
||||
|
||||
\paragraph{Practitioner trust.} The 2025 Stack Overflow survey ($>$49{,}000 developers) completes the picture with a striking pair: 84\,\% use or plan to use AI tools, yet 46\,\% actively distrust the accuracy of their output, and only 3\,\% report high trust. The most-cited frustration (45\,\%) is AI output that is ``almost right, but not quite''; 66\,\% report spending more time fixing almost-right code than they would have spent otherwise \citep{stackoverflow2025survey}. Adoption rises while trust falls -- consistent with METR and DORA: the effort has migrated from writing to verifying.
|
||||
|
||||
\subsection{Reconciling the divergence: moderator variables}
|
||||
\label{subsec:moderators}
|
||||
|
||||
The apparent contradictions dissolve once the studies are indexed by their moderator variables (Table~\ref{tab:moderators}). The same technology yields $+55.8\,\%$ and $-19\,\%$ because Case~1 (Section~\ref{subsec:case-copilot}) and Case~2 (Section~\ref{subsec:case-metr}) sit at opposite corners of a five-dimensional design space -- and every other row of Table~\ref{tab:aievidence} finds its place in the same coordinates.
|
||||
|
||||
\begin{table}[htbp]
|
||||
\centering
|
||||
\caption{Moderator variables reconciling the divergent evidence on AI-assisted development. Each row names one dimension along which the studies in Table~\ref{tab:aievidence} differ systematically.}
|
||||
\label{tab:moderators}
|
||||
\small
|
||||
\begin{tabular}{@{}p{2.6cm}p{5.4cm}p{5.8cm}@{}}
|
||||
\toprule
|
||||
\textbf{Moderator} & \textbf{Gains high} & \textbf{Gains low or negative} \\
|
||||
\midrule
|
||||
Experience & Juniors, task novices \citep{peng2023copilot, cui2025effects} & Domain experts in their own code \citep{becker2025metr} \\
|
||||
Codebase & Greenfield, small, standard stack & Mature, large, dense implicit conventions \\
|
||||
Task & Well-defined, bounded & Under-specified, cross-cutting \\
|
||||
Measurement & Task time, perceived productivity & Delivery stability, maintainability, churn \citep{dora2024report, harding2025gitclear} \\
|
||||
Organisation & Small batches, test automation, loose coupling & Large batches, weak guardrails, tight coupling \citep{dora2025aireport} \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\begin{thinkbox}
|
||||
The same class of technology produced $+55.8\,\%$ in one randomised experiment \citep{peng2023copilot} and $-19\,\%$ in another \citep{becker2025metr}. Walk through the five moderators in Table~\ref{tab:moderators}: on which rows do the two studies differ? Now consider the systems you are likely to work on two years after graduation -- greenfield exercises or mature codebases with implicit conventions? Which study's setting is closer to that reality, and what does the METR perception gap (forecast $+24\,\%$, measured $-19\,\%$, post-hoc estimate $+20\,\%$) imply about relying on your own felt productivity as evidence?
|
||||
\end{thinkbox}
|
||||
|
||||
\subsection{The verification bottleneck}
|
||||
\label{subsec:bottleneck}
|
||||
|
||||
The structural conclusion underneath the moderator table can be stated in one sentence: \textbf{code generation became cheap; specification, verification, and architecture became the binding constraints.} When the marginal cost of producing plausible code approaches zero, the scarce resource in the SDLC is no longer typing but everything that surrounds it: understanding the requirement precisely enough to specify it, reviewing and testing what was generated, and accepting responsibility for shipping it. The evidence strands converge on this reading: DORA finds individual acceleration coexisting with delivery instability where control systems are weak \citep{dora2024report, dora2025aireport}; two thirds of surveyed developers report spending more time on almost-right code \citep{stackoverflow2025survey}; a substantial share of METR's measured slow-down is time spent checking, repairing, and discarding AI proposals \citep{becker2025metr}; and industry analyses describe code review as the new bottleneck -- more and larger pull requests meeting unchanged human review capacity \citep{logrocket2025review}.
|
||||
|
||||
Economically put: AI lowers the cost of \emph{producing} code, not the cost of \emph{taking responsibility} for code. Three consequences bind Axis~A back into the fit theory, and each is measurable:
|
||||
|
||||
\begin{enumerate}
|
||||
\item \textbf{Architecture quality gates AI gains.} The core finding of DORA 2025 is that teams in loosely coupled architectures with fast feedback loops convert AI adoption into throughput, while tightly coupled systems with slow processes do not \citep{dora2025aireport} -- the AI-era echo of the classical result that loosely coupled architectures and teams are the strongest predictor of continuous delivery performance \citep{dora2017sodr, forsgren2018accelerate}. In the vocabulary of this theory: D7 (evolvability) and D9 (testability and deployability) gain weight in \emph{every} requirements profile, because architecture--application fit acquires a second reading -- fit to a \emph{mode of work} in which change volume rises by an order of magnitude.
|
||||
\item \textbf{Architecture documentation becomes a control interface.} ADRs, repository convention files, and machine-readable rules are no longer passive records; agents execute them on every run (Section~\ref{subsec:docsascontext}).
|
||||
\item \textbf{Fitness functions become the operating licence for agents.} An agent iterating against a dense test suite and CI-enforced architecture rules is contained; without them, every agent change is unpriced risk (Section~\ref{subsec:guardrails}).
|
||||
\end{enumerate}
|
||||
|
||||
\begin{keypoint}
|
||||
\textbf{Maxim 7.} Good architecture was always the art of making change cheap and safe; AI raises the change rate by an order of magnitude -- and therefore raises, not lowers, the value of architecture.
|
||||
\end{keypoint}
|
||||
|
||||
\subsection{Architecture documentation as context for agents}
|
||||
\label{subsec:docsascontext}
|
||||
|
||||
Agentic tools are context-driven: they produce architecture-conformant code only if the architecture is \emph{explicit, machine-readable, and in the repository}. This upgrades documentation artefacts that Part~\ref{part:foundations} introduced for human readers into a control interface for machine collaborators:
|
||||
|
||||
\begin{itemize}
|
||||
\item \textbf{Architecture Decision Records.} The ADR \citep{nygard2011documenting}, preferably in MADR form \citep{kopp2018markdown}, serves agents twice: as \emph{input context} (why is the system structured this way? which options were rejected, and why?) and as \emph{output format} (an agent drafts an ADR from a design discussion; a human decides and signs, per Assumption~A1).
|
||||
\item \textbf{Agent instruction files.} Project-local files such as \texttt{CLAUDE.md} \citep{anthropic2025claudecode} and the vendor-neutral \texttt{AGENTS.md} format -- published in 2025, adopted within months by over 60{,}000 open-source repositories and supported by practically all agents \citep{openai2025agentsmd, infoq2025agentsmd} -- carry the stack, conventions, build and test commands, module boundaries, and no-go zones. They are loaded at every session start: documentation that was once ``too expensive to maintain for human readers'' now amortises because it is \emph{executed} on every agent run.
|
||||
\item \textbf{Machine-checkable conventions.} Wherever a convention can be stated as a rule (dependency directions, naming, layering), it should be a failing test rather than a prose exhortation -- the fitness-function discipline of Part~\ref{part:fit} \citep{ford2022evolutionary, archunit2024userguide}.
|
||||
\end{itemize}
|
||||
|
||||
The corollary cuts both ways: documentation debt is now reproduced at machine speed. An outdated convention file or a stale ADR does not merely mislead the occasional new colleague; it is faithfully executed by every agent session, multiplying the error across the codebase. DORA 2025 confirms the mechanism organisationally -- ``AI-accessible internal knowledge'' and healthy data ecosystems rank among the seven capabilities that amplify AI benefits \citep{dora2025aireport}.
|
||||
|
||||
\begin{lstlisting}[language={}, caption={Excerpt from an agent instruction file (\texttt{AGENTS.md}) for the course project. Every line is a control statement that an agent executes on each run -- and that therefore must be kept as current as code.}, label={lst:agentsmd}]
|
||||
# Portfolio Intelligence Platform -- agent instructions
|
||||
|
||||
## Architecture (binding; see docs/adr/)
|
||||
- Modular monolith, module boundaries enforced by CI
|
||||
(see fitness_functions/boundaries_test.py). Do not add
|
||||
cross-module imports; use the module's public API.
|
||||
- All LLM access goes through gateway/ -- never call a
|
||||
provider SDK from domain code (ADR-011).
|
||||
|
||||
## Verification (run before proposing changes)
|
||||
- make test # unit + module-boundary rules
|
||||
- make evals # eval harness; required for any
|
||||
# change under prompts/ or gateway/
|
||||
|
||||
## No-go zones
|
||||
- ledger/ : append-only audit journal. Propose changes
|
||||
as an ADR draft instead of editing code.
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Guardrails as the precondition for safe agent use}
|
||||
\label{subsec:guardrails}
|
||||
|
||||
The inversion of the bottleneck dictates where engineering effort must go. If verification is the scarce resource, then everything that \emph{automates} verification multiplies the value of AI tooling -- and everything that leaves verification informal converts AI speed into instability:
|
||||
|
||||
\begin{itemize}
|
||||
\item \textbf{Test suites are the operating licence.} An agent working against a dense, fast test suite can iterate: wrong code fails immediately and is repaired or discarded at machine speed. Without that net, every agent-generated change ships unpriced risk. This is precisely the ``strong version control and test automation'' capability pair that DORA identifies as an AI amplifier \citep{dora2025aireport}.
|
||||
\item \textbf{Architectural fitness functions fence the structure.} A fitness function -- any mechanism providing an objective integrity assessment of an architectural characteristic \citep{ford2022evolutionary} -- is the machine-readable form of an architecture decision. Dependency rules, cycle checks, and module-boundary verification as CI gates \citep{archunit2024userguide, drotbohm2023modulith} were good practice before AI; with agents in the loop they become the mechanism by which an architect constrains a collaborator who never attends design meetings.
|
||||
\item \textbf{The delivery pipeline becomes a defence instrument.} Static analysis, SAST (static application security testing), dependency and secret scanning, contract tests, and progressive delivery move from hygiene to necessity: they are the only controls that scale with generation volume \citep{humble2010continuous, pearce2022asleep}.
|
||||
\end{itemize}
|
||||
|
||||
Note the continuity with Part~\ref{part:fit}: nothing in this list is new machinery. The measurement contract already demanded executable invariants under which the architecture may keep evolving; Axis~A merely adds a new class of change producer whose volume makes the contract non-optional.
|
||||
|
||||
\subsection{The agentic tool landscape 2025/2026 -- soberly}
|
||||
\label{subsec:landscape}
|
||||
|
||||
A lecture script should record the tool landscape the way a geologist records a riverbed: as evidence of forces, not as a map that will stay accurate. The tool generation of 2021--2023 (autocomplete-style assistants) suggested lines; the generation from 2024/2025 onwards \emph{plans, edits multiple files, runs builds and tests, and iterates on failures} -- agentic loops with tool access.
|
||||
|
||||
\begin{itemize}
|
||||
\item \textbf{Claude Code} (Anthropic): an agentic CLI tool -- research preview February 2025, general availability May 2025 -- operating in the terminal and IDE integrations, reading project context, executing commands, and producing commits; its repository-level configuration anchor is the \texttt{CLAUDE.md} file \citep{anthropic2025claudecode}.
|
||||
\item \textbf{Cursor} (Anysphere): an AI-first IDE with an agent mode; the dominant tool among the experienced developers in the METR study \citep{becker2025metr}.
|
||||
\item \textbf{GitHub Copilot}: the experimental Copilot Workspace was retired in May 2025; its concepts survived in the asynchronous \emph{Copilot coding agent} (issues to pull requests, running in CI infrastructure) and the synchronous agent mode in the IDE \citep{github2025codingagent}.
|
||||
\item \textbf{Devin} (Cognition): marketed in 2024 as the ``first AI software engineer''; its 13.86\,\% SWE-bench result in March 2024 helped trigger the agent wave \citep{cognition2024swebench}; in July 2025 Cognition acquired the IDE vendor Windsurf -- evidence of rapid market consolidation \citep{techcrunch2025windsurf}.
|
||||
\end{itemize}
|
||||
|
||||
Two open standards matter more than any product, because they are \emph{architectural} in nature. The \textbf{Model Context Protocol (MCP)}, introduced by Anthropic in November 2024, standardises how LLM applications connect to tools and data sources (JSON-RPC; servers expose tools, resources, and prompts); it was adopted by OpenAI, Google DeepMind, and Microsoft during 2025 and transferred in December 2025 to the Agentic AI Foundation under the Linux Foundation, with over 10{,}000 public MCP servers in existence \citep{anthropic2024mcp, anthropic2025aaif, linuxfoundation2025aaif}. \textbf{\texttt{AGENTS.md}} standardises project-level agent instructions \citep{openai2025agentsmd}. Vendor SDKs meanwhile extract the agent loop itself as a library, which is the bridge to Axis~B: the same building blocks that run SDLC agents also run runtime agent workflows (Section~\ref{sec:agentpattern}).
|
||||
|
||||
\begin{ailinse}[MCP is ports-and-adapters at ecosystem scale]
|
||||
Strip the branding and MCP is a familiar shape: a technology-neutral \emph{port} (the protocol) with swappable \emph{adapters} (servers wrapping databases, ticket systems, browsers), letting any conforming client use any conforming tool -- the role JDBC/ODBC played for databases. The hexagonal pattern of Part~\ref{part:patterns} did not become obsolete in the agent era; it became an ecosystem standard \citep{cockburn2024hexagonal, anthropic2024mcp}.
|
||||
\end{ailinse}
|
||||
|
||||
\paragraph{Benchmarks and their limits.} SWE-bench poses 2{,}294 real GitHub issues from twelve Python projects: given the repository and issue text, the system must produce a patch that passes hidden tests \citep{jimenez2024swebench}. The trajectory is steep: 1.96\,\% for the best 2023 setup, 13.86\,\% for Devin in March 2024 \citep{cognition2024swebench}, and -- on the human-validated 500-task \emph{SWE-bench Verified} subset \citep{openai2024swebenchverified} -- around 77--81\,\% for frontier models by late 2025 \citep{anthropic2025opus45}. Four qualifications keep the number honest: (1)~contamination risk -- the benchmark repositories are in the training data; (2)~scope -- Python only, and only issues that come with tests; (3)~criterion -- ``tests pass'' is not ``maintainable, architecture-conformant solution''; (4)~saturation -- on the harder, contamination-resistant SWE-bench Pro, frontier models initially scored around 23\,\% \citep{scaleai2025swebenchpro}. The juxtaposition of near-80\,\% benchmark scores with METR's measured slow-down of experts is the module's canonical exercise in benchmark literacy.
|
||||
|
||||
\begin{hinweisbox}
|
||||
This section encodes the state of early 2026, and its product names carry an expiry date measured in months (Copilot Workspace lived roughly a year). What is stable -- and examinable -- are the \emph{patterns}: the synchronous pair-agent versus the asynchronous task-agent as interaction modes, context files and ADRs as the control interface, and fitness functions as the containment mechanism. Treat every concrete tool claim in this section as carrying its own temporal fitness function: re-verify on every tool generation.
|
||||
\end{hinweisbox}
|
||||
|
||||
\subsection{Risks and responsibility}
|
||||
\label{subsec:risks}
|
||||
|
||||
\paragraph{Security of generated code.} The evidence predates the agent wave and has only gained relevance with volume. In a systematic study across 89 security-relevant scenarios, roughly 40\,\% of 1{,}689 Copilot-generated programs contained vulnerabilities from the CWE top-25 list -- models reproduce insecure patterns present in their training data \citep{pearce2022asleep}. A user study found that participants with an AI assistant wrote \emph{less} secure code on most tasks while believing their code to be \emph{more} secure than the control group's \citep{perry2023insecure}. A third, structurally new risk is package hallucination (``slopsquatting''): across roughly 576{,}000 analysed generations, about a fifth of recommended package references did not exist -- names an attacker can register pre-emptively \citep{spracklen2025package}. The architectural consequence is the same in all three cases: SAST, dependency and secret scanning, and licence checks in CI are not optional under AI use, and security review capacity must scale with generation volume.
|
||||
|
||||
\paragraph{Automation bias and skill formation.} Over-trust in automated systems is a decades-old human-factors finding; AI coding contexts reproduce its signature measurably -- Perry et al.'s participants overestimated their security, METR's experts overestimated their speed \citep{perry2023insecure, becker2025metr}. The formation of skill is equally at stake: a randomised study of engineers learning a new library found AI assistance reduced comprehension-test scores by roughly 17\,\%, with the usage pattern as the decisive moderator -- conceptual questions to the AI preserved learning, wholesale delegation of code production destroyed it \citep{infoq2026skillformation}. The labour-market signal points the same way: entry-level developer positions are measurably declining because AI absorbs exactly the tasks on which juniors traditionally learned \citep{stackoverflow2025genz}. For this module the implication is curricular and personal: the role being trained here is the \emph{specifier, verifier, and architect}; the typing role is disappearing, and the competence ladder towards the surviving roles must be rebuilt deliberately -- including deliberate AI-free practice of fundamentals.
|
||||
|
||||
\paragraph{Accountability.} Legally and professionally, the person who merges code answers for it, regardless of what generated it. AI tools are not liability-bearing entities; organisations therefore treat AI output correctly as the contribution of an unknown third party: mandatory review, provenance labelling, and an explicit policy for permitted uses -- DORA 2025 lists a clearly communicated AI policy first among the seven amplifier capabilities \citep{dora2025aireport}. For architecture the rule is sharp: AI may \emph{draft} an ADR; a nameable person decides, signs, and defends it \citep{nygard2011documenting}. Architecture is an accountability performance, not a text-production performance. Intellectual-property risk remains open but manageable: in the Copilot class action (\emph{Doe v.\ GitHub}), the DMCA claim was dismissed in 2024 -- outputs were held not to be sufficiently identical copies -- while licence-related claims continue \citep{register2024dmca, saveri2025doegithub}; the practical response is provider duplication filters and indemnification, licence scanning in CI, and a documented residual risk in the governance record.
|
||||
|
||||
\begin{projektbox}
|
||||
Axis A governs \emph{how} you build the Portfolio Intelligence Platform. The project applies every mechanism of this section: (i)~the repository carries an \texttt{AGENTS.md}/\texttt{CLAUDE.md} in the spirit of Listing~\ref{lst:agentsmd}, and you are expected to keep it as current as code; (ii)~every architecture decision is an ADR -- agents may draft, but a named team member signs; (iii)~agent-generated changes enter the main branch only through the CI gate: module-boundary fitness functions, the test suite, and (for anything touching prompts or the gateway) the eval harness of Section~\ref{subsec:evalharness}; (iv)~your project handbook contains a one-page AI policy: permitted tools, provenance labelling, and review rules. The graded artefact is not the generated code -- it is the control system around it.
|
||||
\end{projektbox}
|
||||
|
||||
% ============================================
|
||||
% SECTION: AXIS B -- AI AS RUNTIME COMPONENT
|
||||
% ============================================
|
||||
\section{Axis B: AI as a Runtime Component}
|
||||
\label{sec:axisb}
|
||||
|
||||
\emph{One of the platform's features is a single LLM call -- news in, sentiment out. Why not call it like any other function?} Axis B moves AI from the workshop into the product, and as always, the case precedes the taxonomy: walk one concrete call end to end, watch what breaks, and name every break with a dimension the reader already owns.
|
||||
|
||||
\subsection{Case: the news-sentiment call, wired the obvious way}
|
||||
\label{subsec:case-sentiment}
|
||||
|
||||
The Portfolio Intelligence Platform contains a deliberately small AI feature: when a user opens a portfolio, the platform fetches the latest news items for its positions and asks an LLM, per item, \emph{is this news positive, negative, or neutral for this holding -- and why?} One prompt, one structured answer: the simplest runtime AI component the course project owns. Wire it the obvious way -- a provider-SDK call inside the request handler, synchronously in the page-rendering path -- and five failures arrive on schedule, each landing on a dimension of Table~\ref{tab:dimensions}:
|
||||
|
||||
\begin{enumerate}
|
||||
\item \textbf{Latency (D3).} The call takes seconds -- one to sixty-plus, depending on model and load -- where every other call in the handler takes milliseconds: the page now blocks on the slowest and least controllable component in the stack.
|
||||
\item \textbf{Cost (D10).} The call is priced per token, so the feature bills per \emph{request}: every portfolio open costs real money, and a loop over twenty positions is a twenty-fold cost regression the way an $n{+}1$ query is a latency regression. No classical component in the platform has this property.
|
||||
\item \textbf{Non-determinism (D12).} Run the same article twice and the answers differ; sometimes an answer is garbage -- a score for a company not in the portfolio, a negative headline read as positive. Wired synchronously, the component has none of the three things Part~\ref{part:foundations} said such a component needs: no \emph{queue} to absorb its latency and outages, no \emph{port} behind which a test can substitute a deterministic fake, no \emph{measurement point} where the cost and quality of every call are observable.
|
||||
\item \textbf{Drift (D7).} The provider ships a new model version or deprecates the old one -- GA models carry deprecation windows of the order of six months \citep{openai2026deprecations} -- and the component's behaviour changes \emph{without any local action}: no commit, no deployment, no reviewable diff. The feature's behaviour is now co-owned by a third party.
|
||||
\item \textbf{Injection (D6).} The news article is untrusted input read by a component that cannot reliably separate instructions from data: a crafted ``article'' can carry instructions to the model \citep{owasp2025llmtop10}. The feature has quietly opened an attack surface that no classical threat model in the platform covers.
|
||||
\end{enumerate}
|
||||
|
||||
Nothing on this list is a bug in the model, and nothing on it is fixed by a better prompt. Every failure is a property of the \emph{wiring}: a non-deterministic, fallible, latency-heavy, per-call-priced component was integrated as if it were deterministic, reliable, fast, and free. The rest of the section generalises: the component taxonomy below; why containment, not mere integration (Section~\ref{subsec:se4ai}); the reference architecture that re-wires the call correctly (Section~\ref{subsec:integration}); the test instrument for a component without exact assertions (Section~\ref{subsec:evalharness}); the attack surface (Section~\ref{subsec:owasp}); the law (Section~\ref{subsec:aiact}).
|
||||
|
||||
\subsection{The three component types}
|
||||
|
||||
The sentiment call is one instance of a species. For the first time, production systems contain building blocks that are non-deterministic, fallible, latency-heavy, priced per call, and capable of changing behaviour without any local action -- through model updates, data drift, or provider deprecation \citep{sculley2015hidden, gama2014drift, openai2026deprecations}. The thesis of this section, prepared by Assumption~A6, is that such components change no principle of software engineering but shift the weights in the quality attribute space -- and thereby the pattern choice. Loose coupling, asynchronous integration, explicit contracts, and observability migrate from ``nice to have'' to mandatory. Modern industry usage speaks of \emph{compound AI systems} for exactly this reason: state-of-the-art results increasingly come from systems composed of models, retrievers, validators, and deterministic services rather than from a single model call \citep{zaharia2024compound}.
|
||||
|
||||
\begin{definitionbox}[AI runtime component]
|
||||
An \emph{AI runtime component} is a component of the delivered system whose output is produced by a learned or search-based model rather than by explicitly programmed logic. The module distinguishes three types with systematically different engineering profiles: \textbf{(a)}~LLM components for analysis, extraction, and generation over unstructured input; \textbf{(b)}~classical ML components for classification and regression; \textbf{(c)}~optimisation components (LP/MIP and constraint solvers, metaheuristics). The types differ exactly on the dimensions this theory measures -- determinism, latency, cost model, dominant risk, explainability -- and therefore demand different integration forms (Table~\ref{tab:aicomponents}).
|
||||
\end{definitionbox}
|
||||
|
||||
\begin{table}[htbp]
|
||||
\centering
|
||||
\caption{The three AI component types and their quality-attribute profiles. Each column implies a different integration form -- which is why ``add AI'' is never a single architectural decision.}
|
||||
\label{tab:aicomponents}
|
||||
\footnotesize
|
||||
\begin{tabular}{@{}p{2.5cm}p{3.9cm}p{3.6cm}p{3.9cm}@{}}
|
||||
\toprule
|
||||
\textbf{Dimension} & \textbf{(a) LLM analysis / generation} & \textbf{(b) ML classification / regression} & \textbf{(c) Optimisation (LP/MIP/CP)} \\
|
||||
\midrule
|
||||
Determinism & non-deterministic (even at $T=0$ only ``mostly'') & deterministic after training & reproducible at fixed seed/threads/limit; variance in practice \\
|
||||
Latency & seconds (1--60+) & milliseconds possible & seconds to hours; anytime behaviour \\
|
||||
Cost model & per token/call (operating expenditure) & training expensive, inference cheap & compute + solver licence \\
|
||||
Dominant risk & hallucination, prompt injection, provider drift/deprecation & data/concept drift, training/serving skew \citep{gama2014drift, breck2017mltest} & modelling errors, runtime explosion \\
|
||||
Explainability & low (generated justifications are themselves model output) & medium (feature importance) & \textbf{high -- provable}: optimality gap, duals, IIS \\
|
||||
Integration form & gateway + async + cache & serving endpoint + MLOps pipeline \citep{google2023mlops, kreuzberger2023mlops} & job queue / batch worker \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\paragraph{Type (a): LLM components.} LLM components turn unstructured input -- documents, e-mails, reports -- into analyses, extractions, or generated text. Three engineering building blocks define the type. First, \textbf{retrieval-augmented generation (RAG)} \citep{lewis2020rag}: knowledge is moved out of the model weights into a swappable, versionable, inspectable data component -- updated by re-indexing rather than retraining, with provenance through citable sources \citep{gao2023survey}. That RAG is an engineering problem rather than a model problem is documented by the case-study evidence of seven recurring failure points (missing content, failed ranking of the relevant documents, extraction and formatting errors, incomplete answers), with the sobering observation that RAG robustness \emph{evolves} in operation rather than being designed in \citep{barnett2024seven}. Second, \textbf{prompts are configuration artefacts}: version-controlled, regression-tested, behaviour-determining like code -- exactly the configuration-debt territory mapped by \citet{sculley2015hidden}. Third, \textbf{structured outputs} turn the LLM from a free-text oracle into a component with a typed interface: since 2024, provider APIs can enforce, via constrained decoding, that outputs conform to a developer-supplied JSON schema \citep{openai2024structured}. Syntactic correctness is thereby guaranteed; \emph{semantic} correctness remains to be verified (Sections~\ref{subsec:integration} and~\ref{subsec:evalharness}). The type's lifecycle risk is the provider: GA models carry deprecation windows of the order of six months, and shorter windows have been observed \citep{openai2026deprecations} -- a hard-coded model name is a ticking dependency, which is an architectural statement, not an operational one.
|
||||
|
||||
\paragraph{Type (b): classical ML components.} Self-trained models (scoring, churn, fraud, forecasting) bring the full nine-stage workflow -- from model requirements and data collection through training, evaluation, deployment, and monitoring, with dense feedback loops \citep{amershi2019software}. The characteristic engineering problems are \emph{training/serving skew} (divergent data preparation between training and serving, one of the most frequent production failure sources \citep{breck2017mltest, google2023mlops}), and \emph{data and concept drift}: the relationship between inputs and target changes under the deployed model, in sudden, gradual, incremental, or recurring form \citep{gama2014drift}. The consequence deserves its own sentence: \textbf{a deployed model is a perishable good} -- monitoring and retraining are operating requirements, not options. The tooling answers are feature stores with consistent online/offline views \citep{hermann2017michelangelo}, model registries versioning model, data, code, and configuration together, and the MLOps discipline consolidated by \citet{kreuzberger2023mlops}; the maturity ladder is treated in Section~\ref{subsec:mlops}. For a full systems treatment see \citet{huyen2022designing}.
|
||||
|
||||
\paragraph{Type (c): optimisation components.} The third type is routinely overlooked in the SE4AI literature but belongs in every advisory platform: mathematical optimisation with LP/MIP solvers \citep{gurobi2024manual} and constraint programming \citep{perron2024ortools} -- CP-SAT has dominated recent MiniZinc Challenge results, including a complete gold-medal sweep in 2024 \citep{krupke2024cpsat} -- plus stochastic metaheuristics. The engineering profile inverts the LLM's: solvers are \emph{deterministic but heavy}. Exact solvers reproduce results at fixed seed, thread count, and time limit, though parallelism and time limits produce run-to-run performance variability in practice; runtimes range from seconds to hours, often with anytime behaviour (longer runs, better solutions). That forces asynchronous integration -- job queue, status polling, callback; never a synchronous call in a web request path. Their compensating strength is \emph{provable} explainability: an optimality gap, dual values and shadow prices, and -- on infeasibility -- an irreducible infeasible subset (IIS), i.e.\ a minimal set of contradictory constraints as an explanation. In regulated domains this is a load-bearing argument for the division of labour the course project enforces: hard, auditable decisions belong to the solver and the deterministic services, not to the LLM.
|
||||
|
||||
\begin{keypoint}
|
||||
The three component types differ exactly where the twelve dimensions of Table~\ref{tab:dimensions} measure: determinism (D4), latency (D3), cost (D10), auditability (D6), testability (D9). ``We are adding AI'' is therefore never one decision -- it is a per-component matching problem, answered with the same profile logic as everything else in this module. One rule spans all three types: \emph{contain the component behind an explicit boundary; never scatter it through the domain}.
|
||||
\end{keypoint}
|
||||
|
||||
\subsection{Why containment: the SE4AI classics}
|
||||
\label{subsec:se4ai}
|
||||
|
||||
Two foundational results explain why AI components need architectural containment rather than mere integration.
|
||||
|
||||
\citet{sculley2015hidden} transferred the technical-debt metaphor to ML systems and made two structural observations. First, \emph{only a small fraction of a real-world ML system is ML code}: the famous figure shows the model as a small black box amid large blocks of configuration, data collection, feature extraction, data verification, serving infrastructure, and monitoring. The system around the model is the actual engineering task -- precisely this module's perspective. Second, ML components resist modularisation:
|
||||
|
||||
\begin{definitionbox}[CACE -- Changing Anything Changes Everything]
|
||||
ML models entangle their input signals: no feature is ever truly independent, so a change to one feature distribution, hyperparameter, or upstream data source changes the behaviour of the whole model. \citet{sculley2015hidden} call this the CACE principle. Its architectural consequence is \emph{boundary erosion}: the strong abstraction boundaries on which modular design relies are systematically undermined by ML components -- alongside the paper's system anti-patterns of glue code, pipeline jungles, dead experimental code paths, configuration debt, hidden feedback loops, and undeclared consumers of model outputs.
|
||||
\end{definitionbox}
|
||||
|
||||
\citet{amershi2019software}, from a broad study of Microsoft product teams, identified three fundamental differences between ML-based and classical development: (1)~data discovery, versioning, labelling, and schema management are harder than -- and qualitatively different from -- code management, with no Git-equivalent of comparable maturity; (2)~model customisation and reuse demand combined SE and ML competence rather than classical software reuse skills; (3)~\emph{AI components are harder to modularise than software modules} -- models are entangled (CACE), error behaviour is non-monotonic, and models interact in poorly predictable ways. The operational counterpart is the ML Test Score: a rubric of 28 concrete tests and monitoring requirements across data, model development, infrastructure, and monitoring, distilled from Google production experience \citep{breck2017mltest} -- production readiness made measurable, and a ready-made checklist for the course project.
|
||||
|
||||
\begin{ailinse}[Parnas meets CACE]
|
||||
Part~\ref{part:patterns} established Maxim 4: domain-oriented partitioning around anticipated change is the strongest single predictor of evolvability \citep{parnas1972criteria}. CACE identifies a component class in which change anticipation fails \emph{inside} the component -- everything co-varies with everything. The resolution is not to abandon Parnas but to apply him one level up: if the component cannot be decomposed, the decomposition happens \emph{around} it. The module boundary goes where the entanglement stops -- at the component's contract. That is the entire intellectual content of the gateway pattern in Figure~\ref{fig:llmgateway}, and it is sixty-year-old advice \citep{sculley2015hidden, amershi2019software}.
|
||||
\end{ailinse}
|
||||
|
||||
\subsection{Integration patterns: a reference architecture}
|
||||
\label{subsec:integration}
|
||||
|
||||
The architectural response to Sections~\ref{sec:axisb}--\ref{subsec:se4ai} is not new machinery but old machinery applied more strictly. Figure~\ref{fig:llmgateway} assembles the tactics into a reference architecture, and it is also the correct re-wiring of the news-sentiment call of Section~\ref{subsec:case-sentiment}: the call moves behind a typed port into the gateway (curing drift and containing injection), its non-interactive volume moves onto the queue (curing latency and buying batch pricing), and every call crosses one measurement point (making cost and quality observable). The paragraphs below justify each element.
|
||||
|
||||
\begin{figure}[htbp]
|
||||
\centering
|
||||
\resizebox{\textwidth}{!}{%
|
||||
\begin{tikzpicture}[
|
||||
node distance=0.5cm and 1.2cm,
|
||||
sysbox/.style={rectangle, draw, rounded corners=4pt, minimum width=3.0cm, minimum height=1.0cm, align=center, font=\small\sffamily, line width=0.8pt},
|
||||
core/.style={sysbox, fill=bankblue!20, draw=bankblue, font=\small\sffamily\bfseries, minimum height=2.6cm},
|
||||
gwpart/.style={sysbox, fill=violet!15, draw=aiviolet, minimum width=3.6cm, minimum height=0.75cm, font=\scriptsize\sffamily},
|
||||
comp/.style={sysbox, fill=bankgreen!15, draw=bankgreen},
|
||||
extern/.style={sysbox, fill=gray!15, draw=gray!60!black},
|
||||
guard/.style={sysbox, fill=bankred!10, draw=bankred},
|
||||
evalb/.style={sysbox, fill=teal!10, draw=projteal},
|
||||
arr/.style={-{Stealth[length=2.5mm]}, thick, gray!60!black},
|
||||
darr/.style={{Stealth[length=2.5mm]}-{Stealth[length=2.5mm]}, thick, gray!60!black}
|
||||
]
|
||||
% Domain core (left)
|
||||
\node[core] (core) {Deterministic\\domain core\\[2pt]{\scriptsize\mdseries decides and books;}\\{\scriptsize\mdseries no provider SDK imports}};
|
||||
|
||||
% Gateway internals (center)
|
||||
\node[gwpart, right=2.6cm of core.north east, anchor=north west, yshift=0.9cm] (assemble) {prompt assembly + schema validation};
|
||||
\node[gwpart, below=0.18cm of assemble] (router) {model router (cheap $\rightarrow$ expensive cascade)};
|
||||
\node[gwpart, below=0.18cm of router] (cache) {semantic cache};
|
||||
\node[gwpart, below=0.18cm of cache] (breaker) {timeouts, circuit breakers, fallback chains};
|
||||
\node[gwpart, below=0.18cm of breaker] (cost) {cost telemetry per request / feature / tenant};
|
||||
|
||||
% Gateway frame
|
||||
\begin{scope}[on background layer]
|
||||
\node[draw=aiviolet, line width=1pt, rounded corners=5pt, fill=violet!5,
|
||||
fit=(assemble)(router)(cache)(breaker)(cost),
|
||||
inner sep=8pt, label={[font=\small\sffamily\bfseries, aiviolet]above:{LLM gateway (anti-corruption layer)}}] (gw) {};
|
||||
\end{scope}
|
||||
|
||||
% Providers (right)
|
||||
\node[extern, right=1.4cm of router.east, anchor=west, yshift=0.7cm] (prov1) {Provider A\\{\scriptsize models $m_1, m_2$}};
|
||||
\node[extern, below=0.5cm of prov1] (prov2) {Provider B\\{\scriptsize fallback}};
|
||||
\node[extern, below=0.5cm of prov2] (local) {Local model\\{\scriptsize last-resort degradation}};
|
||||
|
||||
% Async queue (bottom left)
|
||||
\node[comp, below=1.6cm of core, minimum width=3.6cm] (queue) {Async job queue\\{\scriptsize batching, backpressure, retries}};
|
||||
\node[comp, right=1.2cm of queue] (workers) {Worker pool\\{\scriptsize bounded concurrency}};
|
||||
|
||||
% Ontology guard (bottom center)
|
||||
\node[guard, below=1.15cm of gw.south, minimum width=5.2cm] (guard) {Ontology / schema guard\\{\scriptsize entity resolution, domain axioms, citation check}};
|
||||
|
||||
% Eval harness (bottom)
|
||||
\node[evalb, right=1.0cm of guard, minimum width=3.4cm] (eval) {Eval harness\\{\scriptsize CI gate: prompts, models, providers}};
|
||||
|
||||
% Arrows
|
||||
\draw[arr] ([yshift=14pt]core.east) -- node[above, font=\scriptsize\sffamily]{typed port} ([yshift=14pt]core.east -| gw.west);
|
||||
\draw[arr] (gw.east) ++(0,0.7) -- (prov1.west);
|
||||
\draw[arr] (gw.east) -- (prov2.west);
|
||||
\draw[arr] (gw.east) ++(0,-0.7) -- (local.west);
|
||||
\draw[arr] (core.south) -- node[left, font=\scriptsize\sffamily]{non-interactive jobs} (queue.north);
|
||||
\draw[arr] (queue.east) -- (workers.west);
|
||||
\draw[arr] (workers.east) -| node[right, font=\scriptsize\sffamily, pos=0.75]{} (gw.south west);
|
||||
\draw[arr] (gw.south) -- node[right, font=\scriptsize\sffamily]{every output} (guard.north);
|
||||
\draw[arr] (guard.west) -| node[left, font=\scriptsize\sffamily, pos=0.8, align=right]{validated result\\or rejection} (core.south east);
|
||||
\draw[arr, dashed] (eval.west) -- (guard.east);
|
||||
\draw[arr, dashed] (eval.north) -- (gw.south east);
|
||||
\end{tikzpicture}%
|
||||
}
|
||||
\caption{Reference architecture for LLM integration: a deterministic domain core reaches the model only through a typed port into an LLM gateway (anti-corruption layer) that owns routing, caching, stability patterns, and cost telemetry; non-interactive work flows through an asynchronous queue; every output passes the ontology/schema guard; the eval harness gates changes to prompts, models, and providers in CI \citep{evans2003ddd, nygard2018release, flotorch2026gateway}.}
|
||||
\label{fig:llmgateway}
|
||||
\end{figure}
|
||||
|
||||
\begin{itemize}
|
||||
\item \textbf{Anti-corruption layer / LLM gateway.} The anti-corruption layer originates in domain-driven design as a translation layer that prevents a foreign system's model from corrupting one's own \citep{evans2003ddd}. Applied to LLMs: \emph{no domain code speaks to a provider API}. A facade owns the provider SDKs, prompt construction, schema validation, retry logic, model selection, and cost telemetry; the domain sees only a typed interface (\texttt{analyse\_report(document) -> RiskAssessment}). Provider deprecation \citep{openai2026deprecations} thereby becomes an adapter task instead of a crisis, and the facade is mockable in every test. As an industry pattern the gateway has consolidated into its own infrastructure layer -- the AI counterpart of the API gateway \citep{flotorch2026gateway}. In hexagonal terms the LLM is simply an adapter on a port \citep{cockburn2024hexagonal} -- the structural fact behind the $++$ in the D12 row of Table~\ref{tab:cap-hx}, and the strongest single reason the HX pattern gains weight in the AI era.
|
||||
\item \textbf{Deterministic core, probabilistic edge.} Everything deterministically computable -- validation, aggregation, key-figure computation, authorisation, persistence, booking -- stays deterministic code; the LLM handles only what determinism cannot (language understanding, extraction from unstructured text, formulation). The design rule the course project enforces: \emph{LLM agents propose; deterministic services decide and book.} Keep the non-deterministic core as small as possible and push it to the edge.
|
||||
\item \textbf{Asynchronous integration.} Seconds-scale latency, rate limits, and outage risk put AI calls behind a queue wherever the domain allows: the caller enqueues a job, a worker pool calls the model at a controlled degree of parallelism, results return by event or callback. The queue buys backpressure instead of overload, retries without blocking users, smoothing of rate limits -- and natural batching points: provider batch APIs process non-urgent volume loads at roughly 50\,\% discount within processing windows up to 24 hours \citep{openai2024batch}. This is Axis B's direct coupling to the EDA and PF patterns of Part~\ref{part:patterns} -- exactly the mechanisms the D12 rows of Tables~\ref{tab:cap-eda} and~\ref{tab:cap-pf} priced at $++$.
|
||||
\item \textbf{Semantic caching.} Instead of exact-match keys, requests are compared by embedding similarity, so semantically equivalent queries hit the cache \citep{bang2023gptcache}. The engineering point students must not miss: a false-positive cache hit is a \emph{correctness} risk, not a performance blemish -- the similarity threshold is a quality/cost regulator and belongs in the eval harness, not in a config file nobody reviews.
|
||||
\item \textbf{Model routing.} Model choice per request is one of the largest cost levers in the stack: cascades that start with the cheapest model and escalate only on insufficient answer quality report up to 98\,\% cost reduction at comparable quality \citep{chen2023frugalgpt}; learned routers trained on human preference data cut cost by more than a factor of two without quality loss, generalising to unseen model pairs \citep{ong2025routellm}.
|
||||
\item \textbf{Stability patterns.} The catalogue transfers directly from \citet{nygard2018release}: timeouts (an LLM call without one blocks a thread for minutes), retries with exponential backoff -- but only for idempotent calls and with cost awareness, since every retry burns tokens -- circuit breakers per provider and model, fallback chains (alternative model $\rightarrow$ alternative provider $\rightarrow$ cached or rule-based answer $\rightarrow$ honest degradation: ``analysis currently unavailable''), and bulkheads separating interactive from batch quotas. Only the failure semantics are new: a \emph{semantically unusable} answer -- schema violation, suspected hallucination -- must trigger the error path exactly like an HTTP~500.
|
||||
\item \textbf{Ontology and schema as contract.} The most effective systematic hallucination defence is layered: (1)~structured outputs enforce syntax \citep{openai2024structured}; (2)~every extracted entity (account number, ISIN, customer name, key figure) is resolved against the deterministic data store, and unresolvable references are \emph{rejected}, not passed on; (3)~domain axioms hold as invariants -- sums add up, weights lie in $[0,1]$, cited passages exist in the source document; (4)~grounding via RAG makes citations mandatory \citep{lewis2020rag, barnett2024seven}. The schema becomes a contract in the design-by-contract sense, and the gateway is the contract checker.
|
||||
\end{itemize}
|
||||
|
||||
\begin{ailinse}[Model routing is a classical tactic in new clothes]
|
||||
Part~\ref{part:foundations} defined tactics as the atomic units of architectural design \citep{bass2021software}. Routing traffic across a cheap and an expensive resource depending on demand is the ancient resource-arbitration tactic -- the FrugalGPT cascade \citep{chen2023frugalgpt} is its token-economics incarnation. Note where it lives in Figure~\ref{fig:llmgateway}: in the gateway, as infrastructure, invisible to domain logic. A tactic that leaks into the domain layer stops being a tactic and starts being coupling.
|
||||
\end{ailinse}
|
||||
|
||||
\subsection{The eval harness as an engineering artefact}
|
||||
\label{subsec:evalharness}
|
||||
|
||||
Non-determinism breaks the classical test idiom: \texttt{assert expected == actual} presupposes that equal inputs produce equal outputs. When that assumption falls, correctness must be redefined \emph{statistically} -- ``correct in at least 95\,\% of the evaluation cases'' -- and the team needs a test artefact of the first rank to carry that definition.
|
||||
|
||||
\begin{definitionbox}[Eval harness]
|
||||
An \emph{eval harness} is a versioned suite of test cases, scoring logic, and statistical thresholds for a non-deterministic component, executed in the CI/CD pipeline like a test suite. It gates every prompt change, model update, and provider migration. Its thresholds are the response measures of the AI-related quality attribute scenarios (Assumption~A4), and its pass rate is a fitness function in the measurement contract of Part~\ref{part:fit}.
|
||||
\end{definitionbox}
|
||||
|
||||
Four complementary evaluation strategies make up a complete harness:
|
||||
|
||||
\begin{enumerate}
|
||||
\item \textbf{Regression against labelled references.} A curated golden set of input/expectation pairs from the domain, scored with task-appropriate metrics (exact match or F1 on extracted fields, rubric scores for generated text). Every prompt change, model update, and migration runs against this suite -- the direct counterpart of the regression test.
|
||||
\item \textbf{LLM-as-judge.} Strong LLM judges agree with human preference judgements in over 80\,\% of cases -- the level of human--human agreement -- which makes them a scalable scoring instrument \citep{zheng2023judging}. The same study documents the systematic biases every user must control for: \emph{position bias} (candidate order sways the verdict), \emph{verbosity bias} (longer answers preferred), \emph{self-enhancement bias} (judges favour their own outputs), and weak mathematical/reasoning grading -- with countermeasures including position swapping and reference-guided judging. The engineering conclusion: the judge is a measurement instrument that must itself be calibrated against human labels. \emph{The judge needs its own eval.}
|
||||
\item \textbf{Domain axioms and property-based testing.} Instead of exact expected values, the harness checks \emph{properties} that must hold for all valid outputs -- the transfer of property-based testing \citep{claessen2000quickcheck} to non-deterministic components: schema validity, referential integrity against the ontology, metamorphic relations (a paraphrased input must yield a semantically equivalent output), and domain monotonicities. Axioms catch failure classes that no finite golden set covers.
|
||||
\item \textbf{Online evaluation.} Sampled human review, user feedback signals, and drift monitoring of the eval metrics in production -- the LLM counterpart of model monitoring in the ML workflow \citep{amershi2019software, breck2017mltest}.
|
||||
\end{enumerate}
|
||||
|
||||
\begin{keypoint}
|
||||
\textbf{The course thesis on testing AI.} The eval harness is to AI components what the test pyramid is to deterministic code: the artefact that converts ``it seems to work'' into a falsifiable, continuously executed claim. Without it, every model migration is a blind flight -- and given provider deprecation windows of months \citep{openai2026deprecations}, migrations are not hypothetical. Statistical acceptance replaces exact assertion; the thresholds are architecture decisions and belong in the measurement contract.
|
||||
\end{keypoint}
|
||||
|
||||
\begin{examplebox}[An eval harness for the portfolio platform]
|
||||
Listing~\ref{lst:evalharness} sketches the core of the course project's eval harness: a golden-set regression with a statistical threshold, domain-axiom checks against the ontology, and the calibration test for the LLM judge itself. Note what is \emph{absent}: no assertion demands an exact output string. The three thresholds (mean F1 $\geq 0.92$, zero axiom violations, judge--human agreement $\kappa \geq 0.7$, where $\kappa$ is Cohen's chance-corrected agreement measure) are the response measures; changing any of them is an architecture decision that requires an ADR, because it redefines what the platform accepts as ``correct''.
|
||||
|
||||
\begin{lstlisting}[caption={Core of the portfolio platform's eval harness (simplified). It runs in CI on every change to prompts, models, or the gateway, alongside the deterministic test suite.}, label={lst:evalharness}]
|
||||
GOLDEN = load_cases("evals/portfolio_extraction_v3.jsonl")
|
||||
|
||||
def test_extraction_regression(gateway):
|
||||
"""Statistical acceptance, not exact assertion."""
|
||||
scores = [f1(gateway.extract(c.report), c.expected)
|
||||
for c in GOLDEN]
|
||||
assert mean(scores) >= 0.92 # statistical threshold
|
||||
|
||||
def test_domain_axioms(gateway, ontology):
|
||||
"""Properties that hold for ALL valid outputs."""
|
||||
answer = gateway.advise(sample_portfolio())
|
||||
for pos in answer.positions:
|
||||
# every entity resolves against the deterministic store
|
||||
assert ontology.resolves(pos.isin), f"unknown: {pos.isin}"
|
||||
# domain axiom: portfolio weights sum to one
|
||||
total = sum(p.weight for p in answer.positions)
|
||||
assert abs(total - 1.0) < 1e-6
|
||||
for cit in answer.citations:
|
||||
# cited passages must exist in the source document
|
||||
assert cit.passage in source_text(cit.doc_id)
|
||||
|
||||
def test_judge_is_calibrated(judge, human_labels):
|
||||
"""LLM-as-judge is an instrument: calibrate it."""
|
||||
agreement = cohens_kappa(judge.score(GOLDEN), human_labels)
|
||||
assert agreement >= 0.70 # the judge's own eval
|
||||
\end{lstlisting}
|
||||
\end{examplebox}
|
||||
|
||||
\subsection{A new threat class: OWASP LLM Top 10 and prompt injection}
|
||||
\label{subsec:owasp}
|
||||
|
||||
AI components add an attack surface that classical threat models do not cover. The OWASP Top 10 for LLM Applications codifies it \citep{owasp2025llmtop10}; Table~\ref{tab:owasp} pairs each risk with the architectural counter-measure -- deliberately, because the defence is structural, not model-internal.
|
||||
|
||||
\begin{table}[htbp]
|
||||
\centering
|
||||
\caption{OWASP Top 10 for LLM Applications 2025 \citep{owasp2025llmtop10} with the architectural counter-measure for each risk. Most counter-measures are elements of Figure~\ref{fig:llmgateway}.}
|
||||
\label{tab:owasp}
|
||||
\footnotesize
|
||||
\begin{tabular}{@{}p{1.2cm}p{5.1cm}p{7.3cm}@{}}
|
||||
\toprule
|
||||
\textbf{ID} & \textbf{Risk} & \textbf{Architectural counter-measure} \\
|
||||
\midrule
|
||||
LLM01 & Prompt injection (direct and indirect) & Defence in depth: privilege separation, output validation, human-in-the-loop for sensitive actions \\
|
||||
LLM02 & Sensitive information disclosure & Data minimisation in prompts; output filtering at the gateway \\
|
||||
LLM03 & Supply chain & Vetting of models, weights, and dependencies; registry discipline \\
|
||||
LLM04 & Data and model poisoning & Data governance and provenance for training/index data \\
|
||||
LLM05 & Improper output handling & Treat output as untrusted input: schema validation, encoding, ontology guard \\
|
||||
LLM06 & Excessive agency & Least-privilege tool design; deterministic services own irreversible actions \\
|
||||
LLM07 & System prompt leakage & No secrets or authorisation logic in prompts \\
|
||||
LLM08 & Vector and embedding weaknesses & Access control and tenant isolation on the retrieval index \\
|
||||
LLM09 & Misinformation & Grounding with mandatory citations; domain-axiom checks \\
|
||||
LLM10 & Unbounded consumption & Rate limits, token budgets, cost circuit breakers per tenant \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\begin{hinweisbox}
|
||||
Prompt injection is not fully solvable inside the model, because LLMs process instructions and data in the \emph{same channel}: any document, e-mail, or web page the system reads can carry instructions (``ignore your previous rules and \dots''), and no reliable in-model separator exists. The defence is therefore defence in depth at the \emph{system} level: least-privilege tools (LLM06), output validation (LLM05), human approval for consequential actions, and consumption limits (LLM10) \citep{owasp2025llmtop10}. This is the security-flavoured restatement of the section's design rule: the architecture, not the model, is the trust boundary. For the course project it means concretely that no LLM output may reach the booking path without passing the ontology guard, and no agent tool may perform an irreversible action.
|
||||
\end{hinweisbox}
|
||||
|
||||
\subsection{Regulation as a hard constraint: the EU AI Act}
|
||||
\label{subsec:aiact}
|
||||
|
||||
Regulation closes the quality-attribute loop with legal force. Regulation (EU) 2024/1689 -- the AI Act -- entered into force on 1~August 2024 and takes a risk-based approach with four classes: \emph{unacceptable risk} (prohibited practices, e.g.\ social scoring), \emph{high risk} (Annex~III use cases including creditworthiness assessment, employment, and critical infrastructure -- with obligations on risk management, data governance, technical documentation, logging, human oversight, and accuracy/robustness/cybersecurity), \emph{limited risk} (transparency duties such as labelling AI interaction and generated content), and \emph{minimal risk} \citep{eu2024aiact}. The obligations phase in on a fixed timetable: prohibitions and AI-literacy duties from 2~February 2025, governance rules and duties for general-purpose AI models from 2~August 2025, general applicability including the Annex~III high-risk requirements from 2~August 2026, and high-risk AI embedded in regulated products from 2~August 2027.
|
||||
|
||||
For this theory the AI Act has a precise, limited role: its obligations are \textbf{quality attributes with legal force}, and they enter the requirements profile as hard constraints K(a), not as weights (Part~\ref{part:foundations}: constraints are knock-out filters, never averaged away). A finance-related advisory platform -- application class C10, particularly with any creditworthiness bearing -- can fall into the high-risk class, at which point logging of agent steps, technical documentation, human oversight, and demonstrated robustness stop being engineering preferences and become conditions of legal operation \citep{eu2024aiact}. Architecturally each obligation lands on an element already in Figure~\ref{fig:llmgateway}: logging duties land on the gateway's telemetry and the audit journal; human-oversight duties land on the human-in-the-loop interfaces of the determinism boundary; robustness duties land on the fallback chains and the eval harness. Compliance, correctly designed, is not a parallel work stream -- it is the same architecture, documented.
|
||||
|
||||
% ============================================
|
||||
% SECTION: HOW AI SHIFTS THE MATRIX
|
||||
% ============================================
|
||||
\section{How AI Shifts the Matrix}
|
||||
\label{sec:matrixshift}
|
||||
|
||||
\emph{You have computed the C10 verdict three times -- what were those computations doing to the rest of the matrix?} The verdict itself needs no fourth derivation. Part~\ref{part:foundations} ran it first, small: the mini-match of L, MM, and MS against C10's five High weights (Table~\ref{tab:minimatch}). Part~\ref{part:applications} derived the profile behind those weights and what real systems chose (Table~\ref{tab:req-c10}, Section~\ref{sec:c10}). Part~\ref{part:fit} extended the row to all seven candidates (Table~\ref{tab:fit-c10}). Two of the four forms in which this part absorbs AI -- the tenth class and the twelfth dimension -- are exactly the artefacts those computations used; this section supplies the generalisation: the supply-side reading of the row the reader owns, the full D12 column it exercised, and the cells that moved -- cell by cell, with stated and measurable reasons.
|
||||
|
||||
\subsection{The C10 row, cell by cell}
|
||||
\label{subsec:c10row}
|
||||
|
||||
Start from the row you own (Table~\ref{tab:fit-c10}). This subsection adds the one reading that the three computations used but never stated in one place: \emph{which D12 mechanism each cell exercises}. The two $++$ cells (MM, HX) are the \emph{boundary and port} cells -- a CI-verifiable module boundary \citep{drotbohm2023modulith} and an anti-corruption adapter on a port \citep{cockburn2024hexagonal, sculley2015hidden} are what contain a fallible, entangled component. The two $+$ cells (EDA, PF) are the \emph{queue} cells -- asynchronous absorption of latency, rate limits, and outages, and pipeline-shaped ingestion and evals \citep{lewis2020rag}. The capped cells fail the D12 trio in characteristic ways: L provides none of the three -- no queue, no port, no measurement point; MS puts seconds-scale, fallible calls into synchronous chains (the missing queue) \citep{nygard2018release}; SL runs minutes-long LLM and solver work against platform timeout ceilings \citep{jonas2019berkeley}.
|
||||
|
||||
The resulting recommendation -- a hexagonal modular monolith plus pipelines and an orchestrated agent workflow, with EDA as the secondary job/audit spine, governed by token and latency budgets and the determinism boundary (\emph{agents propose; deterministic services decide and book}) -- is recorded in Part~\ref{part:fit} (Section~\ref{subsec:fit-c10}) and in ADR-007 (Listing~\ref{lst:adr007}).
|
||||
|
||||
\subsection{D12 across the seven patterns}
|
||||
\label{subsec:d12}
|
||||
|
||||
What the C10 row exercised for one class, the D12 row of the capability table states for all seven patterns at once. Dimension D12 (AI integrability) measures how cheaply a structure can host a component that is slow, fallible, and priced per call -- concretely, whether the pattern naturally provides \emph{the queue, the port, and the measurement point} that such a component requires. Table~\ref{tab:d12row} restates the D12 row of the capability table (Table~\ref{tab:capability}) with its rationale.
|
||||
|
||||
\begin{table}[htbp]
|
||||
\centering
|
||||
\caption{The D12 row (AI integrability) of the consolidated capability table (Table~\ref{tab:capability}), with tactic-level rationales.}
|
||||
\label{tab:d12row}
|
||||
\small
|
||||
\begin{tabular}{@{}p{2.3cm}cp{9.6cm}@{}}
|
||||
\toprule
|
||||
\textbf{Pattern} & \textbf{D12} & \textbf{Rationale} \\
|
||||
\midrule
|
||||
L -- Layered & $\circ$ & Technical layers give the non-deterministic component no boundary, no queue, and no measurement point of its own \\
|
||||
MM -- Modular monolith & $+$ & A dedicated AI module with a hard, CI-verifiable interface contains the component cheaply \citep{drotbohm2023modulith} \\
|
||||
HX -- Hexagonal & $++$ & The LLM is an adapter on a port: swappable, mockable, contract-guarded -- the ACL discipline structurally built in \citep{cockburn2024hexagonal, evans2003ddd} \\
|
||||
MS -- Microservices & $\circ$ & Per-service isolation helps; synchronous chains through seconds-scale calls hurt -- net neutral \citep{nygard2018release} \\
|
||||
EDA -- Event-driven & $++$ & Queues absorb exactly what LLMs are worst at: latency, rate limits, outages; natural batching points \\
|
||||
PF -- Pipes-and-filters & $++$ & Ingestion, training, and eval pipelines are pipes-and-filters by construction \citep{lewis2020rag, google2023mlops} \\
|
||||
SL -- Serverless & $\circ$ & Event-glue around batch AI APIs fits; platform timeout ceilings collide with minutes-long LLM/solver runs \citep{jonas2019berkeley} \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\subsection{Which existing cells shift, and why}
|
||||
\label{subsec:shifts}
|
||||
|
||||
Beyond the new row and column, AI as a runtime component moves \emph{existing} evaluations in stated directions -- all five movements visible in the D12 ratings and each carrying a measurable reason:
|
||||
|
||||
\begin{enumerate}
|
||||
\item \textbf{Asynchronous patterns gain (EDA, PF $\uparrow$).} Queues and pipelines absorb what LLMs are worst at -- latency, rate limits, outage -- and ingestion and eval pipelines are pipes-and-filters by construction \citep{lewis2020rag, barnett2024seven}.
|
||||
\item \textbf{Hexagonal gains most (HX $\uparrow$).} The ACL/port discipline is exactly what the CACE problem demands \citep{sculley2015hidden}; Assumption A1's cost-of-change criterion bites hardest at model replacement, and testing against deterministic fakes is the only way to keep the deterministic 95\,\% of the system deterministic.
|
||||
\item \textbf{Synchronous distributed chains lose (MS $\downarrow$ where LLM calls sit in the request path).} Seconds-scale latency and per-hop failure probability multiply along the chain; without constitutive stability patterns this is a cascade design \citep{nygard2018release}.
|
||||
\item \textbf{Serverless is conditional (SL $\sim$).} Platform timeout ceilings against minutes-long LLM and solver runs cap it; event-glue around batch APIs remains a fit \citep{jonas2019berkeley}.
|
||||
\item \textbf{A cost dimension becomes load-bearing everywhere.} Cost per request, feature, and tenant is a runtime quality attribute with no counterpart in classical profiles; it belongs in the gateway and in CI budgets, and routing across cheap and expensive models is the new incarnation of a classical resource-arbitration tactic (cascades: up to $\sim$98\,\% cost reduction at comparable quality \citep{chen2023frugalgpt}; learned routers: more than 2$\times$ cheaper without quality loss \citep{ong2025routellm}).
|
||||
\end{enumerate}
|
||||
|
||||
\begin{keypoint}
|
||||
The matrix does not get rewritten by AI; it gets \emph{shifted} -- in five stated directions, for five stated and measurable reasons. A student who can name, for any cell movement, the quality-attribute mechanism behind it (which tactic the pattern bundles or impedes for a slow, fallible, per-call-priced component) has understood both Part~\ref{part:fit} and this one.
|
||||
\end{keypoint}
|
||||
|
||||
\subsection{MLOps maturity: when the pipeline promise is real}
|
||||
\label{subsec:mlops}
|
||||
|
||||
For type-(b) components, the PF cells' promise is realised only at sufficient process maturity. The canonical ladder distinguishes three levels \citep{google2023mlops}: \textbf{Level~0} -- a manual, script-driven, interactive process; data science and operations are separated, and the model is handed ``over the fence'' as an artefact; releases are rare, CI/CD absent, monitoring minimal (the documented reality of many teams). \textbf{Level~1} -- an automated ML pipeline with continuous training: the \emph{pipeline}, not the model, is the deployment artefact, with automated data and model validation, triggers, a metadata store, and a feature store. \textbf{Level~2} -- CI/CD automation of the pipeline components themselves, enabling fast, reliable experiment-to-production cycles. \citet{kreuzberger2023mlops} consolidate the discipline into nine principles (CI/CD automation, workflow orchestration, reproducibility, versioning of data/model/code, collaboration, continuous training and evaluation, metadata tracking, monitoring, feedback loops) with the matching component and role landscape. The fit-theoretical reading: the level describes how much of D9 (testability/deployability) and D12 the organisation can actually \emph{cash in} -- a Level-0 team holding a $++$ pattern rating realises little of it, which is the Axis-B echo of DORA's Axis-A finding that guardrail maturity, not tool adoption, converts potential into performance \citep{dora2025aireport}.
|
||||
|
||||
Three of the four absorption forms are now on the table, each computed rather than asserted -- the tenth class, the twelfth dimension, the shifted cells; the fourth, the emergent composition pattern, is the subject of Section~\ref{sec:agentpattern}. The assumption can therefore be restated as what it has been all along: a falsifiable claim, now with evidence attached.
|
||||
|
||||
\begin{keypoint}
|
||||
\textbf{Assumption A6 restated as a falsifiable claim.} Runtime AI components are non-deterministic, fallible, latency-heavy, per-call-priced, and subject to drift and vendor deprecation \citep{sculley2015hidden, amershi2019software, gama2014drift}. They stretch existing quality dimensions by orders of magnitude and add sub-attributes (token cost per request, eval pass rate, provider deprecation risk, prompt-injection resistance \citep{owasp2025llmtop10}). What does \emph{not} change is the method: scenarios with response measures, tactics, trade-off analysis, ADRs, fitness functions. The theory absorbs AI -- as a tenth application class, a twelfth profile dimension, shifted cell values, and one emergent composition pattern -- instead of being reinvented for it; the quality gate is carried by the one new test-artefact class A6 named from the start, the eval harness.
|
||||
\end{keypoint}
|
||||
|
||||
% ============================================
|
||||
% SECTION: AGENT ORCHESTRATION -- THE EMERGENT EIGHTH PATTERN
|
||||
% ============================================
|
||||
\section{Agent Orchestration: The Emergent Eighth Pattern}
|
||||
\label{sec:agentpattern}
|
||||
|
||||
\emph{``Should I reduce my exposure to European industrials?'' -- no single model call can answer that responsibly, so what structure can?} The final structural novelty of the AI era is the orchestration of agents, and as everywhere in this script, the concrete system comes before the catalogue: this section opens with the advisory workflow the course project actually builds, and only then names what it is an instance of.
|
||||
|
||||
\subsection{Case: the course project's advisor workflow}
|
||||
\label{subsec:case-advisor}
|
||||
|
||||
Walk the question through the platform. An \textbf{orchestrator} -- an LLM call with a fixed system prompt -- splits the request into sub-tasks and delegates each to a specialist. A \textbf{document analyst} retrieves and reads the relevant research notes and filings from the ingestion corpus and returns extracted findings with citations. A \textbf{portfolio quant} produces the exposure and concentration numbers -- by calling only \emph{deterministic} analytics services, because arithmetic is not a job for a language model. A \textbf{compliance checker} verifies the assembled draft: every cited passage exists, every entity resolves against the ontology, every mandate constraint holds. The orchestrator merges the results into one grounded answer. Every call by every participant flows through the LLM gateway of Figure~\ref{fig:llmgateway} -- routed, cached, budgeted, logged -- and nothing any agent produces reaches the user or the books without passing the guard: \emph{agents propose; deterministic services decide and book}.
|
||||
|
||||
Now strip the labels, and the shape is one the reader knows intimately: a coordinator decomposing work for specialised workers is the mediator topology of event-driven architecture (Section~\ref{sec:pat-eda}); the fixed retrieve-extract-check sequence inside each specialist is a pipeline (Section~\ref{sec:pat-pf}); peers coordinating over shared context would be the broker topology. That observation carries the section's deliberately deflationary claim: agent orchestration is not a new architectural style but a \emph{composition pattern for non-deterministic runtime components} that reuses the topologies of the seven patterns the reader already knows -- which is why it can be evaluated with the rating grid the reader already has. This is the claim the outlook of Part~\ref{part:patterns} filed in advance; this section pays it out.
|
||||
|
||||
\subsection{What an agent is -- and is not}
|
||||
\label{subsec:agentdef}
|
||||
|
||||
\begin{definitionbox}[Agent; workflow vs.\ agent]
|
||||
An \emph{agent} is an LLM running in a loop with tools and state: at each iteration the model observes the current state (conversation, tool results, working memory), selects an action (a tool call or an answer), and the loop executes it and feeds the result back -- until a termination condition holds. Schematically: \emph{agent = loop + tools + state}. The load-bearing distinction \citep{anthropic2024agents}: a \textbf{workflow} orchestrates LLM calls and tools along \emph{predefined code paths} -- deterministic structure, non-deterministic building blocks; an \textbf{agent} lets the model \emph{steer its own process and tool use} -- the control flow itself becomes model output. Autonomy is therefore not a binary but a dial, and every notch on it costs latency, tokens, and testability.
|
||||
\end{definitionbox}
|
||||
|
||||
The engineering guidance of the source that defined this vocabulary matches the module's philosophy verbatim: find the simplest solution possible; prefer simple, composable patterns over frameworks; escalate to agents only when the task genuinely requires open decision paths \citep{anthropic2024agents}. Orchestration frameworks that model workflows as explicit graphs \citep{langchain2024langgraph} make the topology inspectable -- which is an architectural virtue for the same reason a C4 diagram is.
|
||||
|
||||
\subsection{Topologies and their classical analogues}
|
||||
\label{subsec:topologies}
|
||||
|
||||
The advisor workflow of Section~\ref{subsec:case-advisor} instantiates one topology; Table~\ref{tab:agenttopology} and Figure~\ref{fig:agenttopologies} name them all. Every workflow topology maps exactly onto a structure from Part~\ref{part:patterns} that the reader now knows cell by cell -- the chain onto pipes-and-filters, orchestrator--workers onto mediator EDA, autonomous multi-agent onto the broker topology -- and the mapping is didactically valuable because every property the classical pattern is known for (and every weakness) transfers.
|
||||
|
||||
\begin{table}[htbp]
|
||||
\centering
|
||||
\caption{Agent-orchestration topologies mapped to classical patterns \citep{anthropic2024agents, langchain2024langgraph}. The classical analogue predicts both the strengths and the failure modes.}
|
||||
\label{tab:agenttopology}
|
||||
\small
|
||||
\begin{tabular}{@{}p{3.4cm}p{3.4cm}p{6.6cm}@{}}
|
||||
\toprule
|
||||
\textbf{Topology} & \textbf{Classical analogue} & \textbf{Structure and use} \\
|
||||
\midrule
|
||||
Prompt chaining (chain) & Pipes-and-filters (PF) & Each call processes the previous output; programmatic gates between stages; fixed decomposition \\
|
||||
Routing & Routing layer / mediator & A classification step directs inputs to specialised prompts or models; the runtime sibling of model routing \\
|
||||
Parallelisation (sectioning, voting) & Broker-style fan-out & Independent subtasks in parallel, or repeated runs with majority vote \\
|
||||
Orchestrator--workers (tree/graph) & Mediator EDA & A lead model decomposes the task dynamically and delegates to workers; central workflow control \\
|
||||
Evaluator--optimizer & Feedback control loop & Generator and evaluator model iterate until a quality criterion holds \\
|
||||
Autonomous multi-agent & Broker topology & Peer agents coordinate over shared context; maximal flexibility, minimal central control \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\begin{figure}[htbp]
|
||||
\centering
|
||||
\begin{tikzpicture}[
|
||||
agentbox/.style={rectangle, draw, rounded corners=3pt, minimum width=1.5cm, minimum height=0.7cm, align=center, font=\scriptsize\sffamily, fill=violet!15, draw=aiviolet, line width=0.7pt},
|
||||
gatebox/.style={rectangle, draw, rounded corners=3pt, minimum width=1.2cm, minimum height=0.7cm, align=center, font=\scriptsize\sffamily, fill=bankgreen!15, draw=bankgreen, line width=0.7pt},
|
||||
lbl/.style={font=\scriptsize\sffamily\bfseries, align=center},
|
||||
arr/.style={-{Stealth[length=2mm]}, semithick, gray!60!black}
|
||||
]
|
||||
% --- Chain ---
|
||||
\node[agentbox] (c1) {LLM 1};
|
||||
\node[gatebox, right=0.5cm of c1] (g1) {gate};
|
||||
\node[agentbox, right=0.5cm of g1] (c2) {LLM 2};
|
||||
\node[agentbox, right=0.5cm of c2] (c3) {LLM 3};
|
||||
\draw[arr] (c1) -- (g1); \draw[arr] (g1) -- (c2); \draw[arr] (c2) -- (c3);
|
||||
\node[lbl, above=0.25cm of g1, xshift=0.9cm] {Chain $\;\hat{=}\;$ pipes-and-filters};
|
||||
|
||||
% --- Orchestrator-workers ---
|
||||
\node[agentbox, right=1.6cm of c3, yshift=0.65cm] (orch) {Orchestrator};
|
||||
\node[agentbox, below=0.55cm of orch, xshift=-1.7cm] (w1) {Worker A};
|
||||
\node[agentbox, below=0.55cm of orch] (w2) {Worker B};
|
||||
\node[agentbox, below=0.55cm of orch, xshift=1.7cm] (w3) {Worker C};
|
||||
\draw[arr] (orch) -- (w1); \draw[arr] (orch) -- (w2); \draw[arr] (orch) -- (w3);
|
||||
\node[lbl, above=0.25cm of orch] {Orchestrator--workers $\;\hat{=}\;$ mediator EDA};
|
||||
|
||||
% --- Evaluator-optimizer ---
|
||||
\node[agentbox, below=2.4cm of c1, xshift=0.6cm] (gen) {Generator};
|
||||
\node[agentbox, right=1.5cm of gen] (ev) {Evaluator};
|
||||
\draw[arr] (gen.10) -- (ev.170);
|
||||
\draw[arr] (ev.190) -- node[below, font=\tiny\sffamily]{feedback} (gen.350);
|
||||
\node[lbl, above=0.25cm of gen, xshift=1.4cm] {Evaluator--optimizer $\;\hat{=}\;$ control loop};
|
||||
|
||||
% --- Multi-agent broker ---
|
||||
\node[gatebox, right=2.6cm of ev, minimum width=3.4cm, minimum height=0.5cm] (bus) {shared context / bus};
|
||||
\node[agentbox, above=0.5cm of bus, xshift=-1.2cm] (a1) {Agent 1};
|
||||
\node[agentbox, above=0.5cm of bus, xshift=1.2cm] (a2) {Agent 2};
|
||||
\node[agentbox, below=0.5cm of bus] (a3) {Agent 3};
|
||||
\draw[arr] (a1) -- (bus); \draw[arr] (a2) -- (bus); \draw[arr] (bus) -- (a3);
|
||||
\node[lbl, below=0.3cm of a3] {Multi-agent $\;\hat{=}\;$ broker topology};
|
||||
\end{tikzpicture}%
|
||||
\caption{Four agent-orchestration topologies and their classical analogues. Deterministic gates (green) between non-deterministic stages (violet) are the workflow discipline: structure stays in code, judgement stays in the model \citep{anthropic2024agents}.}
|
||||
\label{fig:agenttopologies}
|
||||
\end{figure}
|
||||
|
||||
Because the topologies are the old topologies, the evaluation logic of this theory applies unchanged -- sharpened along exactly three axes: \textbf{non-determinism} (testability is read as eval coverage, Section~\ref{subsec:evalharness}), \textbf{token economics} (cost per request, not per infrastructure), and \textbf{fallibility} (fault tolerance is read as guardrails, evaluator loops, and deterministic fallbacks behind ports). Table~\ref{tab:agentchoice} compresses the choice into the same style of decision aid the matrix provides.
|
||||
|
||||
\begin{table}[htbp]
|
||||
\centering
|
||||
\caption{Choosing an orchestration topology from the task signature. Read top-down and stop at the first matching row -- the ordering encodes ``simplest structure first'' \citep{anthropic2024agents}.}
|
||||
\label{tab:agentchoice}
|
||||
\small
|
||||
\begin{tabular}{@{}p{4.9cm}p{3.5cm}p{5.0cm}@{}}
|
||||
\toprule
|
||||
\textbf{Task signature} & \textbf{Topology} & \textbf{Cost/risk note} \\
|
||||
\midrule
|
||||
Fixed decomposition; every intermediate result verifiable & Prompt chain (workflow) & Cheapest and most testable; deterministic gates between stages \\
|
||||
Heterogeneous input categories with specialised handling & Routing & Cheap; the router itself needs its own eval \\
|
||||
Broad, parallelisable subtasks; breadth-first search & Parallelisation or orchestrator--workers & Token cost multiplies with worker count ($\sim$15$\times$ class, see below) \\
|
||||
Output must clear a measurable quality bar & Evaluator--optimizer & Latency and cost grow per iteration; needs a reliable evaluator \\
|
||||
Path genuinely unknown; open-ended tool use & Agent & Highest cost and risk; guardrails, budgets, and oversight mandatory \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\subsection{The economics of autonomy}
|
||||
\label{subsec:agenteconomics}
|
||||
|
||||
The rigour case for restraint is quantified by the best-documented production account available: Anthropic's multi-agent research system (an orchestrator--workers design) beat a single agent by 90.2\,\% on the company's internal research eval -- at roughly \textbf{15$\times$ the token consumption} of a chat interaction (simple agents: about 4$\times$), with token use alone explaining 80\,\% of the performance variance \citep{anthropic2025multiagent} -- the numbers the Part~\ref{part:patterns} outlook previewed. That is a textbook CBAM decision in the sense of Part~\ref{part:fit} \citep{kazman2002making}: autonomy is bought with cost, latency, and error accumulation, and is justified only where the task's utility-response curve clears the price -- broad, parallelisable research questions do; a form-filling workflow does not. Regulation closes the loop from the other side: the AI Act's logging, documentation, human-oversight, and robustness duties (Section~\ref{subsec:aiact}) attach to exactly the autonomy this section prices \citep{eu2024aiact}.
|
||||
|
||||
\begin{keypoint}
|
||||
\textbf{The default rule for agent architecture.} Workflows before agents; the simplest structure first; autonomy only on demonstrated need; every escalation an ADR with a measurement contract \citep{anthropic2024agents}. An orchestration decision without a token budget and an eval threshold is an opinion -- Maxim 6 applies to agents without modification.
|
||||
\end{keypoint}
|
||||
|
||||
\subsection{A capability-profile sketch}
|
||||
\label{subsec:agentprofile}
|
||||
|
||||
If agent orchestration is a composition pattern, it should submit to the same twelve-dimension examination as the seven patterns of Part~\ref{part:patterns}. Table~\ref{tab:agentprofile} offers that profile as a \emph{sketch}: unlike the seven calibrated profiles of Table~\ref{tab:capability}, no Richards--Ford star ratings and no decade of production case studies exist, so every cell is a default hypothesis in the sense of the theory's own limits discussion -- to be replaced by measurement, and re-verified on every model generation. The cells read, as always, ``as the dominant structure of the subsystem it governs'' -- here, the AI subsystem, not the whole platform.
|
||||
|
||||
\begin{table}[htbp]
|
||||
\centering
|
||||
\caption{Capability-profile sketch of agent orchestration against the twelve dimensions -- a provisional profile (state 2025/26), not a calibrated one; every cell carries its own temporal fitness function.}
|
||||
\label{tab:agentprofile}
|
||||
\small
|
||||
\begin{tabular}{@{}p{3.6cm}cp{8.4cm}@{}}
|
||||
\toprule
|
||||
\textbf{Dimension} & \textbf{Rating} & \textbf{Ground} \\
|
||||
\midrule
|
||||
D1 Read scalability & $\circ$ & Orchestration state is small and replicable; throughput is bounded by provider rate limits, not by the structure \\
|
||||
D2 Write scalability \& elasticity & $\circ$ & Fan-out to parallel workers is cheap in structure, expensive in tokens; sustained volume is quota-bound \\
|
||||
D3 Latency \& predictability & $--$ & Seconds per step, steps multiply along the loop; open-ended loops have no tail bound \\
|
||||
D4 Consistency \& integrity & $--$ & Non-deterministic by construction; integrity exists only outside the pattern, in deterministic validation \\
|
||||
D5 Availability \& fault isolation & $-$ & Every step adds provider failure modes and error accumulation; evaluator loops and fallback chains mitigate \citep{nygard2018release} \\
|
||||
D6 Security \& auditability & $\circ$ & Complete step and tool logging is natural ($+$) -- and legally required in high-risk uses \citep{eu2024aiact}; prompt injection and excessive agency widen the attack surface ($-$) \citep{owasp2025llmtop10} \\
|
||||
D7 Evolvability & $+$ & Prompts, tools, and models swap behind contracts; framework and model churn claws part of it back \\
|
||||
D8 Simplicity \& time-to-market & $-$ & A chain workflow is genuinely simple; every notch of autonomy is not \\
|
||||
D9 Testability \& deployability & $--$ & Exhaustive testing is impossible; evals with statistical thresholds replace assertions (Section~\ref{subsec:evalharness}) \\
|
||||
D10 Operating cost efficiency & $--$ & Token cost per request orders of magnitude above classical calls; multi-agent $\sim$15$\times$ chat \citep{anthropic2025multiagent} \\
|
||||
D11 Team scaling & $\circ$ & Sub-agent and tool ownership parallelises teams moderately -- the PF filter-ownership analogy \\
|
||||
D12 AI integrability & $++$ & It \emph{is} the composition pattern for AI components -- trivially its own best host \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
The profile explains at a glance why agent orchestration can never be the dominant structure of a whole platform of class C1--C9: it is vetoed by every High weight on D3, D4, D9, or D10. It is, and remains, an \emph{edge} pattern -- hosted behind the ports of a deterministic core, exactly where the C10 recommendation places it.
|
||||
|
||||
\begin{projektbox}
|
||||
Axis B is \emph{what} you build, and the advisor workflow of Section~\ref{subsec:case-advisor} -- an orchestrator with two to three specialised sub-agents (document analyst, portfolio quant, compliance checker), all behind the LLM gateway of Figure~\ref{fig:llmgateway} -- is what you build it as. The graded Axis-B deliverables are the containment artefacts: (i)~the \textbf{gateway} with model routing, fallback chain, and per-request \textbf{cost observability} (cost per request, per feature -- reported on a dashboard and enforced as a CI budget); (ii)~the \textbf{ontology guard} -- every extracted entity resolves against the deterministic data store, every cited passage exists, portfolio axioms hold; (iii)~the \textbf{eval harness} of Listing~\ref{lst:evalharness} wired as a CI gate; (iv)~one \textbf{ADR} that justifies your chosen orchestration topology against Table~\ref{tab:agentchoice}, with its token budget and eval threshold as the measurement contract. Sub-agents propose; your deterministic services decide and book.
|
||||
\end{projektbox}
|
||||
|
||||
% ============================================
|
||||
% SECTION: SYNTHESIS -- ONE THEORY, FIVE PARTS
|
||||
% ============================================
|
||||
\section{Synthesis: One Theory, Five Parts}
|
||||
\label{sec:synthesis}
|
||||
|
||||
\emph{What, in the end, did AI change?} The bet of the opening can now be settled. Architecture teaching in the AI era faces two symmetric temptations: \emph{denial} -- generative AI as a passing tool fashion that leaves software engineering untouched, a position falsified by the adoption data alone (90\,\% of practitioners report using AI at work by 2025 \citep{dora2025aireport}) -- and \emph{exceptionalism} -- AI systems as a new discipline with new vocabulary, new roles, and new decision logic, a position this part has rejected on the assembled evidence: nothing AI does, on either axis, required a decision no ADR can record, a correctness no response measure can capture, or a structure no tactic vocabulary describes. Between the temptations lies the position defended since Part~\ref{part:foundations}: absorption.
|
||||
|
||||
The script can now be read backwards as a single argument. Part~\ref{part:foundations} established that architecture is the set of significant, hard-to-reverse decisions (A1), that everything is a trade-off (A2), that quality attributes -- not features -- drive structure (A3), and that requirements decide anything only as measurable scenarios (A4); it fixed the twelve dimensions on which all later judgements run (Table~\ref{tab:dimensions}). Part~\ref{part:patterns} turned seven patterns into capability profiles by explaining every rating through the tactics a pattern bundles or impedes (Table~\ref{tab:capability}). Part~\ref{part:applications} turned ten application classes into requirements profiles -- recurring bundles of architecturally significant requirements with response measures and hard constraints (Table~\ref{tab:requirements}). Part~\ref{part:fit} matched them: knock-out screening, veto rule, holistic ordinal reading (Table~\ref{tab:fitmatrix}); it insisted that hybrids are the normal case, that the decision procedure ends in an ADR, and that every ADR ends in a measurement contract, because a decision is a hypothesis tested over the life cycle (A5). Part~\ref{part:ai} then subjected the whole construction to its hardest contemporary stress test -- and the construction held (A6): Axis A raised the value of the theory's artefacts (documentation as agent context, fitness functions as operating licence) rather than obsoleting them; Axis B was absorbed as one class, one dimension, five cell shifts, and one composition pattern whose profile the theory's own grid can express.
|
||||
|
||||
\begin{keypoint}
|
||||
\textbf{Maxim 8.} The theory absorbs AI: a tenth application class, a twelfth dimension, shifted cells, one emergent composition pattern -- same assumptions, same procedure, same contract. The pipeline of this script is one sentence long: \emph{scenarios with numbers (Part~\ref{part:foundations}) meet capability profiles (Part~\ref{part:patterns}) and requirements profiles (Part~\ref{part:applications}) in a non-compensatory match (Part~\ref{part:fit}) whose result is an ADR with a measurement contract -- and nothing about AI, on either axis, changes a single step of it (Part~\ref{part:ai}).}
|
||||
\end{keypoint}
|
||||
|
||||
One symmetry deserves to be made explicit, because it is the deepest result of this part. Axis A concluded that generation is cheap and verification is the bottleneck, so the SDLC must be rebuilt around machine-checkable specifications, guardrails, and human accountability. Axis B concluded that model output is cheap and validation is the bottleneck, so the runtime must be rebuilt around contracts, ontology guards, eval harnesses, and a human-owned determinism boundary. These are the same conclusion at two different binding sites: whether the LLM sits in the toolchain or in the product, the engineering discipline it demands is the discipline of \emph{containing cheap, fallible generation behind expensive, explicit verification} -- which is, on reflection, what this module has called architecture all along.
|
||||
|
||||
\begin{thinkbox}
|
||||
Close the module with the symmetry above. Consider the artefact pairs across the two axes: \texttt{AGENTS.md} versus the system prompt and ontology; the CI fitness function versus the runtime ontology guard; the code-review obligation versus the human-oversight duty of the AI Act; the test suite as the agent's operating licence versus the eval harness as the model's operating licence. For each pair: is this genuinely \emph{one} engineering discipline observed at two binding sites, or are there differences of kind -- in reversibility, in accountability, in failure semantics -- that the symmetry hides? And if it is one discipline: which parts of this script would survive the next order-of-magnitude improvement in model capability, and which would you expect to rewrite?
|
||||
\end{thinkbox}
|
||||