810 lines
44 KiB
TeX
810 lines
44 KiB
TeX
% !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}
|