1<!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" as="image" href="https://cdn.hashnode.com/res/hashnode/image/unsplash/aQYgUYwnCsM/upload/v1641121050901/_cvnyJNXU.jpeg"/><link rel="stylesheet" href="/_next/static/css/0d16c72050851854.css" data-precedence="next"/><link rel="stylesheet" href="/_next/static/css/7ffcc02a3c67389b.css" data-precedence="next"/><link rel="stylesheet" href="/_next/static/css/c20e76e7d11dec32.css" data-precedence="next"/><link rel="stylesheet" href="/_next/static/css/59fefb2212bd5b60.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/webpack-55b36f0cd6c208fe.js"/>
1<script src="/_next/static/chunks/4bd1b696-100b9d70ed4e49c1.js" async=""></script>
1<script src="/_next/static/chunks/9da6db1e-8a4e8c23641c31bf.js" async=""></script>
1<script src="/_next/static/chunks/1255-a242e0ce0372fddf.js" async=""></script>
1<script src="/_next/static/chunks/main-app-bda8a52fe841b3aa.js" async=""></script>
1<script src="/_next/static/chunks/4554-984b480a9db5f3fe.js" async=""></script>
1<script src="/_next/static/chunks/7563-4dfa0994a9b0e37c.js" async=""></script>
1<script src="/_next/static/chunks/9216-9272709ba40c1cfd.js" async=""></script>
1<script src="/_next/static/chunks/2810-6b74d77b4b0dc790.js" async=""></script>
1<script src="/_next/static/chunks/3091-bf1537ff6571a1bd.js" async=""></script>
1<script src="/_next/static/chunks/app/layout-6ae7b4b583d4bba3.js" async=""></script>
1<script src="/_next/static/chunks/app/not-found-b861935655c5698b.js" async=""></script>
1<script src="/_next/static/chunks/5001-fae0bebdd93f95e3.js" async=""></script>
1<script src="/_next/static/chunks/2423-c8b1388240338d7d.js" async=""></script>
1<script src="/_next/static/chunks/652-f40dcb480b4e356f.js" async=""></script>
1<script src="/_next/static/chunks/730-8191af9e9424b148.js" async=""></script>
1<script src="/_next/static/chunks/app/page-cc18ae1a3a7a5ed8.js" async=""></script>
1<script src="/_next/static/chunks/0dbeb660-9e82e99813552576.js" async=""></script>
1<script src="/_next/static/chunks/1545-7abf96433ff6553f.js" async=""></script>
1<script src="/_next/static/chunks/app/%5B...slug%5D/page-ce41bf29cdfb993a.js" async=""></script>
1<meta name="next-size-adjust" content=""/><title>DDD Aggregate pattern: Processes, State Machines and Transducers</title><meta name="description" content="An introduction to designing the Domain-Driven Design Aggregate pattern via first principles from automata theory"/><meta name="google-site-verification" content="K1pB_brVgJW4jSA9hhYdMxGuyiR0EK0Pfzi6nWEH8OE"/><link rel="canonical" href="https://t-pl.io/ddd-aggregates-processes-state-machines-and-transducers"/><meta property="og:title" content="DDD Aggregate pattern: Processes, State Machines and Transducers"/><meta property="og:description" content="An introduction to designing the Domain-Driven Design Aggregate pattern via first principles from automata theory"/><meta property="og:url" content="https://t-pl.io/ddd-aggregates-processes-state-machines-and-transducers"/><meta property="og:site_name" content="Thomas Ploch's Blog - Systems, People & Technology"/><meta property="og:image" content="https://cdn.hashnode.com/res/hashnode/image/unsplash/aQYgUYwnCsM/upload/v1641121050901/_cvnyJNXU.jpeg"/><meta property="og:image:width" content="1200"/><meta property="og:image:height" content="630"/><meta property="og:type" content="article"/><meta property="article:published_time" content="2022-01-02T10:52:42.124Z"/><meta property="article:modified_time" content="2022-01-14T13:34:29.696Z"/><meta property="article:author" content="https://t-pl.io/@tPl0ch"/><meta name="twitter:card" content="summary_large_image"/><meta name="twitter:creator" content="https://twitter.com/tPl0ch"/><meta name="twitter:title" content="DDD Aggregate pattern: Processes, State Machines and Transducers"/><meta name="twitter:description" content="An introduction to designing the Domain-Driven Design Aggregate pattern via first principles from automata theory"/><meta name="twitter:image" content="https://cdn.hashnode.com/res/hashnode/image/unsplash/aQYgUYwnCsM/upload/v1641121050901/_cvnyJNXU.jpeg"/><link rel="icon" href="/favicon.ico"/>
1<script type="text/javascript">window.addEventListener('message',function(e){var d=e.data;if(!d||d.__hnWidget!==1||typeof d.h!=='number'||d.h<=0)return;var f=document.querySelectorAll('.hn-widget-frame');for(var i=0;i<f.length;i++){if(f[i].contentWindow===e.source){f[i].style.height=d.h+'px';break;}}});</script>
1<script src="/_next/static/chunks/polyfills-42372ed130431b0a.js" noModule=""></script>
1</head><body class="__variable_c2612a __variable_246ccd __variable_3069d5 bg-background dark:bg-background"><div hidden=""><!--$--><!--/$--></div>
1<script>((a2, b2, c4, d3, e2, f2, g4, h3) => { 2 let i3 = document.documentElement, j2 = ["light", "dark"]; 3 function k2(b3) { 4 var c5; 5 (Array.isArray(a2) ? a2 : [a2]).forEach((a3) => { 6 let c6 = a3 === "class", d4 = c6 && f2 ? e2.map((a4) => f2[a4] || a4) : e2; 7 c6 ? (i3.classList.remove(...d4), i3.classList.add(f2 && f2[b3] ? f2[b3] : b3)) : i3.setAttribute(a3, b3); 8 }), c5 = b3, h3 && j2.includes(c5) && (i3.style.colorScheme = c5); 9 } 10 if (d3) k2(d3); 11 else try { 12 let a3 = localStorage.getItem(b2) || c4, d4 = g4 && a3 === "system" ? window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light" : a3; 13 k2(d4); 14 } catch { 15 } 16 })("class","theme","system",null,["light","dark"],null,true,true)</script>
16<main id="main-content" class="min-h-screen bg-transparent"><header class="sticky top-0 z-50 w-full py-4 bg-background backdrop-blur-sm transition-transform duration-300 translate-y-0"><a href="#main-content" class="sr-only focus:not-sr-only focus:absolute focus:left-4 focus:top-4 focus:z-50 focus:rounded-md focus:bg-background focus:px-4 focus:py-2 focus:text-sm focus:shadow">Skip to main content</a><div class="relative w-full mx-auto xl:max-w-[80rem] 2xl:max-w-[90rem] px-4 sm:px-12 md:px-18 lg:px-16 xl:px-10"><div class="flex items-center justify-between gap-3 xl:hidden"><div class="flex items-center gap-3 min-w-0 flex-1"><a href="https://hashnode.com/?utm_source=https%3A%2F%2Ft-pl.io&utm_medium=referral&utm_campaign=blog_header_logo&utm_content=logo" class="inline-flex items-center justify-center text-lg text-muted-foreground hover:text-foreground transition border rounded-md h-9 w-9 shrink-0 border-border hover:bg-muted"><i class="text-xl fa-brands fa-hashnode" aria-hidden="true"></i><span class="sr-only">Hashnode</span></a><a title="Thomas Ploch's Blog - Systems, People & Technology" class="text-lg font-semibold text-foreground truncate min-w-0" href="/">Thomas Ploch's Blog - Systems, People & Technology</a></div><div class="flex items-center gap-2 shrink-0"><button class="gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 hover:bg-accent py-2 h-9 w-9 px-0 flex items-center justify-center text-muted-foreground hover:text-foreground bg-transparent border-border shadow-none" aria-label="Open search (press Control or Command and K)"><i class="fa-jelly fa-search text-sm" aria-hidden="true"></i><span class="sr-only">Open search (press Control or Command and K)</span></button><button class="inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 hover:bg-accent w-9 px-3 h-9 text-muted-foreground hover:text-foreground shadow-none" type="button" id="radix-_R_2j4anpfalb_" aria-haspopup="menu" aria-expanded="false" data-state="closed" data-slot="dropdown-menu-trigger"><i class="fa-jelly fa-sun text-sm scale-100 rotate-0 transition-all dark:scale-0 dark:-rotate-90" aria-hidden="true"></i><i class="fa-jelly fa-moon absolute text-sm scale-0 rotate-90 transition-all dark:scale-100 dark:rotate-0" aria-hidden="true"></i><span class="sr-only">Toggle theme</span></button><button class="inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border border-input bg-background hover:bg-accent hover:text-accent-foreground py-2 h-9 w-10 px-0 shadow-none" type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_3j4anpfalb_" data-state="closed" data-slot="sheet-trigger"><i class="fa-jelly fa-bars" aria-hidden="true"></i><span class="sr-only">Open menu</span></button></div></div><div class="hidden xl:grid gap-4 items-center xl:grid-cols-[1fr_auto_1fr] xl:gap-6 max-w-full xl:mx-auto xl:max-w-[80rem] 2xl:max-w-[90rem]"><div class="flex items-center w-full gap-3 min-w-0"><a href="https://hashnode.com/?utm_source=https%3A%2F%2Ft-pl.io&utm_medium=referral&utm_campaign=blog_header_logo&utm_content=logo" class="inline-flex items-center justify-center text-lg text-muted-foreground hover:text-foreground transition border rounded-md h-9 w-9 border-border hover:bg-muted"><i class="text-xl fa-brands fa-hashnode" aria-hidden="true"></i><span class="sr-only">Hashnode</span></a><span class="h-6 border-l border-border"></span>
16<p class="font-semibold text-foreground min-w-0 truncate text-sm"><a title="Thomas Ploch's Blog - Systems, People & Technology" href="/">Thomas Ploch's Blog - Systems, People & Technology</a></p></div><div></div><div class="flex items-center justify-end gap-3 text-muted-foreground"><button class="gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 hover:bg-accent py-2 h-9 w-9 px-0 flex items-center justify-center text-muted-foreground hover:text-foreground bg-transparent border-border shadow-none" aria-label="Open search (press Control or Command and K)"><i class="fa-jelly fa-search text-sm" aria-hidden="true"></i><span class="sr-only">Open search (press Control or Command and K)</span></button><div class="flex items-center gap-3"><button class="inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 hover:bg-accent w-9 px-3 h-9 text-muted-foreground hover:text-foreground shadow-none" type="button" id="radix-_R_6t4anpfalb_" aria-haspopup="menu" aria-expanded="false" data-state="closed" data-slot="dropdown-menu-trigger"><i class="fa-jelly fa-sun text-sm scale-100 rotate-0 transition-all dark:scale-0 dark:-rotate-90" aria-hidden="true"></i><i class="fa-jelly fa-moon absolute text-sm scale-0 rotate-90 transition-all dark:scale-100 dark:rotate-0" aria-hidden="true"></i><span class="sr-only">Toggle theme</span></button><a target="_blank" rel="noopener" class="inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border border-input bg-background hover:bg-accent hover:text-accent-foreground py-2 gap-2 px-3 h-9 shadow-none" href="https://hashnode.com"><i class="text-sm fa-jelly fa-pencil" aria-hidden="true"></i>Write</a></div></div></div></div></header><div data-slot="dialog-header" class="flex flex-col gap-2 text-center sm:text-left sr-only"><h2 id="radix-_R_8anpfalbH1_" data-slot="dialog-title" class="text-lg leading-none font-semibold">Command Palette</h2><p id="radix-_R_8anpfalbH2_" data-slot="dialog-description" class="text-muted-foreground text-sm">Search for a command to run...</p></div><section class="py-8"><div class="px-4 sm:px-8"><div class="w-full max-w-full xl:mx-auto xl:max-w-[80rem] 2xl:max-w-[90rem]"><div class="grid gap-5 max-w-full"><article class="w-full max-w-full rounded-xl border bg-card text-card-foreground"><div class="px-5 pt-12 pb-8 sm:px-8"><header class="space-y-5"><div class="space-y-4 text-center max-w-4xl mx-auto"><h1 class="text-2xl sm:text-3xl md:text-4xl lg:text-5xl font-bold leading-tight tracking-tight text-balance text-foreground">DDD Aggregates: Processes, State Machines and Transducers</h1><p class="text-lg sm:text-xl leading-normal font-normal text-muted-foreground text-balance">An introduction to designing the Domain-Driven Design Aggregate pattern via first principles from automata theory</p><div class="flex flex-wrap items-center justify-center gap-3 text-sm text-muted-foreground"><div class="flex items-center gap-2"><span>Updated</span><time dateTime="2022-01-14T13:34:29.696Z">January 14, 2022</time></div><span class="text-muted-foreground">â¢</span><span>10<!-- --> min read</span><span class="text-muted-foreground">â¢</span><a href="/ddd-aggregates-processes-state-machines-and-transducers.md" target="_blank" rel="noopener" class="inline-flex items-center gap-2 text-muted-foreground transition-colors hover:text-foreground"><i class="fa-brands fa-markdown" aria-hidden="true"></i>View as Markdown</a></div></div></header></div><div class="w-full"><img alt="DDD Aggregates: Processes, State Machines and Transducers" width="1200" height="750" decoding="async" data-nimg="1" class="w-full h-auto" style="color:transparent" src="https://cdn.hashnode.com/res/hashnode/image/unsplash/aQYgUYwnCsM/upload/v1641121050901/_cvnyJNXU.jpeg"/></div><div class="px-5 py-12 sm:px-8 space-y-8"><div class="max-w-2xl mx-auto"><div class="flex flex-wrap items-center gap-5"><div class="flex items-center gap-5"><div class="flex gap-3 items-start"><a target="_blank" rel="noopener" href="https://hashnode.com/@tPl0ch"><span class="relative flex shrink-0 overflow-hidden rounded-full h-10 w-10 border border-border transition-opacity hover:opacity-80"><span class="flex h-full w-full items-center justify-center rounded-full bg-muted text-muted-foreground font-semibold text-lg">T</span></span></a><div class="min-w-0"><div class="flex items-center gap-2"><a target="_blank" rel="noopener" class="font-medium text-foreground hover:text-primary transition-colors" href="https://hashnode.com/@tPl0ch">Thomas Ploch</a><div class="flex items-center gap-1.5 text-sm"><a target="_blank" rel="noopener" class="text-muted-foreground hover:text-foreground transition-colors" aria-label="X (Twitter)" href="https://twitter.com/tPl0ch"><i class="fa-brands fa-x-twitter" aria-hidden="true"></i></a><a target="_blank" rel="noopener" class="text-muted-foreground hover:text-foreground transition-colors" aria-label="LinkedIn" href="https://www.linkedin.com/in/thomas-ploch-a3b79059/"><i class="fa-brands fa-linkedin" aria-hidden="true"></i></a></div></div><div class="text-sm text-muted-foreground line-clamp-2"><p>My name is Thomas, I am 41 years old and an IT generalist with +15 years of experience in various industries including insurance, e-commerce, manufacturing, logistics, travel and transportation.</p> 17<p>I have built, led and grown various development teams and am currently very interested in the "New Work" movement. My belief is that the command & control structures found in many organizations are relic from the industrial revolution, and that we as an industry need to move beyond these old ways of working - facilitative leadership, cross-functional collaboration, generative cultures, networked organizations.</p> 18<p>My current technical focus lies on building distributed reactive systems within the domain of dynamic pricing, applying a mix of functional thinking with the strategic and tactical principles from domain-driven design.</p> 19</div></div></div></div></div></div><div class="max-w-2xl mx-auto"><a class="group flex items-center gap-3 rounded-lg border border-border px-3 py-2 transition hover:border-primary hover:bg-accent" href="/series/process-aggregates"><i class="fa-jelly fa-layer-group h-4 w-4 text-muted-foreground group-hover:text-primary transition-colors" aria-hidden="true"></i><div class="flex flex-col"><span class="text-sm text-muted-foreground">Part of series</span><span class="text-sm font-medium text-foreground group-hover:text-primary transition-colors">Domain-Driven Design: A mathematical model for process-oriented Aggregates</span></div></a></div><div class="relative"><aside class="hidden xl:block absolute top-0 left-0 h-full"><nav class="sticky top-22 w-44"><div class="hidden xl:block group/toc relative"><div class="grid"><div class="[grid-area:1/1] opacity-0 group-hover/toc:opacity-100 transition-opacity duration-200 max-h-[calc(100vh-3rem)] overflow-y-auto"><p class="text-sm font-semibold uppercase tracking-wide text-muted-foreground mb-3">On this page</p><nav aria-label="On this page"><a class="block py-1 text-sm transition-colors hover:text-foreground text-muted-foreground" style="padding-left:0rem" href="#heading-the-need-for-process-oriented-models">The need for process-oriented models</a><a class="block py-1 text-sm transition-colors hover:text-foreground text-muted-foreground" style="padding-left:0.75rem" href="#heading-the-rise-of-collaborative-temporal-modelling">The rise of collaborative temporal modelling</a><a class="block py-1 text-sm transition-colors hover:text-foreground text-muted-foreground" style="padding-left:0rem" href="#heading-rediscovering-finite-state-machines">Rediscovering Finite-State Machines</a><a class="block py-1 text-sm transition-colors hover:text-foreground text-muted-foreground" style="padding-left:0.75rem" href="#heading-the-universe-is-a-messy-place">The universe is a messy place</a><a class="block py-1 text-sm transition-colors hover:text-foreground text-muted-foreground" style="padding-left:0.75rem" href="#heading-where-are-the-events">Where are the Events?</a><a class="block py-1 text-sm transition-colors hover:text-foreground text-muted-foreground" style="padding-left:0rem" href="#heading-introducing-finite-state-transducers-fsts">Introducing Finite-State Transducers (FSTs)</a><a class="block py-1 text-sm transition-colors hover:text-foreground text-muted-foreground" style="padding-left:0.75rem" href="#heading-a-short-excursion-on-the-output-relation-w-omega">A short excursion on the output relation Ï (omega)</a><a class="block py-1 text-sm transition-colors hover:text-foreground text-muted-foreground" style="padding-left:0rem" href="#heading-example-designing-a-user-registration-process">Example: Designing a User Registration Process</a><a class="block py-1 text-sm transition-colors hover:text-foreground text-muted-foreground" style="padding-left:0.75rem" href="#heading-speaking-the-event-language">Speaking the Event language!</a><a class="block py-1 text-sm transition-colors hover:text-foreground text-muted-foreground" style="padding-left:0.75rem" href="#heading-thou-command-shall-be-my-duty">Thou Command shall be my duty!</a><a class="block py-1 text-sm transition-colors hover:text-foreground text-muted-foreground" style="padding-left:0.75rem" href="#heading-designing-the-states">Designing the States</a><a class="block py-1 text-sm transition-colors hover:text-foreground text-muted-foreground" style="padding-left:0.75rem" href="#heading-how-should-we-react">How should we react?</a><a class="block py-1 text-sm transition-colors hover:text-foreground text-muted-foreground" style="padding-left:0.75rem" href="#heading-construction-of-our-transducer-aggregate">Construction of our Transducer Aggregate!</a><a class="block py-1 text-sm transition-colors hover:text-foreground text-muted-foreground" style="padding-left:1.5rem" href="#heading-exercise">Exercise</a><a class="block py-1 text-sm transition-colors hover:text-foreground text-muted-foreground" style="padding-left:0rem" href="#heading-conclusions">Conclusions</a><a class="block py-1 text-sm transition-colors hover:text-foreground text-muted-foreground" style="padding-left:0rem" href="#heading-whats-next">Whatâs next?</a><a class="block py-1 text-sm transition-colors hover:text-foreground text-muted-foreground" style="padding-left:0rem" href="#heading-personal-note">Personal note</a></nav></div><div class="[grid-area:1/1] relative flex flex-col gap-px transition-opacity duration-200 group-hover/toc:opacity-0 pointer-events-none self-start max-h-[calc(100vh-3rem)] overflow-hidden pl-3"><div class="absolute left-0 w-0.5 rounded-full bg-foreground transition-all duration-300 opacity-0" style="transform:translateY(0px);height:12px"></div><div class="flex items-center h-3" style="padding-left:0px"><div class="h-0.5 rounded-full transition-all duration-300 bg-border" style="width:50px"></div></div><div class="flex items-center h-3" style="padding-left:10px"><div class="h-0.5 rounded-full transition-all duration-300 bg-border" style="width:44px"></div></div><div class="flex items-center h-3" style="padding-left:0px"><div class="h-0.5 rounded-full transition-all duration-300 bg-border" style="width:35px"></div></div><div class="flex items-center h-3" style="padding-left:10px"><div class="h-0.5 rounded-full transition-all duration-300 bg-border" style="width:29px"></div></div><div class="flex items-center h-3" style="padding-left:10px"><div class="h-0.5 rounded-full transition-all duration-300 bg-border" style="width:21px"></div></div><div class="flex items-center h-3" style="padding-left:0px"><div class="h-0.5 rounded-full transition-all duration-300 bg-border" style="width:54px"></div></div><div class="flex items-center h-3" style="padding-left:10px"><div class="h-0.5 rounded-full transition-all duration-300 bg-border" style="width:48px"></div></div><div class="flex items-center h-3" style="padding-left:0px"><div class="h-0.5 rounded-full transition-all duration-300 bg-border" style="width:47px"></div></div><div class="flex items-center h-3" style="padding-left:10px"><div class="h-0.5 rounded-full transition-all duration-300 bg-border" style="width:28px"></div></div><div class="flex items-center h-3" style="padding-left:10px"><div class="h-0.5 rounded-full transition-all duration-300 bg-border" style="width:30px"></div></div><div class="flex items-center h-3" style="padding-left:10px"><div class="h-0.5 rounded-full transition-all duration-300 bg-border" style="width:20px"></div></div><div class="flex items-center h-3" style="padding-left:10px"><div class="h-0.5 rounded-full transition-all duration-300 bg-border" style="width:20px"></div></div><div class="flex items-center h-3" style="padding-left:10px"><div class="h-0.5 rounded-full transition-all duration-300 bg-border" style="width:41px"></div></div><div class="flex items-center h-3" style="padding-left:20px"><div class="h-0.5 rounded-full transition-all duration-300 bg-border" style="width:10px"></div></div><div class="flex items-center h-3" style="padding-left:0px"><div class="h-0.5 rounded-full transition-all duration-300 bg-border" style="width:11px"></div></div><div class="flex items-center h-3" style="padding-left:0px"><div class="h-0.5 rounded-full transition-all duration-300 bg-border" style="width:12px"></div></div><div class="flex items-center h-3" style="padding-left:0px"><div class="h-0.5 rounded-full transition-all duration-300 bg-border" style="width:13px"></div></div></div></div></div></nav></aside><div class="max-w-2xl mx-auto min-w-0 contain-[inline-size]"><div class="prose dark:prose-invert prose-pre:bg-foreground prose-pre:text-background prose-pre:border prose-pre:border-border prose-pre:rounded prose-pre:p
19x-5 prose-pre:py-4 dark:prose-pre:bg-muted dark:prose-pre:text-foreground dark:prose-pre:border-border prose-pre:overflow-x-auto max-w-none text-base sm:text-lg [&>div>p:first-child]:mt-0 [&>div>p:first-child]:pt-0 min-w-0 wrap-break-word [&_a]:break-all **:max-w-full"><div><p>This blog post is the first one in a series of three posts in which we try to derive a mathematical model for process-oriented Domain-Driven Design (DDD) Aggregates.</p> 20<h2 id="heading-the-need-for-process-oriented-models">The need for process-oriented models</h2> 21<p>In order to understand this need we need to dive into complex systems theory. Donât worry, we will not dive deep!</p> 22<p>Not surprisingly software is not an isolated artifact. It must be embedded into the socio-technical context of the people that use and produce it, paired with the constant interactions of the environment. What we need to know is how complex systems show the behaviors that we, as system designers, try to capture in useful abstractions.</p> 23<blockquote> 24<p><strong>Organizations are dynamic, hierarchically structured entities. Such dynamism is reflected in the emergence of significant events at every organizational level.</strong></p> 25<p><a target="_blank" href="https://www.researchgate.net/publication/272427231_Event_System_Theory_An_Event-Oriented_Approach_to_the_Organizational_Sciences" rel="noopener ugc">[Morgeson F., Mitchell T., Liu D. 2015. Event System Theory: An Event-Oriented Approach To The Origanisational Sciences]</a></p> 26</blockquote> 27<p>We will call these patterns of events <strong>processes</strong>. These processes emerge in systems to achieve something, be it selling books online or providing restaurants with seat reservations. A large research topic termed process theories is trying to understand how patterns of events lead to positive outcomes. Ultimately they are <strong>âstories about what happened and who did what when â that is, events, activities, and choices ordered over timeâ</strong> <a target="_blank" href="https://www.jstor.org/stable/259349?seq=1#page_scan_tab_contents" rel="noopener ugc">[Langley, A. 1999. Strategies for theorizing from process data]</a>.</p> 28<h3 id="heading-the-rise-of-collaborative-temporal-modelling">The rise of collaborative temporal modelling</h3> 29<p>Over the past years new practices to capture these processes emerged. Event Storming, Story Mapping or Domain Story Telling are all examples of approaches to recognize that understanding the repeating patterns of events can give us a great leverage in designing working solutions. These results regularly have a much larger overlap with the organizational reality than traditional static modelling techniques.</p> 30<p>Temporal modelling also had an effect on the tactical design choices that experienced DDD practitioners make when working with Aggregates. Aggregates are then defined as a combination of <strong>Commands</strong> (stimuli from the environment), <strong>Behaviors</strong> (reactions to incoming stimuli that can change the systemâs response mechanisms) and <strong>Events</strong> (system signals in response to changes in system state). The âEvent Sourcingâ pattern for example builds on these fundamental design choices to make the time-ordered â hence âtemporalâ â patterns of events the central element of its design.</p> 31<p><strong>If we can define some Aggregates by time-ordered series of events, then it follows that these Aggregates are also processes.</strong></p> 32<h2 id="heading-rediscovering-finite-state-machines">Rediscovering Finite-State Machines</h2> 33<p>Modelling processes is nothing new in computing. And <strong>automata theory</strong> seems especially interesting:</p> 34<blockquote> 35<p>A Finite-State Machine (FSM) formulation is used to describe the processes during which information or tasks move from one state to another for action, according to a set of rules. The states consists of the smallest amount of information that together with the knowledge of the input can determine the output.</p> 36</blockquote> 37<p>The terms Automaton and Machine are used interchangeably, so when we talk about FSA, we also mean FSM.</p> 38<p>Translated into our process terminology, FSMs process a stream of system stimuli (Commands), enforcing invariants and changing the system state (Behaviors).</p> 39<p>The following figure (Fig. 2) shows how the temporal nature of FSMs is driven by the time-ordered and unidirectional stream of Commands.</p> 40<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1641031481149/N6f766oxh.jpeg" alt="1 Qfbo0Jmfxwoy9tujEhdZ7g.jpg" /></p> 41<p>Since we want to derive a mathematical model, letâs look at the definition of an Finite-State Machine using our previously derived process terminology. An FSM Î is a 5-tuple</p> 42<p>\[ 43A = \Big(S, C, \delta\colon S \times C \to S, S_0\colon S_0 \in S, F\colon F \subset S \Big) 44\]</p> 45<p>where:</p> 46<ul> 47<li><strong>S</strong> is a non-empty, finite set of states</li> 48<li><strong>C</strong> is the <strong>Command language</strong>, a non-empty, finite set of Commands</li> 49<li><strong>δ</strong> is the set of <strong>Behaviors</strong> â a relation between a state and Command to a state</li> 50<li><strong>Sâ</strong> is the initial state where Sâ is an element of S</li> 51<li><strong>F</strong> is the non-empty, finite set of final states where <strong>F</strong> is a subset of <strong>S</strong></li> 52</ul> 53<p>Given this definition, we will need to derive the command and state alphabets from the domain expertsâ knowledge and then connect the dots via our Behavior functions.</p> 54<h3 id="heading-the-universe-is-a-messy-place">The universe is a messy place</h3> 55<p>We love to look for deterministic solutions to problems that are complex and thus non-deterministic by nature. DDD as a modelling approach embraces unexpected behaviors of systems â which is one of the major reasons why I believe applying DDD thinking to complex problems is almost always a good choice. This means that responses to system stimuli are often different depending on the current situation. Imagine yourself as a call-center agent that is suddenly advised to re-route calls for specific topics to supervisors. The world is just not predictable. 56Non-deterministic Finite-State Auatomata (NDFA)</p> 57<p>In order to deal with this messy world automata theory offers two distinct types of FSAs that can express these differences â Non-Deterministic (NDFA) and Deterministic (DFA) FSAs. Differences between DFA and NDFAs are subtle. While DFAs have exactly one transition for each state and command pair, NDFAs can have multiple, or even none. Mathematically, they are both equivalent. You can always transform a DFA into an NDFA and back again.</p> 58<p>But they do differ between the amount of complexity required to represent them. An NDFA with n states can be transformed into a DFA with up to 2â¿ states. <strong>For a decently complicated NDFA of 10 states we would need up to 1024 states in a DFA to represent it!</strong></p> 59<blockquote> 60<p><strong>
60When using NDFAs you trade determinism for simplicity!</strong></p> 61</blockquote> 62<h3 id="heading-where-are-the-events">Where are the Events?</h3> 63<p>If we recollect the definition of the FSA â which was defined by the Command and state languages paired with the Behaviors â one might recognize that there is currently no way to signal anything back to the systems. So, where are the events?</p> 64<p>It seems like a plain NDFA is not enough to represent our processes. Can automata theory provide another concept that we can use in this case?</p> 65<p>Spoiler, yes it can!</p> 66<h2 id="heading-introducing-finite-state-transducers-fsts">Introducing Finite-State Transducers (FSTs)</h2> 67<p>Letâs compare the following schematic diagram of an FST (Fig. 4) with the previous one of an FSM (Fig. 2) and see if we can spot a difference:</p> 68<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1641115365141/UcZxMwTlj.jpeg" alt="1 oecW_d-OOCvYrzEUd4Awsg.jpg" /></p> 69<p>We now have an actual output of Events that correspond to the states and Commands that were fed in. Exactly what we need to send our signals out into the world to wreak havoc! Again, letâs have a look at the formal definition of an <strong>Finite-State Transducer</strong>. It is a 7-tuple</p> 70<p>\[ 71A = \Big(S, C, E, \delta\colon S \times C \to S, \omega\colon S \times C \to E, S_0\colon S_0 \subset S, F\colon F \subset S \Big) 72\]</p> 73<p>where:</p> 74<ul> 75<li><strong>S</strong> is a non-empty, finite set of states</li> 76<li><strong>C</strong> is the <strong>Command language</strong>, a non-empty, finite set of Commands</li> 77<li><strong>E</strong> is the <strong>Event language</strong>, a non-empty, finite set of Events</li> 78<li><strong>δ</strong> is the set of <strong>Behaviors</strong> â a relation of a state and Command pair to a state of form <strong>δ : S x Câ S</strong></li> 79<li><strong>Ï</strong> is the <strong>output relation</strong> of a state and Command pair to an Event of form <strong>Ï : S x C â E</strong></li> 80<li><strong>Sâ</strong> is the non-empty, finite set of initial states where <strong>Sâ â S</strong> (Sâ is a subset of S)</li> 81<li><strong>F</strong> is the non-empty, finite set of final states where <strong>F â S</strong> (F is a subset of S)</li> 82</ul> 83<p>Now that we have Commands, Behaviors and Events we can model our processes as non-deterministic FSTs. Letâs get to action and use the math in an example scenario!</p> 84<h3 id="heading-a-short-excursion-on-the-output-relation-w-omega">A short excursion on the output relation Ï (omega)</h3> 85<p>I quickly want to mention that automata theory differs between two major types of transducers â the <a target="_blank" href="https://en.wikipedia.org/wiki/Moore_machine" rel="noopener ugc"><strong>Moore</strong></a> and <a target="_blank" href="https://en.wikipedia.org/wiki/Mealy_machine" rel="noopener ugc"><strong>Mealy</strong></a> types.</p> 86<p>They are only different in the form of their output relation Ï. Our transducer definition above is a Mealy Transducer, because its output relation Ï depends on the state and Command as inputs, while a Moore Transducer's output relation would only depend on the state, and not the Command.</p> 87<ul> 88<li><strong>Moore</strong> form: <strong>Ï : S â E</strong> (Event generation depends only on state)</li> 89<li><strong>Mealy</strong> form: <strong>Ï : S x C â E</strong> (Event generation depends on Commands and state combined)</li> 90</ul> 91<h2 id="heading-example-designing-a-user-registration-process">Example: Designing a User Registration Process</h2> 92<p>Letâs assume we have had a great Event Storming session and are now trying to apply the math to the crunched knowledge of a specific problem â a User Registration process. We have to define the Commands, States, Behaviors and the Events that should be written to the output in response to a specific Behavior. Since we have chosen Event Storming as our collaboration method of choice we'll start with the Events.</p> 93<h3 id="heading-speaking-the-event-language">Speaking the Event language!</h3> 94<p>We start with building our Event language.</p> 95<ul> 96<li><p><strong>Confirmation was sent</strong></p> 97<p>After having started the registration we want to make sure that the customer really has access to the provided email address, hence we send out a confirmation via email with a confirmation link.</p> 98</li> 99<li><p><strong>Confirmation resent</strong></p> 100<p>When the confirmation has expired we want to enable our customers to easily resend the confirmation, maybe the previous mail was caught by a spam filter.</p> 101</li> 102<li><p><strong>Account was confirmed</strong></p> 103<p>When the confirmation was completed by the customer we say that the account is now confirmed.</p> 104</li> 105<li><p><strong>Account was deleted through a GDPR request</strong></p> 106<p>We are bound by European laws to delete all personal data.</p> 107</li> 108</ul> 109<p><em>It follows that:</em></p> 110<p>\[
111E = \{\small{ConfirmationSent},\small{ConfirmationResent},\small{AccountConfirmed},\small{AccountDeleted}\} 112\]</p> 113<h3 id="heading-thou-command-shall-be-my-duty">Thou Command shall be my duty!</h3> 114<p>We have designed the following Commands analogous to our Events:</p> 115<ul> 116<li><strong>Start registration</strong></li> 117<li><strong>Confirm account</strong></li> 118<li><strong>Resend confirmation</strong></li> 119<li><strong>Fulfill GDPR request</strong></li> 120</ul> 121<p><em>It follows that:</em></p> 122<p>\[ 123C = \{\small{StartRegistration},\small{ConfirmAccount},\small{ResendConfirmation},\small{FulfillGDPRRequest}\} 124\]</p> 125<h3 id="heading-designing-the-states">Designing the States</h3> 126<p>Remember that we have a principle that should always be on our mind when designing State:</p> 127<blockquote> 128<p>The states should consist of the smallest amount of information that together with the knowledge of the input can determine the output.</p> 129</blockquote> 130<p>Our goal is to find the minimum required amount of information to enable suitable reactions. Here less is always more.</p> 131<p>This example is not focusing on managing data, but it is possible to define properties on states â this will not have an effect on the general formulas.</p> 132<ul> 133<li><p><strong>Potential customer</strong></p> 134<p>This is our initial state \(PotentialCustomer \in S_0\). Any unregistered customer is a potential!</p> 135</li> 136<li><p><strong>Requires confirmation</strong></p> 137</li> 138<li><strong>Active</strong></li> 139<li><p><strong>Deleted</strong></p> 140<p>This is a final state \(Deleted \in F\)</p> 141</li> 142</ul> 143<p><em>It follows that:</em></p> 144<p>\[ 145S = \{ 146\small{PotentialCustomer}, 147\small{RequiresConfirmation}, 148\small{Active}, 149\small{Deleted} 150\} 151\]</p> 152<p>and</p> 153<p>$$ 154S_0 = \{\\ 155\small{PotentialCustomer} 156\} 157$$</p> 158<p>and</p> 159<p>$$ 160F = \{\\ 161\small{Deleted} 162\} 163$$</p> 164<h3 id="heading-how-should-we-react">How should we react?</h3> 165<p>The last thing we need is to define our Behavior (δ) and Event (Ï) functions.</p> 166<pre><code class="lang-text">δ : S x C â S = { 167 (PotentialCustomer, StartRegistration) â RequiresConfirmation, 168 (RequiresConfirmation, ResendConfirmation) â RequiresConfirmation, 169 (RequiresConfirmation, ConfirmAccount) â Confirmed, 170 (Active, FulfillGDPRRequest) â Deleted, 171 (RequiresConfirmation, FulfillGDPRRequest) â Deleted 172} 173</code></pre> 174<p>and</p> 175<pre><code class="lang-text">Ï : S x C â E = { 176 (PotentialCustomer, StartRegistration) â ConfirmationSent, 177 (RequiresConfirmation, ResendConfirmation) â ConfirmationResent, 178 (RequiresConfirmation, ConfirmAccount) â AccountConfirmed, 179 (Active, FulfillGDPRRequest) â AccountDeleted, 180 (RequiresConfirmation, FulfillGDPRRequest) â ϵ, 181} 182</code></pre> 183<p>The ϵ here is special. It says that there is no output for this specific Command-State pair. We will learn more about ϵ and ways we can model handling errors in the next post of this series.</p> 184<h3 id="heading-construction-of-our-transducer-aggregate">Construction of our Transducer Aggregate!</h3> 185<p>Now we can finally construct our User Registration Aggregate (or rather non-deterministic Finite-State Transducer) as:</p> 186<p>\[ 187T = \Big(S, C, E, \delta, \omega, \{PotentialCustomer\}, \{Deleted\} \Big) 188\]</p> 189<p>and send the following Commands to it:</p> 190<p>$$ 191C = \{\small{StartRegistration},\small{ResendConfirmation},\small{ConfirmAccount},\small{FulfillGDPRRequest}\} 192$$</p> 193<p>In response we will receive the following Events:</p> 194<p>$$ 195E = \{\small{ConfirmationSent},\small{ConfirmationResent},\small{AccountConfirmed},\small{AccountDeleted}\} 196$$</p> 197<h4 id="heading-exercise">Exercise</h4> 198<p>Given the following commands:</p> 199<p>$$ 200C = \{\small{StartRegistration},\small{ResendConfirmation},\small{FulfillGDPRRequest}\} 201$$</p> 202<ol> 203<li>Which sequence of events would we get?</li> 204<li>Which state is produced?</li> 205</ol> 206<h2 id="heading-conclusions">Conclusions</h2> 207<ul> 208<li>We have learned that process-oriented, temporal models are a great match when dealing with the behaviors of complex systems â and how collaborative modelling techniques have shaped our understanding of these systems.</li> 209<li>We looked into the past of computing advances to rediscover automata theory as a means to model processes, explored different types of machines (FSA, DFA, NDFA, FST) and mapped these to desired properties of temporal Aggregate design.</li> 210<li>We put the math to action and designed a an User Registration Aggregate as a concrete example.</li> 211</ul> 212<h2 id="heading-whats-next">Whatâs next?</h2> 213<p>
213In the next post of the series we will cover the following topics:</p> 214<ul> 215<li>Learning about <em>Accpetors</em> and <em>Sequencers</em></li> 216<li>Exploring generic operations on FSAs like <em>unions</em>, <em>concatenations</em> and <em>projections</em>.</li> 217<li>Using these operations to naturally transform our current User Registration example into an event-sourced model.</li> 218</ul> 219<h2 id="heading-personal-note">Personal note</h2> 220<p>These posts are a try to summarize my personal thoughts about this topic for quite some time. I encourage everyone to challenge me on these ideas, and I am the last one to claim that this is the right way to think about these problems.</p> 221<p>The hope I have is that readers have fun following me through my thinking process!</p> 222<p>Thank you.</p> 223<p><em>This article was originally published on Medium, but unfortunately I don't want to support or use Medium as a publishing platform. Hence I am moving my blog posts to hashnode. The original article can be found <a target="_blank" href="https://medium.com/@tPl0ch/domain-driven-design-a-mathematical-model-for-process-oriented-aggregates-pt-i-6aecc8957865" rel="noopener ugc">here</a>.</em></p> 224</div></div></div></div><div class="max-w-2xl mx-auto border-t border-border pt-8 space-y-5"><div class="flex flex-wrap items-center gap-2"><a class="inline-flex items-center gap-1.5 rounded-full border border-border px-3 py-1 text-sm text-muted-foreground transition hover:border-primary hover:text-primary" href="/tag/ddd">#<!-- -->ddd</a><a class="inline-flex items-center gap-1.5 rounded-full border border-border px-3 py-1 text-sm text-muted-foreground transition hover:border-primary hover:text-primary" href="/tag/functional-programming">#<!-- -->functional-programming</a><a class="inline-flex items-center gap-1.5 rounded-full border border-border px-3 py-1 text-sm text-muted-foreground transition hover:border-primary hover:text-primary" href="/tag/computer-science">#<!-- -->computer-science</a></div></div></div></article></div></div></div></section><section class="pb-8"><div class="px-4 sm:px-8"><div class="w-full max-w-full xl:mx-auto xl:max-w-[80rem] 2xl:max-w-[90rem]"><div class="max-w-4xl w-full mx-auto"><div class="rounded-xl border bg-card text-card-foreground p-5 sm:p-8"><section class="space-y-5"><div class="flex items-center justify-between"><h2 class="text-lg font-bold tracking-tight">Comments<!-- --> (1)</h2><a target="_blank" rel="noopener" class="inline-flex items-center gap-2 rounded-md border border-border px-3 py-1.5 text-sm font-medium text-foreground transition hover:border-primary hover:text-primary" href="https://hashnode.com/posts/ddd-aggregates-processes-state-machines-and-transducers/61d183fa0cfc5655c184620c"><i class="fa-regular fa-comment" aria-hidden="true"></i>Join the discussion</a></div><div class="space-y-5"><div class="space-y-3"><div class=""><div class="flex gap-3"><a target="_blank" rel="noopener" class="shrink-0" href="https://hashnode.com/@tonivj5"><span class="relative flex shrink-0 overflow-hidden rounded-full h-8 w-8 border border-border transition-opacity hover:opacity-80"><span class="flex h-full w-full items-center justify-center rounded-full bg-muted text-muted-foreground font-semibold text-sm">T</span></span></a><div class="min-w-0 flex-1"><div class="flex items-center gap-2 text-sm"><a target="_blank" rel="noopener" class="font-medium text-foreground hover:text-primary transition-colors" href="https://hashnode.com/@tonivj5">Toni Villena</a><span class="text-muted-foreground">4y ago</span></div><div class="mt-1 text-sm text-foreground prose dark:prose-invert prose-sm max-w-none [&>p]:my-1 [&>p:first-child]:mt-0 [&>p:last-child]:mb-0"><p>very interesting, waiting for the second part! :-D</p> 225</div></div></div></div></div></div></section></div></div></div></div></section><section class="pb-8"><div class="px-4 sm:px-8"><div class="w-full max-w-full xl:mx-auto xl:max-w-[80rem] 2xl:max-w-[90rem]"><div class="max-w-4xl w-full mx-auto"><div class="rounded-xl border bg-card text-card-foreground overflow-hidden"><div class="p-5 sm:p-6 space-y-3"><a class="group flex items-center gap-2" href="/series/process-aggregates"><i class="fa-jelly fa-layer-group h-4 w-4 text-muted-foreground" aria-hidden="true"></i><h2 class="text-base font-semibold leading-snug tracking-tight text-foreground group-hover:text-primary transition-colors">Domain-Driven Design: A mathematical model for process-oriented Aggregates</h2></a><div class="flex items-center gap-3 text-sm text-muted-foreground"><span>Part <!-- -->1<!-- --> of <!-- -->1</span><div class="flex-1 h-1 rounded-full bg-muted overflow-hidden"><div class="h-full rounded-full bg-primary transition-all" style="width:100%"></div></div></div><p class="text-sm leading-relaxed text-muted-foreground line-clamp-2">In this series I want to exploit theorems from automata theory to formally define the Domain-Driven Design Aggregate pattern.</p></div></div></div></div></div></section>
225<script type="application/ld+json">{"@context":"https://schema.org","@type":"Article","url":"https://t-pl.io/ddd-aggregates-processes-state-machines-and-transducers","mainEntityOfPage":"https://t-pl.io/ddd-aggregates-processes-state-machines-and-transducers","headline":"DDD Aggregates: Processes, State Machines and Transducers","description":"This blog post is the first one in a series of three posts in which we try to derive a mathematical model for process-oriented Domain-Driven Design (DDD) Aggregates.\nThe need for process-oriented models\nIn order to understand this need we need to div...","author":{"@type":"Person","name":"Thomas Ploch","url":"https://hashnode.com/@tPl0ch","image":"https://cdn.hashnode.com/res/hashnode/image/upload/v1640931885215/4AIFHuTXb.jpeg","sameAs":"https://x.com/tPl0ch"},"publisher":{"@type":"Organization","name":"Thomas Ploch's Blog - Systems, People & Technology","url":"https://t-pl.io"},"datePublished":"2022-01-02T10:52:42.124Z","dateModified":"2022-01-14T13:34:29.696Z","image":{"@type":"ImageObject","url":"https://cdn.hashnode.com/res/hashnode/image/unsplash/aQYgUYwnCsM/upload/v1641121050901/_cvnyJNXU.jpeg"},"keywords":"DDD, Functional Programming, Computer Science"}</script>
225<footer class="px-4 pt-8 pb-20 sm:px-8 text-muted-foreground" aria-label="Footer"><div class="w-full max-w-4xl mx-auto"><div class="flex flex-col items-center gap-4 text-center text-sm"><p class="font-medium"><time dateTime="2026"><span class="font-sans">©</span> <!-- -->2026</time> <!-- -->Thomas Ploch's Blog - Systems, People & Technology</p><nav aria-label="Footer navigation"><ul class="flex flex-wrap justify-center gap-4 text-sm tracking-wide"><li><a class="transition hover:text-foreground" href="/archive">Archive</a></li><li><a class="transition hover:text-foreground" target="_blank" rel="noopener" href="https://hashnode.com/privacy-policy">Privacy</a></li><li><a class="transition hover:text-foreground" target="_blank" rel="noopener" href="https://hashnode.com/terms">Terms</a></li></ul></nav><div class="pt-8 flex justify-center gap-6"><a target="_blank" rel="noopener" class="flex items-center gap-2 text-sm transition hover:text-foreground" title="Sitemap" href="/sitemap.xml"><i class="fa-regular fa-sitemap"></i><span>Sitemap</span></a><a target="_blank" rel="noopener" class="flex items-center gap-2 text-sm transition hover:text-foreground" title="RSS Feed" href="/rss.xml"><i class="fa-regular fa-rss"></i><span>RSS</span></a></div><div class="pt-10 text-center"><a target="_blank" rel="noopener" aria-label="Visit Hashnode (opens in a new tab)" class="inline-flex items-center justify-center gap-2 whitespace-nowrap font-medium transition-colors focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 hover:bg-accent hover:text-accent-foreground h-10 rounded-md text-xl px-5 py-4" href="https://hashnode.com/?utm_source=https%3A%2F%2Ft-pl.io&utm_medium=referral&utm_campaign=blog_footer_logo&utm_content=logo"><svg fill="none" viewBox="0 0 282 39" aria-hidden="true" class="h-6 w-auto min-w-[9.5rem] text-muted-foreground transition hover:text-foreground"><path fill="currentColor" d="M2.68 13.032c-3.573 3.505-3.573 9.363 0 12.936L13.032 36.32c3.505 3.573 9.363 3.573 12.936 0L36.32 25.968c3.573-3.573 3.573-9.431 0-12.936L25.968 2.68c-3.573-3.573-9.431-3.573-12.936 0zm12.211 1.935c2.507-2.521 6.582-2.544 9.104-.038s2.544 6.582.038 9.104-6.582 2.544-9.104.038-2.544-6.582-.038-9.104"></path><path fill="currentColor" d="M268.379 39q-6.322 0-10.35-4.108-4.002-4.134-4.002-10.483 0-6.296 4.002-10.43 4-4.135 10.163-4.135 6.028 0 9.817 3.734 3.814 3.735 3.814 9.497v2.8h-24.248v-4.054h17.633q-.187-2.747-2.054-4.508-1.868-1.76-4.962-1.76-3.28-.001-5.388 2.374-2.108 2.373-2.108 6.375 0 4.188 2.348 6.695 2.347 2.481 5.895 2.481 1.68 0 2.934-.453a8.5 8.5 0 0 0 2.321-1.307q1.041-.854 2.268-2.614l4.694 2.96q-1.707 2.748-3.494 4.135a12.7 12.7 0 0 1-3.975 2.081q-2.187.72-5.308.72m-33.496 0q-5.575 0-9.283-4.028-3.681-4.029-3.681-10.484 0-6.43 3.761-10.51 3.76-4.108 9.47-4.108 2.8 0 5.175 1.2 2.4 1.174 3.628 3.148l.026-.08V0h7.016v38.2h-6.722v-4.722l.64.8-.694.133q-1.28 2.108-3.788 3.361Q237.924 39 234.883 39m1.627-6.002q3.308 0 5.495-2.428t2.188-6.135q0-3.762-2.214-6.109-2.214-2.374-5.469-2.374-3.28 0-5.522 2.347-2.214 2.348-2.214 6.163 0 3.76 2.214 6.162 2.214 2.374 5.522 2.374M205.811 39q-6.376 0-10.537-4.161-4.161-4.188-4.161-10.404 0-6.321 4.161-10.456 4.188-4.135 10.537-4.135 6.348 0 10.537 4.161 4.188 4.161 4.188 10.43 0 6.216-4.188 10.404Q212.186 39 205.811 39m0-6.162q3.307 0 5.575-2.374 2.267-2.374 2.267-6.055 0-3.707-2.294-6.056-2.267-2.347-5.548-2.347-3.308 0-5.575 2.374-2.268 2.348-2.268 6.029t2.241 6.055q2.268 2.374 5.602 2.374M162.586 38.2V10.644h6.802v5.015l-.8-.987h.906q1.308-2.187 3.762-3.494 2.48-1.335 5.228-1.334 4.615 0 7.256 2.8 2.667 2.776 2.667 7.603V38.2h-7.069V21.794q0-2.854-1.387-4.401t-4.134-1.547q-2.614 0-4.402 1.974-1.76 1.974-1.76 4.881V38.2zm-30.181 0V0h6.962v14.698h.134q1.2-2.187 3.574-3.521 2.375-1.335 5.229-1.334 4.615 0 7.255 2.828 2.668 2.801 2.668 7.522V38.2h-7.069V21.794q0-2.827-1.387-4.402-1.387-1.573-4.055-1.573-2.587 0-4.428 2.027-1.814 2.027-1.814 4.962v15.391zm-14.416.8q-2.882 0-5.015-.64-2.108-.614-3.761-1.84-1.654-1.228-2.668-2.695l-.987-1.467 4.695-3.174.773 1.067a9.1 9.1 0 0 0 1.788 1.814 8.2 8.2 0 0 0 2.32 1.2q1.308.4 3.068.4 2.161 0 3.441-.8 1.308-.8 1.307-2.294 0-1.36-1.147-2.108-1.12-.747-5.068-1.654-5.335-1.253-7.656-3.334-2.32-2.107-2.321-5.362 0-3.76 3.148-6.002 3.148-2.267 7.923-2.267 2.454 0 4.348.507t3.388 1.493q1.493.988 2.454 2.188l.987 1.2-4.482 3.255-.667-.774a7.4 7.4 0 0 0-1.627-1.387 6.4 6.4 0 0 0-2.054-.88 9.5 9.5 0 0 0-2.401-.294q-1.974 0-3.201.8-1.2.774-1.2 1.921 0 1.254 1.12 2.027 1.147.748 5.229 1.681 5.334 1.227 7.629 3.308 2.294 2.055 2.294 5.308 0 4.029-3.228 6.43Q123.217 39 117.989 39M87.61 39q-4.508 0-7.335-2.454-2.828-2.481-2.828-6.482 0-4.188 3.254-6.669t8.483-2.48q2.082 0 4.028.426 1.974.427 3.361 1.12v-1.6q0-2.588-1.813-4.082-1.788-1.493-4.615-1.493-1.628 0-2.801.373a8.7 8.7 0 0 0-2.188.987q-.987.614-1.84 1.414l-.854.8-4.081-3.788 1.307-1.173a18.7 18.7 0 0 1 2.934-2.108q1.601-.933 3.601-1.44t4.589-.507q5.868 0 9.229 2.88 3.361 2.882 3.361 8.084V38.2h-6.749v-5.922l1.654 2.187h-1.76q-1.308 2.055-3.655 3.308Q90.545 39 87.611 39m1.814-4.988q3.148 0 5.149-2.187 2-2.215 2-5.309v-.08q-1.12-.693-2.72-1.094a13 13 0 0 0-3.388-.426q-2.828 0-4.562 1.2-1.734 1.173-1.734 3.521 0 2.028 1.468 3.201t3.787 1.174M49 38.2V0h6.962v14.698h.134q1.2-2.187 3.574-3.521 2.375-1.335 5.229-1.334 4.615 0 7.255 2.828 2.668 2.801 2.668 7.522V38.2h-
2257.07V21.794q0-2.827-1.386-4.402-1.387-1.573-4.055-1.573-2.587 0-4.428 2.027-1.815 2.027-1.814 4.962v15.391z"></path></svg></a></div></div></div></footer></main><!--$--><!--/$-->
225<script src="/_next/static/chunks/webpack-55b36f0cd6c208fe.js" id="_R_" async=""></script>
225<script>(self.__next_f=self.__next_f||[]).push([0])</script>
225<script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[16174,[\"4554\",\"static/chunks/4554-984b480a9db5f3fe.js\",\"7563\",\"static/chunks/7563-4dfa0994a9b0e37c.js\",\"9216\",\"static/chunks/9216-9272709ba40c1cfd.js\",\"2810\",\"static/chunks/2810-6b74d77b4b0dc790.js\",\"3091\",\"static/chunks/3091-bf1537ff6571a1bd.js\",\"7177\",\"static/chunks/app/layout-6ae7b4b583d4bba3.js\"],\"ThemeProvider\"]\n3:I[82180,[\"4554\",\"static/chunks/4554-984b480a9db5f3fe.js\",\"7563\",\"static/chunks/7563-4dfa0994a9b0e37c.js\",\"9216\",\"static/chunks/9216-9272709ba40c1cfd.js\",\"2810\",\"static/chunks/2810-6b74d77b4b0dc790.js\",\"3091\",\"static/chunks/3091-bf1537ff6571a1bd.js\",\"7177\",\"static/chunks/app/layout-6ae7b4b583d4bba3.js\"],\"TooltipProvider\"]\n4:I[63851,[\"4554\",\"static/chunks/4554-984b480a9db5f3fe.js\",\"7563\",\"static/chunks/7563-4dfa0994a9b0e37c.js\",\"9216\",\"static/chunks/9216-9272709ba40c1cfd.js\",\"2810\",\"static/chunks/2810-6b74d77b4b0dc790.js\",\"3091\",\"static/chunks/3091-bf1537ff6571a1bd.js\",\"7177\",\"static/chunks/app/layout-6ae7b4b583d4bba3.js\"],\"UrqlProvider\"]\n5:I[82714,[\"4554\",\"static/chunks/4554-984b480a9db5f3fe.js\",\"7563\",\"static/chunks/7563-4dfa0994a9b0e37c.js\",\"9216\",\"static/chunks/9216-9272709ba40c1cfd.js\",\"2810\",\"static/chunks/2810-6b74d77b4b0dc790.js\",\"3091\",\"static/chunks/3091-bf1537ff6571a1bd.js\",\"7177\",\"static/chunks/app/layout-6ae7b4b583d4bba3.js\"],\"ConsentManager\"]\n6:I[9766,[],\"\"]\n7:I[98924,[],\"\"]\n8:I[33293,[\"4554\",\"static/chunks/4554-984b480a9db5f3fe.js\",\"4345\",\"static/chunks/app/not-found-b861935655c5698b.js\"],\"default\"]\n9:I[21447,[\"4554\",\"static/chunks/4554-984b480a9db5f3fe.js\",\"7563\",\"static/chunks/7563-4dfa0994a9b0e37c.js\",\"9216\",\"static/chunks/9216-9272709ba40c1cfd.js\",\"2810\",\"static/chunks/2810-6b74d77b4b0dc790.js\",\"3091\",\"static/chunks/3091-bf1537ff6571a1bd.js\",\"7177\",\"static/chunks/app/layout-6ae7b4b583d4bba3.js\"],\"Integrations\"]\na:I[35514,[\"4554\",\"static/chunks/4554-984b480a9db5f3fe.js\",\"7563\",\"static/chunks/7563-4dfa0994a9b0e37c.js\",\"9216\",\"static/chunks/9216-9272709ba40c1cfd.js\",\"2810\",\"static/chunks/2810-6b74d77b4b0dc790.js\",\"3091\",\"static/chunks/3091-bf1537ff6571a1bd.js\",\"7177\",\"static/chunks/app/layout-6ae7b4b583d4bba3.js\"],\"Analytics\"]\nc:I[24431,[],\"OutletBoundary\"]\ne:I[15278,[],\"AsyncMetadataOutlet\"]\n10:I[24431,[],\"ViewportBoundary\"]\n12:I[24431,[],\"MetadataBoundary\"]\n13:\"$Sreact.suspense\"\n15:I[57150,[],\"\"]\n:HL[\"/_next/static/media/22a5144ee8d83bca-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/72a2a501b11d0ccb.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/8934b430a4adeb19-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/8e9860b6e62d6359-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/c4b700dcb2187787-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/e4af272ccee01ff0-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/css/0d16c72050851854.css\",\"style\"]\n:HL[\"/_next/static/css/7ffcc02a3c67389b.css\",\"style\"]\n:HL[\"/_next/static/css/c20e76e7d11dec32.css\",\"style\"]\n:HL[\"/_next/static/css/59fefb2212bd5b60.css\",\"style\"]\n0:{\"P\":null,\"b\":\"RrCGzNVHUG674hJ_sjvms\",\"p\":\"\",\"c\":[\"\",\"ddd-aggregates-processes-state-machines-and-transducers?x-host=t-pl.io\"],\"i\":false,\"f\":[[[\"\",{\"children\":[[\"slug\",\"ddd-aggregates-processes-state-machines-and-transducers\",\"c\"],{\"children\":[\"__PAGE__?{\\\"x-host\\\":\\\"t-pl.io\\\"}\",{}]}]},\"$undefined\",\"$undefined\",true],[\"\",[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/0d16c72050851854.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"link\",\"1\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/7ffcc02a3c67389b.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"link\",\"2\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/c20e76e7d11dec32.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"link\",\"3\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/59fefb2212bd5b60.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"l"])</script>
225<script>self.__next_f.push([1,"ang\":\"en\",\"suppressHydrationWarning\":true,\"children\":[[\"$\",\"head\",null,{\"children\":[\"$\",\"script\",null,{\"type\":\"text/javascript\",\"dangerouslySetInnerHTML\":{\"__html\":\"window.addEventListener('message',function(e){var d=e.data;if(!d||d.__hnWidget!==1||typeof d.h!=='number'||d.h\u003c=0)return;var f=document.querySelectorAll('.hn-widget-frame');for(var i=0;i\u003cf.length;i++){if(f[i].contentWindow===e.source){f[i].style.height=d.h+'px';break;}}});\"}}]}],[\"$\",\"body\",null,{\"className\":\"__variable_c2612a __variable_246ccd __variable_3069d5 bg-background dark:bg-background\",\"children\":[\"$\",\"$L2\",null,{\"attribute\":\"class\",\"defaultTheme\":\"system\",\"enableSystem\":true,\"disableTransitionOnChange\":true,\"children\":[\"$\",\"$L3\",null,{\"children\":[\"$\",\"$L4\",null,{\"children\":[\"$\",\"$L5\",null,{\"children\":[[\"$\",\"$L6\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L7\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[\"$\",\"$L8\",null,{}],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}],[\"$\",\"$L9\",null,{}],[\"$\",\"$La\",null,{}]]}]}]}]}]}]]}]]}],{\"children\":[[\"slug\",\"ddd-aggregates-processes-state-machines-and-transducers\",\"c\"],[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L6\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L7\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[\"__PAGE__\",[\"$\",\"$1\",\"c\",{\"children\":[\"$Lb\",null,[\"$\",\"$Lc\",null,{\"children\":[\"$Ld\",[\"$\",\"$Le\",null,{\"promise\":\"$@f\"}]]}]]}],{},null,false]},null,false]},null,false],[\"$\",\"$1\",\"h\",{\"children\":[null,[[\"$\",\"$L10\",null,{\"children\":\"$L11\"}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]],[\"$\",\"$L12\",null,{\"children\":[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$13\",null,{\"fallback\":null,\"children\":\"$L14\"}]}]}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$15\",[]],\"s\":false,\"S\":false}\n11:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\nd:null\n16:I[80622,[],\"IconMark\"]\nf:{\"metadata\":[[\"$\",\"title\",\"0\",{\"children\":\"DDD Aggregate pattern: Processes, State Machines and Transducers\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"An introduction to designing the Domain-Driven Design Aggregate pattern via first principles from automata theory\"}],[\"$\",\"meta\",\"2\",{\"name\":\"google-site-verification\",\"content\":\"K1pB_brVgJW4jSA9hhYdMxGuyiR0EK0Pfzi6nWEH8OE\"}],[\"$\",\"link\",\"3\",{\"rel\":\"canonical\",\"href\":\"https://t-pl.io/ddd-aggregates-processes-state-machines-and-transducers\"}],[\"$\",\"meta\",\"4\",{\"property\":\"og:title\",\"content\":\"DDD Aggregate pattern: Processes, State Machines and Transducers\"}],[\"$\",\"meta\",\"5\",{\"property\":\"og:description\",\"content\":\"An introduction to designing the Domain-Driven Design Aggregate pattern via first principles from automata theory\"}],[\"$\",\"meta\",\"6\",{\"property\":\"og:url\",\"content\":\"https://t-pl.io/ddd-aggregates-processes-state-machines-and-transducers\"}],[\"$\",\"meta\",\"7\",{\"property\":\"og:site_name\",\"content\":\"Thomas Ploch's Blog - Systems, People \u0026 Technology\"}],[\"$\",\"meta\",\"8\",{\"property\":\"og:image\",\"content\":\"https://cdn.hashnode.com/res/hashnode/image/unsplash/aQYgUYwnCsM/upload/v1641121050901/_cvnyJNXU.jpeg\"}],[\"$\",\"meta\",\"9\",{\"property\":\"og:image:width\",\"content\":\"1200\"}],[\"$\",\"meta\",\"10\",{\"property\":\"og:image:height\",\"content\":\"630\"}],[\"$\",\"meta\",\"11\",{\"property\":\"og:type\",\"content\":\"article\"}],[\"$\",\"meta\",\"12\",{\"property\":\"article:published_time\",\"content\":\"2022-01-02T10:52:42.124Z\"}],[\"$\",\"meta\",\"13\",{\"property\":\"article:modified_time\",\"content\":\"2022-01-14T13:34:29.696Z\"}],[\"$\",\"meta\",\"14\",{\"property\":\"article:author\",\"content\":\"https://t-pl.i
225o/@tPl0ch\"}],[\"$\",\"meta\",\"15\",{\"name\":\"twitter:card\",\"content\":\"summary_large_image\"}],[\"$\",\"meta\",\"16\",{\"name\":\"twitter:creator\",\"content\":\"https://twitter.com/tPl0ch\"}],[\"$\",\"meta\",\"17\",{\"name\":\"twitter:title\",\"content\":\"DDD Aggregate patte"])</script>
225<script>self.__next_f.push([1,"rn: Processes, State Machines and Transducers\"}],[\"$\",\"meta\",\"18\",{\"name\":\"twitter:description\",\"content\":\"An introduction to designing the Domain-Driven Design Aggregate pattern via first principles from automata theory\"}],[\"$\",\"meta\",\"19\",{\"name\":\"twitter:image\",\"content\":\"https://cdn.hashnode.com/res/hashnode/image/unsplash/aQYgUYwnCsM/upload/v1641121050901/_cvnyJNXU.jpeg\"}],[\"$\",\"link\",\"20\",{\"rel\":\"icon\",\"href\":\"/favicon.ico\"}],[\"$\",\"$L16\",\"21\",{}]],\"error\":null,\"digest\":\"$undefined\"}\n14:\"$f:metadata\"\n17:I[652,[\"4554\",\"static/chunks/4554-984b480a9db5f3fe.js\",\"7563\",\"static/chunks/7563-4dfa0994a9b0e37c.js\",\"5001\",\"static/chunks/5001-fae0bebdd93f95e3.js\",\"2423\",\"static/chunks/2423-c8b1388240338d7d.js\",\"9216\",\"static/chunks/9216-9272709ba40c1cfd.js\",\"3091\",\"static/chunks/3091-bf1537ff6571a1bd.js\",\"652\",\"static/chunks/652-f40dcb480b4e356f.js\",\"730\",\"static/chunks/730-8191af9e9424b148.js\",\"8974\",\"static/chunks/app/page-cc18ae1a3a7a5ed8.js\"],\"BlogHeader\"]\n18:T441f,\u003cp\u003eThis blog post is the first one in a series of three posts in which we try to derive a mathematical model for process-oriented Domain-Driven Design (DDD) Aggregates.\u003c/p\u003e\n\u003ch2 id=\"heading-the-need-for-process-oriented-models\"\u003eThe need for process-oriented models\u003c/h2\u003e\n\u003cp\u003eIn order to understand this need we need to dive into complex systems theory. Donât worry, we will not dive deep!\u003c/p\u003e\n\u003cp\u003eNot surprisingly software is not an isolated artifact. It must be embedded into the socio-technical context of the people that use and produce it, paired with the constant interactions of the environment. What we need to know is how complex systems show the behaviors that we, as system designers, try to capture in useful abstractions.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e\u003cstrong\u003eOrganizations are dynamic, hierarchically structured entities. Such dynamism is reflected in the emergence of significant events at every organizational level.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e\u003ca target=\"_blank\" href=\"https://www.researchgate.net/publication/272427231_Event_System_Theory_An_Event-Oriented_Approach_to_the_Organizational_Sciences\"\u003e[Morgeson F., Mitchell T., Liu D. 2015. Event System Theory: An Event-Oriented Approach To The Origanisational Sciences]\u003c/a\u003e\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eWe will call these patterns of events \u003cstrong\u003eprocesses\u003c/strong\u003e. These processes emerge in systems to achieve something, be it selling books online or providing restaurants with seat reservations. A large research topic termed process theories is trying to understand how patterns of events lead to positive outcomes. Ultimately they are \u003cstrong\u003eâstories about what happened and who did what when â that is, events, activities, and choices ordered over timeâ\u003c/strong\u003e \u003ca target=\"_blank\" href=\"https://www.jstor.org/stable/259349?seq=1#page_scan_tab_contents\"\u003e[Langley, A. 1999. Strategies for theorizing from process data]\u003c/a\u003e.\u003c/p\u003e\n\u003ch3 id=\"heading-the-rise-of-collaborative-temporal-modelling\"\u003eThe rise of collaborative temporal modelling\u003c/h3\u003e\n\u003cp\u003eOver the past years new practices to capture these processes emerged. Event Storming, Story Mapping or Domain Story Telling are all examples of approaches to recognize that understanding the repeating patterns of events can give us a great leverage in designing working solutions. These results regularly have a much larger overlap with the organizational reality than traditional static modelling techniques.\u003c/p\u003e\n\u003cp\u003eTemporal modelling also had an effect on the tactical design choices that experienced DDD practitioners make when working with Aggregates. Aggregates are then defined as a combination of \u003cstrong\u003eCommands\u003c/strong\u003e (stimuli from the environment), \u003cstrong\u003eBehaviors\u003c/strong\u003e (reactions to incoming stimuli that can change the systemâs response mechanisms) and \u003cstrong\u003eEvents\u003c/strong\u003e (system signals in response to changes in system state). The âEvent Sourcingâ pattern for example builds on these fundamental design choices to make the time-ordered â hence âtemporalâ â patterns of events the central element of its design.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eIf we can define some Aggregates by time-ordered series of e"])</script>
225<script>self.__next_f.push([1,"vents, then it follows that these Aggregates are also processes.\u003c/strong\u003e\u003c/p\u003e\n\u003ch2 id=\"heading-rediscovering-finite-state-machines\"\u003eRediscovering Finite-State Machines\u003c/h2\u003e\n\u003cp\u003eModelling processes is nothing new in computing. And \u003cstrong\u003eautomata theory\u003c/strong\u003e seems especially interesting:\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eA Finite-State Machine (FSM) formulation is used to describe the processes during which information or tasks move from one state to another for action, according to a set of rules. The states consists of the smallest amount of information that together with the knowledge of the input can determine the output.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eThe terms Automaton and Machine are used interchangeably, so when we talk about FSA, we also mean FSM.\u003c/p\u003e\n\u003cp\u003eTranslated into our process terminology, FSMs process a stream of system stimuli (Commands), enforcing invariants and changing the system state (Behaviors).\u003c/p\u003e\n\u003cp\u003eThe following figure (Fig. 2) shows how the temporal nature of FSMs is driven by the time-ordered and unidirectional stream of Commands.\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"https://cdn.hashnode.com/res/hashnode/image/upload/v1641031481149/N6f766oxh.jpeg\" alt=\"1 Qfbo0Jmfxwoy9tujEhdZ7g.jpg\" /\u003e\u003c/p\u003e\n\u003cp\u003eSince we want to derive a mathematical model, letâs look at the definition of an Finite-State Machine using our previously derived process terminology. An FSM Î is a 5-tuple\u003c/p\u003e\n\u003cp\u003e\\[\nA = \\Big(S, C, \\delta\\colon S \\times C \\to S, S_0\\colon S_0 \\in S, F\\colon F \\subset S \\Big)\n\\]\u003c/p\u003e\n\u003cp\u003ewhere:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eS\u003c/strong\u003e is a non-empty, finite set of states\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eC\u003c/strong\u003e is the \u003cstrong\u003eCommand language\u003c/strong\u003e, a non-empty, finite set of Commands\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eδ\u003c/strong\u003e is the set of \u003cstrong\u003eBehaviors\u003c/strong\u003e â a relation between a state and Command to a state\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eSâ\u003c/strong\u003e is the initial state where Sâ is an element of S\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eF\u003c/strong\u003e is the non-empty, finite set of final states where \u003cstrong\u003eF\u003c/strong\u003e is a subset of \u003cstrong\u003eS\u003c/strong\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eGiven this definition, we will need to derive the command and state alphabets from the domain expertsâ knowledge and then connect the dots via our Behavior functions.\u003c/p\u003e\n\u003ch3 id=\"heading-the-universe-is-a-messy-place\"\u003eThe universe is a messy place\u003c/h3\u003e\n\u003cp\u003eWe love to look for deterministic solutions to problems that are complex and thus non-deterministic by nature. DDD as a modelling approach embraces unexpected behaviors of systems â which is one of the major reasons why I believe applying DDD thinking to complex problems is almost always a good choice. This means that responses to system stimuli are often different depending on the current situation. Imagine yourself as a call-center agent that is suddenly advised to re-route calls for specific topics to supervisors. The world is just not predictable.\nNon-deterministic Finite-State Auatomata (NDFA)\u003c/p\u003e\n\u003cp\u003eIn order to deal with this messy world automata theory offers two distinct types of FSAs that can express these differences â Non-Deterministic (NDFA) and Deterministic (DFA) FSAs. Differences between DFA and NDFAs are subtle. While DFAs have exactly one transition for each state and command pair, NDFAs can have multiple, or even none. Mathematically, they are both equivalent. You can always transform a DFA into an NDFA and back again.\u003c/p\u003e\n\u003cp\u003eBut they do differ between the amount of complexity required to represent them. An NDFA with n states can be transformed into a DFA with up to 2â¿ states. \u003cstrong\u003eFor a decently complicated NDFA of 10 states we would need up to 1024 states in a DFA to represent it!\u003c/strong\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e\u003cstrong\u003eWhen using N
225DFAs you trade determinism for simplicity!\u003c/strong\u003e\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch3 id=\"heading-where-are-the-events\"\u003eWhere are the Events?\u003c/h3\u003e\n\u003cp\u003eIf we recollect the definition of the FSA â which was defined by the Command and state languages paired with the Behaviors â one might recognize that there is currently no way to signal anything back to the systems. So, where are the events?\u003c/p\u003e\n\u003cp\u003eIt seems like a plain NDFA is not enough to "])</script>
225<script>self.__next_f.push([1,"represent our processes. Can automata theory provide another concept that we can use in this case?\u003c/p\u003e\n\u003cp\u003eSpoiler, yes it can!\u003c/p\u003e\n\u003ch2 id=\"heading-introducing-finite-state-transducers-fsts\"\u003eIntroducing Finite-State Transducers (FSTs)\u003c/h2\u003e\n\u003cp\u003eLetâs compare the following schematic diagram of an FST (Fig. 4) with the previous one of an FSM (Fig. 2) and see if we can spot a difference:\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"https://cdn.hashnode.com/res/hashnode/image/upload/v1641115365141/UcZxMwTlj.jpeg\" alt=\"1 oecW_d-OOCvYrzEUd4Awsg.jpg\" /\u003e\u003c/p\u003e\n\u003cp\u003eWe now have an actual output of Events that correspond to the states and Commands that were fed in. Exactly what we need to send our signals out into the world to wreak havoc! Again, letâs have a look at the formal definition of an \u003cstrong\u003eFinite-State Transducer\u003c/strong\u003e. It is a 7-tuple\u003c/p\u003e\n\u003cp\u003e\\[\nA = \\Big(S, C, E, \\delta\\colon S \\times C \\to S, \\omega\\colon S \\times C \\to E, S_0\\colon S_0 \\subset S, F\\colon F \\subset S \\Big)\n\\]\u003c/p\u003e\n\u003cp\u003ewhere:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eS\u003c/strong\u003e is a non-empty, finite set of states\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eC\u003c/strong\u003e is the \u003cstrong\u003eCommand language\u003c/strong\u003e, a non-empty, finite set of Commands\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eE\u003c/strong\u003e is the \u003cstrong\u003eEvent language\u003c/strong\u003e, a non-empty, finite set of Events\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eδ\u003c/strong\u003e is the set of \u003cstrong\u003eBehaviors\u003c/strong\u003e â a relation of a state and Command pair to a state of form \u003cstrong\u003eδ : S x Câ S\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eÏ\u003c/strong\u003e is the \u003cstrong\u003eoutput relation\u003c/strong\u003e of a state and Command pair to an Event of form \u003cstrong\u003eÏ : S x C â E\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eSâ\u003c/strong\u003e is the non-empty, finite set of initial states where \u003cstrong\u003eSâ â S\u003c/strong\u003e (Sâ is a subset of S)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eF\u003c/strong\u003e is the non-empty, finite set of final states where \u003cstrong\u003eF â S\u003c/strong\u003e (F is a subset of S)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eNow that we have Commands, Behaviors and Events we can model our processes as non-deterministic FSTs. Letâs get to action and use the math in an example scenario!\u003c/p\u003e\n\u003ch3 id=\"heading-a-short-excursion-on-the-output-relation-w-omega\"\u003eA short excursion on the output relation Ï (omega)\u003c/h3\u003e\n\u003cp\u003eI quickly want to mention that automata theory differs between two major types of transducers â the \u003ca target=\"_blank\" href=\"https://en.wikipedia.org/wiki/Moore_machine\"\u003e\u003cstrong\u003eMoore\u003c/strong\u003e\u003c/a\u003e and \u003ca target=\"_blank\" href=\"https://en.wikipedia.org/wiki/Mealy_machine\"\u003e\u003cstrong\u003eMealy\u003c/strong\u003e\u003c/a\u003e types.\u003c/p\u003e\n\u003cp\u003eThey are only different in the form of their output relation Ï. Our transducer definition above is a Mealy Transducer, because its output relation Ï depends on the state and Command as inputs, while a Moore Transducer's output relation would only depend on the state, and not the Command.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eMoore\u003c/strong\u003e form: \u003cstrong\u003eÏ : S â E\u003c/strong\u003e (Event generation depends only on state)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMealy\u003c/strong\u003e form: \u003cstrong\u003eÏ : S x C â E\u003c/strong\u003e (Event generation depends on Commands and state combined)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"heading-example-designing-a-user-registration-process\"\u003eExample: Designing a User Registration Process\u003c/h2\u003e\n\u003cp\u003eLetâs assume we have had a great Event Storming session and are now trying to apply the math to the crunched knowledge of a specific problem â a User Registration process. We have to define the Commands, States, Behaviors and the Events that should be written to the output in response to a specific Behavior. Since we have chosen Event Storming as our collaboration method of choice we'll start with the Events.\u003c/p\u003e\n\u003ch3 id=\"heading-speaking-the-event-language\"\u003eSpeaking the Event language!\u003c/h3\u003e\n\u003cp\u003eWe start with building our Event language.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cp\u003e\u003cstrong\u003eConfirmation was sent\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eAfter having started the registration we want to make sure that the customer really has access to the provided email address, hence we send out a confirmation via email with a confirmation link.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cp\u003e\u003cstrong\u003eConfirmation resent\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eWhen the confirmation has expired we want to enable our customers to easily resend the confirmation, maybe t"])</script>
225<script>self.__next_f.push([1,"he previous mail was caught by a spam filter.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cp\u003e\u003cstrong\u003eAccount was confirmed\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eWhen the confirmation was completed by the customer we say that the account is now confirmed.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cp\u003e\u003cstrong\u003eAccount was deleted through a GDPR request\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eWe are bound by European laws to delete all personal data.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cem\u003eIt follows that:\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003e\\[\nE = \\{\\small{ConfirmationSent},\\small{ConfirmationResent},\\small{AccountConfirmed},\\small{AccountDeleted}\\}\n\\]\u003c/p\u003e\n\u003ch3 id=\"heading-thou-command-shall-be-my-duty\"\u003eThou Command shall be my duty!\u003c/h3\u003e\n\u003cp\u003eWe have designed the following Commands analogous to our Events:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eStart registration\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eConfirm account\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eResend confirmation\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eFulfill GDPR request\u003c/strong\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cem\u003eIt follows that:\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003e\\[\nC = \\{\\small{StartRegistration},\\small{ConfirmAccount},\\small{ResendConfirmation},\\small{FulfillGDPRRequest}\\}\n\\]\u003c/p\u003e\n\u003ch3 id=\"heading-designing-the-states\"\u003eDesigning the States\u003c/h3\u003e\n\u003cp\u003eRemember that we have a principle that should always be on our mind when designing State:\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eThe states should consist of the smallest amount of information that together with the knowledge of the input can determine the output.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eOur goal is to find the minimum required amount of information to enable suitable reactions. Here less is always more.\u003c/p\u003e\n\u003cp\u003eThis example is not focusing on managing data, but it is possible to define properties on states â this will not have an effect on the general formulas.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cp\u003e\u003cstrong\u003ePotential customer\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eThis is our initial state \\(PotentialCustomer \\in S_0\\). Any unregistered customer is a potential!\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cp\u003e\u003cstrong\u003eRequires confirmation\u003c/strong\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eActive\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cp\u003e\u003cstrong\u003eDeleted\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eThis is a final state \\(Deleted \\in F\\)\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cem\u003eIt follows that:\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003e\\[\nS = \\{\n\\small{PotentialCustomer},\n\\small{RequiresConfirmation},\n\\small{Active},\n\\small{Deleted}\n\\}\n\\]\u003c/p\u003e\n\u003cp\u003eand\u003c/p\u003e\n\u003cp\u003e$$\nS_0 = \\{\\\\\n\\small{PotentialCustomer}\n\\}\n$$\u003c/p\u003e\n\u003cp\u003eand\u003c/p\u003e\n\u003cp\u003e$$\nF = \\{\\\\\n\\small{Deleted}\n\\}\n$$\u003c/p\u003e\n\u003ch3 id=\"heading-how-should-we-react\"\u003eHow should we react?\u003c/h3\u003e\n\u003cp\u003eThe last thing we need is to define our Behavior (δ) and Event (Ï) functions.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"lang-text\"\u003eδ : S x C â S = {\n (PotentialCustomer, StartRegistration) â RequiresConfirmation,\n (RequiresConfirmation, ResendConfirmation) â RequiresConfirmation,\n (RequiresConfirmation, ConfirmAccount) â Confirmed,\n (Active, FulfillGDPRRequest) â Deleted,\n (RequiresConfirmation, FulfillGDPRRequest) â Deleted\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eand\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"lang-text\"\u003eÏ : S x C â E = {\n (PotentialCustomer, StartRegistration) â ConfirmationSe
225nt,\n (RequiresConfirmation, ResendConfirmation) â ConfirmationResent,\n (RequiresConfirmation, ConfirmAccount) â AccountConfirmed,\n (Active, FulfillGDPRRequest) â AccountDeleted,\n (RequiresConfirmation, FulfillGDPRRequest) â ϵ,\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThe ϵ here is special. It says that there is no output for this specific Command-State pair. We will learn more about ϵ and ways we can model handling errors in the next post of this series.\u003c/p\u003e\n\u003ch3 id=\"heading-construction-of-our-transducer-aggregate\"\u003eConstruction of our Transducer Aggregate!\u003c/h3\u003e\n\u003cp\u003eNow we can finally construct our User Registration Aggregate (or rather non-deterministic Finite-State Transducer) as:\u003c/p\u003e\n\u003cp\u003e\\[\nT = \\Big(S, C, E, \\delta, \\omega, \\{PotentialCustomer\\}, \\{Deleted\\} \\Big)\n\\]\u003c/p\u003e\n\u003cp\u003eand send the following Commands to it:\u003c/p\u003e\n\u003cp\u003e$$\nC = \\{\\small{StartRegistration},\\small{ResendConfirmation},\\small{ConfirmAccount},\\small{FulfillGDPRRequest}\\}\n$$\u003c/p\u003e\n\u003cp\u003eIn response we will receive the following Events:\u003c/p\u003e\n\u003cp\u003e$$\nE = \\{\\small{ConfirmationSent},\\small{ConfirmationResent},\\small{AccountConfirmed},\\small{AccountDeleted}\\}\n$$\u003c/p\u003e\n\u003ch4 id=\"heading-exercise\"\u003eExercise\u003c/h4\u003e\n\u003cp\u003eGiven the following commands:\u003c/p\u003e\n\u003cp\u003e$$\nC = \\{\\smal"])</script>
225<script>self.__next_f.push([1,"l{StartRegistration},\\small{ResendConfirmation},\\small{FulfillGDPRRequest}\\}\n$$\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eWhich sequence of events would we get?\u003c/li\u003e\n\u003cli\u003eWhich state is produced?\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"heading-conclusions\"\u003eConclusions\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eWe have learned that process-oriented, temporal models are a great match when dealing with the behaviors of complex systems â and how collaborative modelling techniques have shaped our understanding of these systems.\u003c/li\u003e\n\u003cli\u003eWe looked into the past of computing advances to rediscover automata theory as a means to model processes, explored different types of machines (FSA, DFA, NDFA, FST) and mapped these to desired properties of temporal Aggregate design.\u003c/li\u003e\n\u003cli\u003eWe put the math to action and designed a an User Registration Aggregate as a concrete example.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"heading-whats-next\"\u003eWhatâs next?\u003c/h2\u003e\n\u003cp\u003eIn the next post of the series we will cover the following topics:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eLearning about \u003cem\u003eAccpetors\u003c/em\u003e and \u003cem\u003eSequencers\u003c/em\u003e\u003c/li\u003e\n\u003cli\u003eExploring generic operations on FSAs like \u003cem\u003eunions\u003c/em\u003e, \u003cem\u003econcatenations\u003c/em\u003e and \u003cem\u003eprojections\u003c/em\u003e.\u003c/li\u003e\n\u003cli\u003eUsing these operations to naturally transform our current User Registration example into an event-sourced model.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"heading-personal-note\"\u003ePersonal note\u003c/h2\u003e\n\u003cp\u003eThese posts are a try to
225summarize my personal thoughts about this topic for quite some time. I encourage everyone to challenge me on these ideas, and I am the last one to claim that this is the right way to think about these problems.\u003c/p\u003e\n\u003cp\u003eThe hope I have is that readers have fun following me through my thinking process!\u003c/p\u003e\n\u003cp\u003eThank you.\u003c/p\u003e\n\u003cp\u003e\u003cem\u003eThis article was originally published on Medium, but unfortunately I don't want to support or use Medium as a publishing platform. Hence I am moving my blog posts to hashnode. The original article can be found \u003ca target=\"_blank\" href=\"https://medium.com/@tPl0ch/domain-driven-design-a-mathematical-model-for-process-oriented-aggregates-pt-i-6aecc8957865\"\u003ehere\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n19:T39ea,This blog post is the first one in a series of three posts in which we try to derive a mathematical model for process-oriented Domain-Driven Design (DDD) Aggregates.\n\n## The need for process-oriented models\n\nIn order to understand this need we need to dive into complex systems theory. Donât worry, we will not dive deep!\n\nNot surprisingly software is not an isolated artifact. It must be embedded into the socio-technical context of the people that use and produce it, paired with the constant interactions of the environment. What we need to know is how complex systems show the behaviors that we, as system designers, try to capture in useful abstractions.\n\n\u003e **Organizations are dynamic, hierarchically structured entities. Such dynamism is reflected in the emergence of significant events at every organizational level.**\n\u003e \n\u003e [\\[Morgeson F., Mitchell T., Liu D. 2015. Event System Theory: An Event-Oriented Approach To The Origanisational Sciences\\]](https://www.researchgate.net/publication/272427231_Event_System_Theory_An_Event-Oriented_Approach_to_the_Organizational_Sciences)\n\nWe will call these patterns of events **processes**. These processes emerge in systems to achieve something, be it selling books online or providing restaurants with seat reservations. A large research topic termed process theories is trying to understand how patterns of events lead to positive outcomes. Ultimately they are **âstories about what happened and who did what when â that is, events, activities, and choices ordered over timeâ** [\\[Langley, A. 1999. Strategies for theorizing from process data\\]](https://www.jstor.org/stable/259349?seq=1#page_scan_tab_contents).\n\n### The rise of collaborative temporal modelling\n\nOver the past years new practices to capture these processes emerged. Event Storming, Story Mapping or Domain Story Telling are all examples of approaches to recognize that understanding the repeating patterns of events can give us a great leverage in designing working solutions. These results regularly have a much larger overla"])</script>
225<script>self.__next_f.push([1,"p with the organizational reality than traditional static modelling techniques.\n\nTemporal modelling also had an effect on the tactical design choices that experienced DDD practitioners make when working with Aggregates. Aggregates are then defined as a combination of **Commands** (stimuli from the environment), **Behaviors** (reactions to incoming stimuli that can change the systemâs response mechanisms) and **Events** (system signals in response to changes in system state). The âEvent Sourcingâ pattern for example builds on these fundamental design choices to make the time-ordered â hence âtemporalâ â patterns of events the central element of its design.\n\n**If we can define some Aggregates by time-ordered series of events, then it follows that these Aggregates are also processes.**\n\n## Rediscovering Finite-State Machines\n\nModelling processes is nothing new in computing. And **automata theory** seems especially interesting:\n\n\u003e A Finite-State Machine (FSM) formulation is used to describe the processes during which information or tasks move from one state to another for action, according to a set of rules. The states consists of the smallest amount of information that together with the knowledge of the input can determine the output.\n\nThe terms Automaton and Machine are used interchangeably, so when we talk about FSA, we also mean FSM.\n\nTranslated into our process terminology, FSMs process a stream of system stimuli (Commands), enforcing invariants and changing the system state (Behaviors).\n\nThe following figure (Fig. 2) shows how the temporal nature of FSMs is driven by the time-ordered and unidirectional stream of Commands.\n\n\n\n\nSince we want to derive a mathematical model, letâs look at the definition of an Finite-State Machine using our previously derived process terminology. An FSM Î is a 5-tuple\n\n\\\\[\nA = \\Big(S, C, \\delta\\colon S \\times C \\to S, S_0\\colon S_0 \\in S, F\\colon F \\subset S \\Big)\n\\\\]\n\nwhere:\n\n* **S** is a non-empty, finite set of states\n* **C** is the **Command language**, a non-empty, finite set of Commands\n* **δ** is the set of **Behaviors** â a relation between a state and Command to a state\n* **Sâ** is the initial state where Sâ is an element of S\n* **F** is the non-empty, finite set of final states where **F** is a subset of **S**\n\nGiven this definition, we will need to derive the command and state alphabets from the domain expertsâ knowledge and then connect the dots via our Behavior functions.\n\n### The universe is a messy place\n\nWe love to look for deterministic solutions to problems that are complex and thus non-deterministic by nature. DDD as a modelling approach embraces unexpected behaviors of systems â which is one of the major reasons why I believe applying DDD thinking to complex problems is almost always a good choice. This means that responses to system stimuli are often different depending on the current situation. Imagine yourself as a call-center agent that is suddenly advised to re-route calls for specific topics to supervisors. The world is just not predictable.\nNon-deterministic Finite-State Auatomata (NDFA)\n\nIn order to deal with this messy world automata theory offers two distinct types of FSAs that can express these differences â Non-Deterministic (NDFA) and Deterministic (DFA) FSAs. Differences between DFA and NDFAs are subtle. While DFAs have exactly one transition for each state and command pair, NDFAs can have multiple, or even none. Mathematically, they are both equivalent. You can always transform a DFA into an NDFA and back again.\n\nBut they do differ between the amount of complexity required to represent them. An NDFA with n states can be transformed into a DFA with up to 2â¿ states. **For a decently complicated NDFA of 10 states we would need up to 1024 states in a DFA to represent it!**\n\n\u003e **When using NDFAs you trade determinism for simplicity!**\n\n### Where are the Events?\n\nIf we recollect the definition of the FSA â which was "])</script>
225<script>self.__next_f.push([1,"defined by the Command and state languages paired with the Behaviors â one might recognize that there is currently no way to signal anything back to the systems. So, where are the events?\n\nIt seems like a plain NDFA is not enough to represent our processes. Can automata theory provide another concept that we can use in this case?\n\nSpoiler, yes it can!\n\n## Introducing Finite-State Transducers (FSTs)\n\nLetâs compare the following schematic diagram of an FST (Fig. 4) with the previous one of an FSM (Fig. 2) and see if we can spot a difference:\n\n\n\n\nWe now have an actual output of Events that correspond to the states and Commands that were fed in. Exactly what we need to send our signals out into the world to wreak havoc! Again, letâs have a look at the formal definition of an **Finite-State Transducer**. It is a 7-tuple\n\n\\\\[\nA = \\Big(S, C, E, \\delta\\colon S \\times C \\to S, \\omega\\colon S \\times C \\to E, S_0\\colon S_0 \\subset S, F\\colon F \\subset S \\Big)\n\\\\]\n\nwhere:\n\n* **S** is a non-empty, finite set of states\n* **C** is the **Command language**, a non-empty, finite set of Commands\n* **E** is the **Event language**, a non-empty, finite set of Events\n* **δ** is the set of **Behaviors** â a relation of a state and Command pair to a state of form **δ : S x Câ S**\n* **Ï** is the **output relation** of a state and Command pair to an Event of form **Ï : S x C â E**\n* **Sâ** is the non-empty, finite set of initial states where **Sâ â S** (Sâ is a subset of S)\n* **F** is the non-empty, finite set of final states where **F â S** (F is a subset of S)\n\nNow that we have Commands, Behaviors and Events we can model our processes as non-deterministic FSTs. Letâs get to action and use the math in an example scenario!\n\n### A short excursion on the output relation Ï (omega)\n\nI quickly want to mention that automata theory differs between two major types of transducers â the [**Moore**](https://en.wikipedia.org/wiki/Moore_machine) and [**Mealy**](https://en.wikipedia.org/wiki/Mealy_machine) types.\n\nThey are only different in the form of their output relation Ï. Our transducer definition above is a Mealy Transducer, because its output relation Ï depends on the state and Command as inputs, while a Moore Transducer's output relation would only depend on the state, and not the Command.\n\n* **Moore** form: **Ï : S â E** (Event generation depends only on state)\n* **Mealy** form: **Ï : S x C â E** (Event generation depends on Commands and state combined)\n\n## Example: Designing a User Registration Process\n\nLetâs assume we have had a great Event Storming session and are now trying to apply the math to the crunched knowledge of a specific problem â a User Registration process. We have to define the Commands, States, Behaviors and the Events that should be written to the output in response to a specific Behavior. Since we have chosen Event Storming as our collaboration method of choice we'll start with the Events.\n\n### Speaking the Event language!\n\nWe start with building our Event language.\n\n* **Confirmation was sent**\n \n After having started the registration we want to make sure that the customer really has access to the provided email address, hence we send out a confirmation via email with a confirmation link.\n\n* **Confirmation resent**\n\n When the confirmation has expired we want to enable our customers to easily resend the confirmation, maybe the previous mail was caught by a spam filter.\n\n* **Account was confirmed**\n\n When the confirmation was completed by the customer we say that the account is now confirmed.\n\n* **Account was deleted through a GDPR request**\n\n We are bound by European laws to delete all personal data.\n\n*It follows that:*\n\n\\\\[\nE = \\\\{\\small{ConfirmationSent},\\small{ConfirmationResent},\\small{AccountConfirmed},\\small{AccountDeleted}\\\\}\n\\\\]\n\n### Thou Command shall be my duty!\n\nWe have designed the following Commands analogous to our Events:\n\n* **Start registration**\n* **Confir"])</script>
225<script>self.__next_f.push([1,"m account**\n* **Resend confirmation**\n* **Fulfill GDPR request**\n\n*It follows that:*\n\n\\\\[\nC = \\\\{\\small{StartRegistration},\\small{ConfirmAccount},\\small{ResendConfirmation},\\small{FulfillGDPRRequest}\\\\}\n\\\\]\n\n### Designing the States\n\nRemember that we have a principle that should always be on our mind when designing State:\n\n\u003e The states should consist of the smallest amount of information that together with the knowledge of the input can determine the output.\n\nOur goal is to find the minimum required amount of information to enable suitable reactions. Here less is always more.\n\nThis example is not focusing on managing data, but it is possible to define properties on states â this will not have an effect on the general formulas.\n\n* **Potential customer**\n \n This is our initial state \\\\(PotentialCustomer \\in S_0\\\\). Any unregistered customer is a potential!\n\n* **Requires confirmation**\n* **Active**\n* **Deleted**\n \n This is a final state \\\\(Deleted \\in F\\\\)\n\n*It follows that:*\n\n\\\\[\nS = \\\\{\n\\small{PotentialCustomer},\n\\small{RequiresConfirmation},\n\\small{Active},\n\\small{Deleted}\n\\\\}\n\\\\]\n\nand\n\n$$\nS_0 = \\\\{\\\\\\\\\n\\small{PotentialCustomer}\n\\\\}\n$$\n\nand\n\n$$\nF = \\\\{\\\\\\\\\n\\small{Deleted}\n\\\\}\n$$\n\n### How should we react?\n\nThe last thing we need is to define our Behavior (δ) and Event (Ï) functions.\n\n```text\nδ : S x C â S = {\n (PotentialCustomer, StartRegistration) â RequiresConfirmation,\n (RequiresConfirmation, ResendConfirmation) â RequiresConfirmation,\n (RequiresConfirmation, ConfirmAccount) â Confirmed,\n (Active, FulfillGDPRRequest) â Deleted,\n (RequiresConfirmation, FulfillGDPRRequest) â Deleted\n}\n```\n\nand\n\n```text\nÏ : S x C â E = {\n (PotentialCustomer, StartRegistration) â ConfirmationSent,\n (RequiresConfirmation, ResendConfirmation) â ConfirmationResent,\n (RequiresConfirmation, ConfirmAccount) â AccountConfirmed,\n (Active, FulfillGDPRRequest) â AccountDeleted,\n (RequiresConfirmation, FulfillGDPRRequest) â ϵ,\n}\n```\n\nThe ϵ here is special. It says that there is no output for this specific Command-State pair. We will learn more about ϵ and ways we can model handling errors in the next post of this series.\n\n### Construction of our Transducer Aggregate!\n\nNow we can finally construct our User Registration Aggregate (or rather non-deterministic Finite-State Transducer) as:\n\n\\\\[\nT = \\Big(S, C, E, \\delta, \\omega, \\\\{PotentialCustomer\\\\}, \\\\{Deleted\\\\} \\Big)\n\\\\]\n\nand send the following Commands to it:\n\n$$\nC = \\\\{\\small{StartRegistration},\\small{ResendConfirmation},\\small{ConfirmAccount},\\small{FulfillGDPRRequest}\\\\}\n$$\n\nIn response we will receive the following Events:\n\n$$\nE = \\\\{\\small{ConfirmationSent},\\small{ConfirmationResent},\\small{AccountConfirmed},\\small{AccountDeleted}\\\\}\n$$\n\n#### Exercise\n\nGiven the following commands:\n\n$$\nC = \\\\{\\small{StartRegistration},\\small{ResendConfirmation},\\small{FulfillGDPRRequest}\\\\}\n$$\n\n1. Which sequence of events would we get?\n2. Which state is produced?\n\n## Conclusions\n\n* We have learned that process-oriented, temporal models are a great match when dealing with the behaviors of complex systems â and how collaborative modelling techniques have shaped our understanding of these systems.\n* We looked into the past of computing advances to rediscover automata theory as a means to model processes, explored different types of machines (FSA, DFA, NDFA, FST) and mapped these to desired properties of temporal Aggregate design.\n* We put the math to action and designed a an User Registration Aggregate as a concrete example.\n\n## Whatâs next?\n\nIn the next post of the series we will cover the following topics:\n\n* Learning about *Accpetors* and *Sequencers*\n* Exploring generic operations on FSAs like *unions*, *concatenations* and *projections*.\n* Using these operations to naturally transform our current User Registration example into an event-sourced model.\n\n## Personal note\n\nThese posts are a try to
225summarize my personal thoughts about this topic for quite some time. I encourage everyone to challenge me on these ideas, and I am the last one to claim that this is t"])</script>
225<script>self.__next_f.push([1,"he right way to think about these problems.\n\nThe hope I have is that readers have fun following me through my thinking process!\n\nThank you.\n\n*This article was originally published on Medium, but unfortunately I don't want to support or use Medium as a publishing platform. Hence I am moving my blog posts to hashnode. The original article can be found [here](https://medium.com/@tPl0ch/domain-driven-design-a-mathematical-model-for-process-oriented-aggregates-pt-i-6aecc8957865).*\n\n\nb:[\"$\",\"main\",null,{\"id\":\"main-content\",\"className\":\"min-h-screen bg-transparent\",\"children\":[[\"$\",\"$L17\",null,{\"publication\":{\"__typename\":\"Publication\",\"id\":\"61ce9d86b9f0453f6d321470\",\"url\":\"https://t-pl.io\",\"canonicalURL\":\"https://t-pl.io\",\"urlPattern\":\"simple\",\"title\":\"Thomas Ploch's Blog - Systems, People \u0026 Technology\",\"displayTitle\":\"Thomas Ploch's Blog - Systems, People \u0026 Technology\",\"hasBadges\":true,\"descriptionSEO\":\"I am an IT generalist with +15 years of experience in various industries including insurance, e-commerce, manufacturing, logistics and travel blogging about sys\",\"seo\":{\"title\":null,\"description\":null,\"__typename\":\"SEO\"},\"publicMembers\":{\"totalDocuments\":1,\"__typename\":\"PublicMembers\"},\"about\":{\"html\":\"\u003cp\u003eI am an IT generalist with +15 years of experience in various industries including insurance, e-commerce, manufacturing, logistics and travel blogging about systems, people and technology.\u003c/p\u003e\\n\",\"text\":\"I am an IT generalist with +15 years of experience in various industries including insurance, e-commerce, manufacturing, logistics and travel blogging about systems, people and technology.\\n\",\"__typename\":\"Content\"},\"features\":{\"proTeam\":{\"isEnabled\":false,\"__typename\":\"ProTeamFeature\"},\"newsletter\":{\"isEnabled\":false,\"__typename\":\"NewsletterFeature\"},\"viewCount\":{\"isEnabled\":false,\"__typename\":\"ViewCountFeature\"},\"readTime\":{\"isEnabled\":true,\"__typename\":\"ReadTimeFeature\"},\"textSelectionSharer\":{\"isEnabled\":true,\"__typename\":\"TextSelectionSharerFeature\"},\"gptBotCrawling\":{\"__typename\":\"GPTBotCrawlingFeature\",\"isEnabled\":true},\"headlessCMS\":{\"isEnabled\":false,\"__typename\":\"HeadlessCMSFeature\"},\"__typename\":\"PublicationFeatures\"},\"aeoSettings\":{\"isEnabled\":false,\"llmsTxtEnabled\":true,\"crawlers\":{\"gptBot\":true,\"claudeBot\":true,\"perplexityBot\":true,\"googleExtended\":true,\"ccBot\":true,\"__typename\":\"AeoCrawlerSettings\"},\"__typename\":\"PublicationAeoSettings\"},\"metaTags\":\"\u003cmeta name=\\\"google-site-verification\\\" content=\\\"K1pB_brVgJW4jSA9hhYdMxGuyiR0EK0Pfzi6nWEH8OE\\\" /\u003e\",\"ogMetaData\":{\"image\":null,\"__typename\":\"OpenGraphMetaData\"},\"author\":{\"__typename\":\"User\",\"id\":\"61ce9d26b9f0453f6d321464\",\"name\":\"Thomas Ploch\",\"username\":\"tPl0ch\",\"profilePicture\":\"https://cdn.hashnode.com/res/hashnode/image/upload/v1640931885215/4AIFHuTXb.jpeg\"},\"preferences\":{\"__typename\":\"PublicationPreferences\",\"logo\":null,\"dar
225kMode\":{\"__typename\":\"DarkModePreferences\",\"logo\":null,\"enabled\":false},\"navbarItems\":[],\"enabledPages\":{\"__typename\":\"EnabledPages\",\"badges\":false,\"newsletter\":false,\"members\":false},\"layout\":\"stacked\",\"disableFooterBranding\":false,\"isSubscriptionModalDisabled\":false},\"favicon\":null,\"headerColor\":\"#AFE4DE\",\"integrations\":{\"fbPixelID\":\"\",\"fathomSiteID\":\"\",\"fathomCustomDomainEnabled\":false,\"fathomCustomDomain\":\"\",\"hotjarSiteID\":\"\",\"matomoSiteID\":null,\"matomoURL\":\"\",\"gaTrackingID\":\"UA-216159325-1\",\"gTagManagerID\":null,\"plausibleAnalyticsEnabled\":false,\"wmPaymentPointer\":\"\",\"koalaPublicKey\":null,\"msClarityID\":null,\"openPanelClientId\":null,\"consentManagement\":{\"enabled\":false,\"version\":1,\"privacyPolicyURL\":null,\"__typename\":\"ConsentManagement\"},\"__typename\":\"PublicationIntegrations\"},\"imprintV2\":null,\"postsCount\":{\"totalDocuments\":1,\"__typename\":\"PostConnection\"},\"isTeam\":true,\"links\":{\"twitter\":\"https://twitter.com/tPl0ch\",\"instagram\":null,\"github\":\"https://github.com/tPl0ch\",\"website\":\"\",\"hashnode\":\"https://hashnode.com/@tPl0ch\",\"youtube\":\"\",\"dailydev\":\"\",\"linkedin\":\"https://www.linkedin.com/in/thomas-ploch-a3b79059/\",\"mastodon\":null,\"facebook\":null,\"bluesky\":null,\"__typename\":\"PublicationLinks\"},\"domainInfo\":{\"__typename\":\"DomainInfo\",\"hash"])</script>
225<script>self.__next_f.push([1,"nodeSubdomain\":\"tpl0ch\",\"domain\":{\"__typename\":\"Domain\",\"host\":\"t-pl.io\",\"ready\":true},\"wwwPrefixedDomain\":null},\"redirectionRules\":[],\"customRules\":[],\"totalRecommendedPublications\":0,\"allowContributorEdits\":false,\"widgets\":[],\"post\":{\"__typename\":\"Post\",\"id\":\"61d183fa0cfc5655c184620c\",\"cuid\":\"ckxx4xggm0dwmxts1gfch6vk0\",\"title\":\"DDD Aggregates: Processes, State Machines and Transducers\",\"subtitle\":\"An introduction to designing the Domain-Driven Design Aggregate pattern via first principles from automata theory\",\"slug\":\"ddd-aggregates-processes-state-machines-and-transducers\",\"brief\":\"This blog post is the first one in a series of three posts in which we try to derive a mathematical model for process-oriented Domain-Driven Design (DDD) Aggregates.\\nThe need for process-oriented models\\nIn order to understand this need we need to div...\",\"featured\":false,\"publishedAt\":\"2022-01-02T10:52:42.124Z\",\"updatedAt\":\"2022-01-14T13:34:29.696Z\",\"url\":\"https://t-pl.io/ddd-aggregates-processes-state-machines-and-transducers\",\"readTimeInMinutes\":10,\"views\":2943,\"reactionCount\":0,\"responseCount\":1,\"replyCount\":1,\"author\":{\"__typename\":\"User\",\"id\":\"61ce9d26b9f0453f6d321464\",\"name\":\"Thomas Ploch\",\"username\":\"tPl0ch\",\"deactivated\":false,\"profilePicture\":\"https://cdn.hashnode.com/res/hashnode/image/upload/v1640931885215/4AIFHuTXb.jpeg\",\"bio\":{\"html\":\"\u003cp\u003eMy name is Thomas, I am 41 years old and an IT generalist with +15 years of experience in various industries including insurance, e-commerce, manufacturing, logistics, travel and transportation.\u003c/p\u003e\\n\u003cp\u003eI have built, led and grown various development teams and am currently very interested in the \\\"New Work\\\" movement. My belief is that the command \u0026amp; control structures found in many organizations are relic from the industrial revolution, and that we as an industry need to move beyond these old ways of working - facilitative leadership, cross-functional collaboration, generative cultures, networked organizations.\u003c/p\u003e\\n\u003cp\u003eMy current technical focus lies on building distributed reactive systems within the domain of dynamic pricing, applying a mix of functional thinking with the strategic and tactical principles from domain-driven design.\u003c/p\u003e\\n\",\"__typename\":\"Content\"},\"socialMediaLinks\":{\"website\":\"\",\"github\":\"https://github.com/tPl0ch\",\"twitter\":\"https://twitter.com/tPl0ch\",\"facebook\":\"\",\"stackoverflow\":\"https://stackoverflow.com/users/1471320/thomas-ploch\",\"linkedin\":\"https://www.linkedin.com/in/thomas-ploch-a3b79059/\",\"__typename\":\"SocialMediaLinks\"}},\"coAuthors\":[],\"seo\":{\"title\":\"DDD Aggregate pattern: Processes, State Machines and Transducers\",\"description\":\"An introduction to designing the Domain-Driven Design Aggregate pattern via first principles from automata theory\",\"__typename\":\"SEO\"},\"coverImage\":{\"url\":\"https://cdn.hashnode.com/res/hashnode/image/unsplash/aQYgUYwnCsM/upload/v1641121050901/_cvnyJNXU.jpeg\",\"isPortrait\":false,\"attribution\":\"https://unsplash.com/@lazycreekimages\",\"isAttributionHidden\":false,\"photographer\":\"Michael Dziedzic\",\"__typename\":\"CoverImage\"},\"content\":{\"html\":\"$18\",\"markdown\":\"$19\",\"__typename\":\"Content\"},\"preferences\":{\"pinnedToBlog\":false,\"disableComments\":false,\"stickCoverToBottom\":true,\"isDelisted\":false,\"__typename\":\"PostPreferences\"},\"series\":{\"id\":\"61d022757cb96c3f92260aac\",\"name\":\"Domain-Driven Design: A mathematical model for process-oriented Aggregates\",\"slug\":\"process-aggregates\",\"__typename\":\"Series\"},\"tags\":[{\"id\":\"576b14ad41d2cbca360cf875\",\"slug\":\"ddd\",\"name\":\"DDD\",\"__typename\":\"Tag\"},{\"id\":\"568f5c6beea132481d017c36\",\"slug\":\"functional-programming\",\"name\":\"Functional Programming\",\"__typename\":\"Tag\"},{\"id\":\"56744722958ef13879b9512b\",\"slug\":\"computer-science\",\"name\":\"Computer Science\",\"__typename\":\"Tag\"}],\"ogMetaData\":{\"image\":\"https://cdn.hashnode.com/res/hashnode/image/unsplash/aQYgUYwnCsM/upload/v1641121050901/_cvnyJNXU.jpeg\",\"__typename\":\"OpenGra
225phMetaData\"},\"canonicalUrl\":null,\"hasLatexInPost\":true,\"faq\":[],\"features\":{\"tableOfContents\":{\"isEnabled\":true,\"items\":[{\"__typename\":\"TableOfContentsItem\",\"id\":\"toc-0\",\"level\":1,\"slug\":\"\",\"title\":\""])</script>
225<script>self.__next_f.push([1,"\",\"parentId\":null},{\"__typename\":\"TableOfContentsItem\",\"id\":\"toc-1\",\"level\":1,\"slug\":\"\",\"title\":\"\",\"parentId\":null},{\"__typename\":\"TableOfContentsItem\",\"id\":\"toc-2\",\"level\":1,\"slug\":\"\",\"title\":\"\",\"parentId\":null},{\"__typename\":\"TableOfContentsItem\",\"id\":\"toc-3\",\"level\":1,\"slug\":\"\",\"title\":\"\",\"parentId\":null},{\"__typename\":\"TableOfContentsItem\",\"id\":\"toc-4\",\"level\":1,\"slug\":\"\",\"title\":\"\",\"parentId\":null},{\"__typename\":\"TableOfContentsItem\",\"id\":\"toc-5\",\"level\":1,\"slug\":\"\",\"title\":\"\",\"parentId\":null},{\"__typename\":\"TableOfContentsItem\",\"id\":\"toc-6\",\"level\":1,\"slug\":\"\",\"title\":\"\",\"parentId\":null},{\"__typename\":\"TableOfContentsItem\",\"id\":\"toc-7\",\"level\":1,\"slug\":\"\",\"title\":\"\",\"parentId\":null},{\"__typename\":\"TableOfContentsItem\",\"id\":\"toc-8\",\"level\":1,\"slug\":\"\",\"title\":\"\",\"parentId\":null},{\"__typename\":\"TableOfContentsItem\",\"id\":\"toc-9\",\"level\":1,\"slug\":\"\",\"title\":\"\",\"parentId\":null},{\"__typename\":\"TableOfContentsItem\",\"id\":\"toc-10\",\"level\":1,\"slug\":\"\",\"title\":\"\",\"parentId\":null},{\"__typename\":\"TableOfContentsItem\",\"id\":\"toc-11\",\"level\":1,\"slug\":\"\",\"title\":\"\",\"parentId\":null},{\"__typename\":\"TableOfContentsItem\",\"id\":\"toc-12\",\"level\":1,\"slug\":\"\",\"title\":\"\",\"parentId\":null},{\"__typename\":\"TableOfContentsItem\",\"id\":\"toc-13\",\"level\":1,\"slug\":\"\",\"title\":\"\",\"parentId\":null},{\"__typename\":\"TableOfContentsItem\",\"id\":\"toc-14\",\"level\":1,\"slug\":\"\",\"title\":\"\",\"parentId\":null},{\"__typename\":\"TableOfContentsItem\",\"id\":\"toc-15\",\"level\":1,\"slug\":\"\",\"title\":\"\",\"parentId\":null},{\"__typename\":\"TableOfContentsItem\",\"id\":\"toc-16\",\"level\":1,\"slug\":\"\",\"title\":\"\",\"parentId\":null}],\"__typename\":\"TableOfContents\"},\"__typename\":\"PostFeatures\"}},\"posts\":{\"edges\":[{\"node\":{\"__typename\":\"Post\",\"id\":\"61d183fa0cfc5655c184620c\",\"title\":\"DDD Aggregates: Processes, State Machines and Transducers\",\"slug\":\"ddd-aggregates-processes-state-machines-and-transducers\",\"publishedAt\":\"2022-01-02T10:52:42.124Z\",\"cuid\":\"ckxx4xggm0dwmxts1gfch6vk0\",\"url\":\"https://t-pl.io/ddd-aggregates-processes-state-machines-and-transducers\",\"subtitle\":\"An introduction to designing the Domain-Driven Design Aggregate pattern via first principles from automata theory\",\"brief\":\"This blog post is the first one in a series of three posts in which we try to derive a mathematical model for process-oriented Domain-Driven Design (DDD) Aggregates.\\nThe need for process-oriented models\\nIn order to understand this need we need to div...\",\"readTimeInMinutes\":10,\"views\":2943,\"tags\":[{\"id\":\"576b14ad41d2cbca360cf875\",\"slug\":\"ddd\",\"name\":\"DDD\",\"__typename\":\"Tag\"},{\"id\":\"568f5c6beea132481d017c36\",\"slug\":\"functional-programming\",\"name\":\"Functional Programming\",\"__typename\":\"Tag\"},{\"id\":\"56744722958ef13879b9512b\",\"slug\":\"computer-science\",\"name\":\"Computer Science\",\"__typename\":\"Tag\"}],\"author\":{\"__typename\":\"User\",\"id\":\"61ce9d26b9f0453f6d321464\",\"username\":\"tPl0ch\",\"name\":\"Thomas Ploch\",\"profilePicture\":\"https://cdn.hashnode.com/res/hashnode/image/upload/v1640931885215/4AIFHuTXb.jpeg\",\"followersCount\":8},\"coverImage\":{\"__typename\":\"CoverImage\",\"url\":\"https://cdn.hashnode.com/res/hashnode/image/unsplash/aQYgUYwnCsM/upload/v1641121050901/_cvnyJNXU.jpeg\",\"isPortrait\":false,\"isAttributionHidden\":false}},\"__typename\":\"PostEdge\"}],\"__typename\":\"PostConnection\"},\"redirectedPost\":null,\"staticPage\":null},\"posts\":[\"$b:props:children:0:props:publication:post\"],\"host\":\"t-pl.io\"}],\"$L1a\",\"$L1b\",\"$L1c\",false,\"$L1d\",null,\"$L1e\"]}]\n1f:I[62031,[\"590\",\"static/chunks/0dbeb660-9e82e99813552576.js\",\"4554\",\"static/chunks/4554-984b480a9db5f3fe.js\",\"7563\",\"static/chunks/7563-4dfa0994a9b0e37c.js\",\"5001\",\"static/chunks/5001-fae0bebdd93f95e3.
225js\",\"2423\",\"static/chunks/2423-c8b1388240338d7d.js\",\"9216\",\"static/chunks/9216-9272709ba40c1cfd.js\",\"1545\",\"static/chunks/1545-7abf96433ff6553f.js\",\"3091\",\"static/chunks/3091-bf1537ff6571a1bd.js\",\"652\",\"static/chunks/652-f40dcb480b4e356f.js\",\"730\",\"static/chunks/730-8191af9e9424b148.js\",\"3048\",\"static/chunks/app/%5B...slug%5D/page-ce41bf29cdfb993a.js\"],\"ReadingModeToggle\"]\n20:I[81356,[\"590\",\"static/chunks/0dbeb660-9e82e99813552576.js\",\"4554\",\"static/chunks/4554-984b480a9db5f3fe.js\",\"7563\",\"static"])</script>
225<script>self.__next_f.push([1,"/chunks/7563-4dfa0994a9b0e37c.js\",\"5001\",\"static/chunks/5001-fae0bebdd93f95e3.js\",\"2423\",\"static/chunks/2423-c8b1388240338d7d.js\",\"9216\",\"static/chunks/9216-9272709ba40c1cfd.js\",\"1545\",\"static/chunks/1545-7abf96433ff6553f.js\",\"3091\",\"static/chunks/3091-bf1537ff6571a1bd.js\",\"652\",\"static/chunks/652-f40dcb480b4e356f.js\",\"730\",\"static/chunks/730-8191af9e9424b148.js\",\"3048\",\"static/chunks/app/%5B...slug%5D/page-ce41bf29cdfb993a.js\"],\"Image\"]\n21:I[52619,[\"4554\",\"static/chunks/4554-984b480a9db5f3fe.js\",\"7563\",\"static/chunks/7563-4dfa0994a9b0e37c.js\",\"5001\",\"static/chunks/5001-fae0bebdd93f95e3.js\",\"2423\",\"static/chunks/2423-c8b1388240338d7d.js\",\"9216\",\"static/chunks/9216-9272709ba40c1cfd.js\",\"3091\",\"static/chunks/3091-bf1537ff6571a1bd.js\",\"652\",\"static/chunks/652-f40dcb480b4e356f.js\",\"730\",\"static/chunks/730-8191af9e9424b148.js\",\"8974\",\"static/chunks/app/page-cc18ae1a3a7a5ed8.js\"],\"\"]\n22:I[33884,[\"590\",\"static/chunks/0dbeb660-9e82e99813552576.js\",\"4554\",\"static/chunks/4554-984b480a9db5f3fe.js\",\"7563\",\"static/chunks/7563-4dfa0994a9b0e37c.js\",\"5001\",\"static/chunks/5001-fae0bebdd93f95e3.js\",\"2423\",\"static/chunks/2423-c8b1388240338d7d.js\",\"9216\",\"static/chunks/9216-9272709ba40c1cfd.js\",\"1545\",\"static/chunks/1545-7abf96433ff6553f.js\",\"3091\",\"static/chunks/3091-bf1537ff6571a1bd.js\",\"652\",\"static/chunks/652-f40dcb480b4e356f.js\",\"730\",\"static/chunks/730-8191af9e9424b148.js\",\"3048\",\"static/chunks/app/%5B...slug%5D/page-ce41bf29cdfb993a.js\"],\"Avatar\"]\n23:I[33884,[\"590\",\"static/chunks/0dbeb660-9e82e99813552576.js\",\"4554\",\"static/chunks/4554-984b480a9db5f3fe.js\",\"7563\",\"static/chunks/7563-4dfa0994a9b0e37c.js\",\"5001\",\"static/chunks/5001-fae0bebdd93f95e3.js\",\"2423\",\"static/chunks/2423-c8b1388240338d7d.js\",\"9216\",\"static/chunks/9216-9272709ba40c1cfd.js\",\"1545\",\"static/chunks/1545-7abf96433ff6553f.js\",\"3091\",\"static/chunks/3091-bf1537ff6571a1bd.js\",\"652\",\"static/chunks/652-f40dcb480b4e356f.js\",\"730\",\"static/chunks/730-8191af9e9424b148.js\",\"3048\",\"static/chunks/app/%5B...slug%5D/page-ce41bf29cdfb993a.js\"],\"AvatarImage\"]\n24:I[33884,[\"590\",\"static/chunks/0dbeb660-9e82e99813552576.js\",\"4554\",\"static/chunks/4554-984b480a9db5f3fe.js\",\"7563\",\"static/chunks/7563-4dfa0994a9b0e37c.js\",\"5001\",\"static/chunks/5001-fae0bebdd93f95e3.js\",\"2423\",\"static/chunks/2423-c8b1388240338d7d.js\",\"9216\",\"static/chunks/9216-9272709ba40c1cfd.js\",\"1545\",\"static/chunks/1545-7abf96433ff6553f.js\",\"3091\",\"static/chunks/3091-bf1537ff6571a1bd.js\",\"652\",\"static/chunks/652-f40dcb480b4e356f.js\",\"730\",\"static/chunks/730-8191af9e9424b148.js\",\"3048\",\"static/chunks/app/%5B...slug%5D/page-ce41bf29cdfb993a.js\"],\"AvatarFallback\"]\n28:I[51285,[\"590\",\"static/chunks/0dbeb660-9e82e99813552576.js\",\"4554\",\"static/chunks/4554-984b480a9db5f3fe.js\",\"7563\",\"static/chunks/7563-4dfa0994a9b0e37c.js\",\"5001\",\"static/chunks/5001-fae0bebdd93f95e3.js\",\"2423\",\"static/chunks/2423-c8b1388240338d7d.js\",\"9216\",\"static/chunks/9216-9272709ba40c1cfd.js\",\"1545\",\"static/chunks/1545-7abf96433ff6553f.js\",\"3091\",\"static/chunks/3091-bf1537ff6571a1bd.js\",\"652\",\"static/chunks/652-f40dcb480b4e356f.js\",\"730\",\"static/chunks/730-8191af9e9424b148.js\",\"3048\",\"static/chunks/app/%5B...slug%5D/page-ce41bf29cdfb993a.js\"],\"CommentsSection\"]\n1a:[\"$\",\"section\",null,{\"className\":\"py-8\",\"children\":[\"$\",\"div\",null,{\"className\":\"px-4 sm:px-8\",\"children\":[\"$\",\"div\",null,{\"className\":\"w-full max-w-full xl:mx-auto xl:max-w-[80rem] 2xl:max-w-[90rem]\",\"children\":[\"$\",\"div\",null,{\"className\":\"grid gap-5 max-w-full\",\"children\":[\"$\",\"article\",null,{\"className\":\"w-full max-w-full rounded-xl border bg-card text-card-foreground\",\"children\":[[\"$\",\"div\",null,{\"className\":\"px-5 pt-12 pb-8 sm:px-8\",\"children\":[\"$\",\"header\",null,{\"className\":\"space-y-5\",\"children\":[\"$\",\"div\",null,{\"className\":\"space-y-4 text-center max-w-4xl mx-auto\",\"children\":[[\"$\",\"h1\",null,{\"className\":\"text-2xl sm:text-3xl md:text-4xl lg:text-5xl font-bold leading-tight tracking-tight text-balance text-foreground\",\"children\":\"DDD Aggregates: Processes, State Machines and Transducers\"}],[\"$\",\"p\",null,{\"className\":\"text-lg sm:text-xl leading-normal font-normal text-muted-foreground text"])</script>
225<script>self.__next_f.push([1,"-balance\",\"children\":\"An introduction to designing the Domain-Driven Design Aggregate pattern via first principles from automata theory\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center justify-center gap-3 text-sm text-muted-foreground\",\"children\":[[\"$\",\"div\",null,{\"className\":\"flex items-center gap-2\",\"children\":[[\"$\",\"span\",null,{\"children\":\"Updated\"}],[\"$\",\"time\",null,{\"dateTime\":\"2022-01-14T13:34:29.696Z\",\"children\":\"January 14, 2022\"}]]}],[[\"$\",\"span\",null,{\"className\":\"text-muted-foreground\",\"children\":\"â¢\"}],[\"$\",\"span\",null,{\"children\":[10,\" min read\"]}]],[\"$\",\"span\",null,{\"className\":\"text-muted-foreground\",\"children\":\"â¢\"}],[\"$\",\"$L1f\",null,{\"slug\":\"ddd-aggregates-processes-state-machines-and-transducers\"}]]}]]}]}]}],[\"$\",\"div\",null,{\"className\":\"w-full\",\"children\":[\"$\",\"$L20\",null,{\"src\":\"https://cdn.hashnode.com/res/hashnode/image/unsplash/aQYgUYwnCsM/upload/v1641121050901/_cvnyJNXU.jpeg\",\"alt\":\"DDD Aggregates: Processes, State Machines and Transducers\",\"width\":1200,\"height\":750,\"className\":\"w-full h-auto\",\"priority\":true}]}],[\"$\",\"div\",null,{\"className\":\"px-5 py-12 sm:px-8 space-y-8\",\"children\":[[\"$\",\"div\",null,{\"className\":\"max-w-2xl mx-auto\",\"children\":[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-5\",\"children\":[[\"$\",\"div\",\"61ce9d26b9f0453f6d321464\",{\"className\":\"flex items-center gap-5\",\"children\":[false,[\"$\",\"div\",null,{\"className\":\"flex gap-3 items-start\",\"children\":[[\"$\",\"$L21\",null,{\"href\":\"https://hashnode.com/@tPl0ch\",\"target\":\"_blank\",\"rel\":\"noopener\",\"children\":[\"$\",\"$L22\",null,{\"className\":\"h-10 w-10 border border-border transition-opacity hover:opacity-80\",\"children\":[[\"$\",\"$L23\",null,{\"src\":\"https://cdn.hashnode.com/res/hashnode/image/upload/v1640931885215/4AIFHuTXb.jpeg?auto=compress,format\u0026format=webp\",\"alt\":\"Thomas Ploch\"}],[\"$\",\"$L24\",null,{\"className\":\"bg-muted text-muted-foreground font-semibold text-lg\",\"children\":\"T\"}]]}]}],[\"$\",\"div\",null,{\"className\":\"min-w-0\",\"children\":[[\"$\",\"div\",null,{\"className\":\"flex items-center gap-2\",\"children\":[[\"$\",\"$L21\",null,{\"href\":\"https://hashnode.com/@tPl0ch\",\"target\":\"_blank\",\"rel\":\"noopener\",\"className\":\"font-medium text-foreground hover:text-primary transition-colors\",\"children\":\"Thomas Ploch\"}],[\"$\",\"div\",null,{\"className\":\"flex items-center gap-1.5 text-sm\",\"children\":[[\"$\",\"$L21\",null,{\"href\":\"https://twitter.com/tPl0ch\",\"target\":\"_blank\",\"rel\":\"noopener\",\"className\":\"text-muted-foreground hover:text-foreground transition-colors\",\"aria-label\":\"X (Twitter)\",\"children\":[\"$\",\"i\",null,{\"className\":\"fa-brands fa-x-twitter\",\"aria-hidden\":true}]}],[\"$\",\"$L21\",null,{\"href\":\"https://www.linkedin.com/in/thomas-ploch-a3b79059/\",\"target\":\"_blank\",\"rel\":\"noopener\",\"className\":\"text-muted-foreground hover:text-foreground transition-colors\",\"aria-label\":\"LinkedIn\",\"children\":[\"$\",\"i\",null,{\"className\":\"fa-brands fa-linkedin\",\"aria-hidden\":true}]}]]}]]}],[\"$\",\"div\",null,{\"className\":\"text-sm text-muted-foreground line-clamp-2\",\"dangerouslySetInnerHTML\":{\"__html\":\"\u003cp\u003eMy name is Thomas, I am 41 years old and an IT generalist with +15 years of experience in various industries including insurance, e-commerce, manufacturing, logistics, travel and transportation.\u003c/p\u003e\\n\u003cp\u003eI have built, led and grown various development teams and am currently very interested in the \\\"New Work\\\" movement. My belief is that the command \u0026amp; control structures found in many organizations are relic from the industrial revolution, and that we as an industry need to move beyond these old ways of working - facilitative leadership, cross-functional collaboration, generative cultures, networked organizations.\u003c/p\u003e\\n\u003cp\u003eMy current technical focus lies on building distributed reactive systems within the domain of dynamic pricing, applying a mix of functional thinking with the strategic and tactical principles from domain-driven design.\u003c/p\u003e\\n\"}}]]}]]}]]}]]}]}],\"$L25\",\"$L26\",false,\"$L27\"]}]]}]}]}]}]}]\n1b:[\"$\",\"section\",null,{\"className\":\"pb-8\",\"children\":[\"$\",\"div\",null,{\"className\":\"px-4 sm:px-8\",\"children\":[\"$\",\"div\",null,{\"className\":\"w-full max-w-full xl:mx-auto xl:"])</script>
225<script>self.__next_f.push([1,"max-w-[80rem] 2xl:max-w-[90rem]\",\"children\":[\"$\",\"div\",null,{\"className\":\"max-w-4xl w-full mx-auto\",\"children\":[\"$\",\"div\",null,{\"className\":\"rounded-xl border bg-card text-card-foreground p-5 sm:p-8\",\"children\":[\"$\",\"$L28\",null,{\"host\":\"t-pl.io\",\"slug\":\"ddd-aggregates-processes-state-machines-and-transducers\",\"postUrl\":\"https://hashnode.com/posts/ddd-aggregates-processes-state-machines-and-transducers/61d183fa0cfc5655c184620c\",\"initialEdges\":[{\"cursor\":\"1\",\"node\":{\"id\":\"61dd545243ea534d6beae16c\",\"content\":{\"html\":\"\u003cp\u003every interesting, waiting for the second part! :-D\u003c/p\u003e\\n\",\"__typename\":\"Content\"},\"dateAdded\":\"2022-01-11T09:56:34.812Z\",\"totalReactions\":0,\"author\":{\"id\":\"5d2b0f867751887c51fe8d63\",\"name\":\"Toni Villena\",\"username\":\"tonivj5\",\"profilePicture\":\"https://cdn.hashnode.com/res/hashnode/image/upload/v1563103110583/k_drBRmV3.jpeg\",\"__typename\":\"User\"},\"replies\":{\"edges\":[],\"pageInfo\":{\"hasNextPage\":false,\"endCursor\":\"50\",\"totalDocuments\":0,\"__typename\":\"PageInfo\"},\"__typename\":\"CommentConnection\"},\"__typename\":\"Comment\"},\"__typename\":\"CommentEdge\"}],\"initialPageInfo\":{\"hasNextPage\":false,\"endCursor\":\"10\",\"totalDocuments\":1,\"__typename\":\"PageInfo\"},\"totalComments\":1}]}]}]}]}]}]\n1c:[\"$\",\"section\",null,{\"className\":\"pb-8\",\"children\":[\"$\",\"div\",null,{\"className\":\"px-4 sm:px-8\",\"children\":[\"$\",\"div\",null,{\"className\":\"w-full max-w-full xl:mx-auto xl:max-w-[80rem] 2xl:max-w-[90rem]\",\"children\":[\"$\",\"div\",null,{\"className\":\"max-w-4xl w-full mx-auto\",\"children\":[\"$\",\"div\",null,{\"className\":\"rounded-xl border bg-card text-card-foreground overflow-hidden\",\"children\":[[\"$\",\"div\",null,{\"className\":\"p-5 sm:p-6 space-y-3\",\"children\":[[\"$\",\"$L21\",null,{\"href\":\"/series/process-aggregates\",\"className\":\"group flex items-center gap-2\",\"children\":[[\"$\",\"i\",null,{\"className\":\"fa-jelly fa-layer-group h-4 w-4 text-muted-foreground\",\"aria-hidden\":true}],[\"$\",\"h2\",null,{\"className\":\"text-base font-semibold leading-snug tracking-tight text-foreground group-hover:text-primary transition-colors\",\"children\":\"Domain-Driven Design: A mathematical model for process-oriented Aggregates\"}]]}],[\"$\",\"div\",null,{\"className\":\"flex items-center gap-3 text-sm text-muted-foreground\",\"children\":[[\"$\",\"span\",null,{\"children\":[\"Part \",1,\" of \",1]}],[\"$\",\"div\",null,{\"className\":\"flex-1 h-1 rounded-full bg-muted overflow-hidden\",\"children\":[\"$\",\"div\",null,{\"className\":\"h-full rounded-full bg-primary transition-all\",\"style\":{\"width\":\"100%\"}}]}]]}],[\"$\",\"p\",null,{\"className\":\"text-sm leading-relaxed text-muted-foreground line-clamp-2\",\"children\":\"In this series I want to exploit theorems from automata theory to formally define the Domain-Driven Design Aggregate pattern.\"}]]}],null]}]}]}]}]}]\n29:T4a0,{\"@context\":\"https://schema.org\",\"@type\":\"Article\",\"url\":\"https://t-pl.io/ddd-aggregates-processes-state-machines-and-transducers\",\"mainEntityOfPage\":\"https://t-pl.io/ddd-aggregates-processes-state-machines-and-transducers\",\"headline\":\"DDD Aggregates: Processes, State Machines and Transducers\",\"description\":\"This blog post is the first one in a series of three posts in which we try to derive a mathematical model for process-oriented Domain-Driven Design (DDD) Aggregates.\\nThe need for process-oriented models\\nIn order to understand this need we need to div...\",\"author\":{\"@type\":\"Person\",\"name\":\"Thomas Ploch\",\"url\":\"https://hashnode.com/@tPl0ch\",\"image\":\"https://cdn.hashnode.com/res/hashnode/image/upload/v1640931885215/4AIFHuTXb.jpeg\",\"sameAs\":\"https://x.com/tPl0ch\"},\"publisher\":{\"@type\":\"Organization\",\"name\":\"Thomas Ploch's Blog - Systems, People \u0026 Technology\",\"url\":\"https://t-pl.io\"},\"datePublished\":\"2022-01-02T10:52:42.124Z\",\"dateModified\":\"2022-01-14T13:34:29.696Z\",\"image\":{\"@type\":\"ImageObject\",\"url\":\"https://cdn.hashnode.com/res/hashnode/image/unsplash/aQYgUYwnCsM/upload/v1641121050901/_cvnyJNXU.jpeg\"},\"keywords\":\"DDD, Functional Programming, Computer Science\"}1d:[\"$\",\"script\",null,{\"type\":\"application/ld+json\",\"dangerouslySetInnerHTML\":{\"__html\":\"$29\"}}]\n2a:I[78655,[\"590\",\"static/chunks/0dbeb660-9e82e99813552576.js\",\"4554\",\"static/chunks/4554-984b480a9db5f3fe.js"])</script>
225<script>self.__next_f.push([1,"\",\"7563\",\"static/chunks/7563-4dfa0994a9b0e37c.js\",\"5001\",\"static/chunks/5001-fae0bebdd93f95e3.js\",\"2423\",\"static/chunks/2423-c8b1388240338d7d.js\",\"9216\",\"static/chunks/9216-9272709ba40c1cfd.js\",\"1545\",\"static/chunks/1545-7abf96433ff6553f.js\",\"3091\",\"static/chunks/3091-bf1537ff6571a1bd.js\",\"652\",\"static/chunks/652-f40dcb480b4e356f.js\",\"730\",\"static/chunks/730-8191af9e9424b148.js\",\"3048\",\"static/chunks/app/%5B...slug%5D/page-ce41bf29cdfb993a.js\"],\"TableOfContents\"]\n25:[\"$\",\"div\",null,{\"className\":\"max-w-2xl mx-auto\",\"children\":[\"$\",\"$L21\",null,{\"href\":\"/series/process-aggregates\",\"className\":\"group flex items-center gap-3 rounded-lg border border-border px-3 py-2 transition hover:border-primary hover:bg-accent\",\"children\":[[\"$\",\"i\",null,{\"className\":\"fa-jelly fa-layer-group h-4 w-4 text-muted-foreground group-hover:text-primary transition-colors\",\"aria-hidden\":true}],[\"$\",\"div\",null,{\"className\":\"flex flex-col\",\"children\":[[\"$\",\"span\",null,{\"className\":\"text-sm text-muted-foreground\",\"children\":\"Part of series\"}],[\"$\",\"span\",null,{\"className\":\"text-sm font-medium text-foreground group-hover:text-primary transition-colors\",\"children\":\"Domain-Driven Design: A mathematical model for process-oriented Aggregates\"}]]}]]}]}]\n2b:T447e,\u003cp\u003eThis blog post is the first one in a series of three posts in which we try to derive a mathematical model for process-oriented Domain-Driven Design (DDD) Aggregates.\u003c/p\u003e\n\u003ch2 id=\"heading-the-need-for-process-oriented-models\"\u003eThe need for process-oriented models\u003c/h2\u003e\n\u003cp\u003eIn order to understand this need we need to dive into complex systems theory. Donât worry, we will not dive deep!\u003c/p\u003e\n\u003cp\u003eNot surprisingly software is not an isolated artifact. It must be embedded into the socio-technical context of the people that use and produce it, paired with the constant interactions of the environment. What we need to know is how complex systems show the behaviors that we, as system designers, try to capture in useful abstractions.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e\u003cstrong\u003eOrganizations are dynamic, hierarchically structured entities. Such dynamism is reflected in the emergence of significant events at every organizational level.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e\u003ca target=\"_blank\" href=\"https://www.researchgate.net/publication/272427231_Event_System_Theory_An_Event-Oriented_Approach_to_the_Organizational_Sciences\" rel=\"noopener ugc\"\u003e[Morgeson F., Mitchell T., Liu D. 2015. Event System Theory: An Event-Oriented Approach To The Origanisational Sciences]\u003c/a\u003e\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eWe will call these patterns of events \u003cstrong\u003eprocesses\u003c/strong\u003e. These processes emerge in systems to achieve something, be it selling books online or providing restaurants with seat reservations. A large research topic termed process theories is trying to understand how patterns of events lead to positive outcomes. Ultimately they are \u003cstrong\u003eâstories about what happened and who did what when â that is, events, activities, and choices ordered over timeâ\u003c/strong\u003e \u003ca target=\"_blank\" href=\"https://www.jstor.org/stable/259349?seq=1#page_scan_tab_contents\" rel=\"noopener ugc\"\u003e[Langley, A. 1999. Strategies for theorizing from process data]\u003c/a\u003e.\u003c/p\u003e\n\u003ch3 id=\"heading-the-rise-of-collaborative-temporal-modelling\"\u003eThe rise of collaborative temporal modelling\u003c/h3\u003e\n\u003cp\u003eOver the past years new practices to capture these processes emerged. Event Storming, Story Mapping or Domain Story Telling are all examples of approaches to recognize that understanding the repeating patterns of events can give us a great leverage in designing working solutions. These results regularly have a much larger overlap with the organizational reality than traditional static modelling techniques.\u003c/p\u003e\n\u003cp\u003eTemporal modelling also had an effect on the tactical design choices that experienced DDD practitioners make when working with Aggregates. Aggregates are then defined as a combination of \u003cstrong\u003eCommands\u003c/strong\u003e (stimuli from the environment), \u003cstrong\u003eBehaviors\u003c/strong\u003e (reactions to incoming stimuli that can change the systemâs response mechanisms) and \u003cstrong\u003eEvents\u003c/strong\u003e (system signals in res"])</script>
225<script>self.__next_f.push([1,"ponse to changes in system state). The âEvent Sourcingâ pattern for example builds on these fundamental design choices to make the time-ordered â hence âtemporalâ â patterns of events the central element of its design.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eIf we can define some Aggregates by time-ordered series of events, then it follows that these Aggregates are also processes.\u003c/strong\u003e\u003c/p\u003e\n\u003ch2 id=\"heading-rediscovering-finite-state-machines\"\u003eRediscovering Finite-State Machines\u003c/h2\u003e\n\u003cp\u003eModelling processes is nothing new in computing. And \u003cstrong\u003eautomata theory\u003c/strong\u003e seems especially interesting:\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eA Finite-State Machine (FSM) formulation is used to describe the processes during which information or tasks move from one state to another for action, according to a set of rules. The states consists of the smallest amount of information that together with the knowledge of the input can determine the output.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eThe terms Automaton and Machine are used interchangeably, so when we talk about FSA, we also mean FSM.\u003c/p\u003e\n\u003cp\u003eTranslated into our process terminology, FSMs process a stream of system stimuli (Commands), enforcing invariants and changing the system state (Behaviors).\u003c/p\u003e\n\u003cp\u003eThe following figure (Fig. 2) shows how the temporal nature of FSMs is driven by the time-ordered and unidirectional stream of Commands.\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"https://cdn.hashnode.com/res/hashnode/image/upload/v1641031481149/N6f766oxh.jpeg\" alt=\"1 Qfbo0Jmfxwoy9tujEhdZ7g.jpg\" /\u003e\u003c/p\u003e\n\u003cp\u003eSince we want to derive a mathematical model, letâs look at the definition of an Finite-State Machine using our previously derived process terminology. An FSM Î is a 5-tuple\u003c/p\u003e\n\u003cp\u003e\\[\nA = \\Big(S, C, \\delta\\colon S \\times C \\to S, S_0\\colon S_0 \\in S, F\\colon F \\subset S \\Big)\n\\]\u003c/p\u003e\n\u003cp\u003ewhere:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eS\u003c/strong\u003e is a non-empty, finite set of states\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eC\u003c/strong\u003e is the \u003cstrong\u003eCommand language\u003c/strong\u003e, a non-empty, finite set of Commands\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eδ\u003c/strong\u003e is the set of \u003cstrong\u003eBehaviors\u003c/strong\u003e â a relation between a state and Command to a state\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eSâ\u003c/strong\u003e is the initial state where Sâ is an element of S\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eF\u003c/strong\u003e is the non-empty, finite set of final states where \u003cstrong\u003eF\u003c/strong\u003e is a subset of \u003cstrong\u003eS\u003c/strong\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eGiven this definition, we will need to derive the command and state alphabets from the domain expertsâ knowledge and then connect the dots via our Behavior functions.\u003c/p\u003e\n\u003ch3 id=\"heading-the-universe-is-a-messy-place\"\u003eThe universe is a messy place\u003c/h3\u003e\n\u003cp\u003eWe love to look for deterministic solutions to problems that are complex and thus non-deterministic by nature. DDD as a modelling approach embraces unexpected behaviors of systems â which is one of the major reasons why I believe applying DDD thinking to complex problems is almost always a good choice. This means that responses to system stimuli are often different depending on the current situation. Imagine yourself as a call-center agent that is suddenly advised to re-route calls for specific topics to supervisors. The world is just not predictable.\nNon-deterministic Finite-State Auatomata (NDFA)\u003c/p\u003e\n\u003cp\u003eIn order to deal with this messy world automata theory offers two distinct types of FSAs that can express these differences â Non-Deterministic (NDFA) and Deterministic (DFA) FSAs. Differences between DFA and NDFAs are subtle. While DFAs have exactly one transition for each state and command pair, NDFAs can have multiple, or even none. Mathematically, they are both equivalent. You can always transform a DFA into an NDFA and back again.\u003c/p\u003e\n\u003cp\u003eBut they do differ between the amount of complexity required to represent them. An NDFA with n states can be transformed into a DFA with up to 2â¿ states. \u003cstrong\u003eFor a decently complicated NDFA of 10 states we would need up to 1024 states in a DFA to represent it!\u003c/strong\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e\u003cstrong\u003eWhen using N
225DFAs you trade determinism for simplicity!\u003c/strong\u003e\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch3 id=\"heading-where-are-the-events\"\u003eWhere are the Events?"])</script>
225<script>self.__next_f.push([1,"\u003c/h3\u003e\n\u003cp\u003eIf we recollect the definition of the FSA â which was defined by the Command and state languages paired with the Behaviors â one might recognize that there is currently no way to signal anything back to the systems. So, where are the events?\u003c/p\u003e\n\u003cp\u003eIt seems like a plain NDFA is not enough to represent our processes. Can automata theory provide another concept that we can use in this case?\u003c/p\u003e\n\u003cp\u003eSpoiler, yes it can!\u003c/p\u003e\n\u003ch2 id=\"heading-introducing-finite-state-transducers-fsts\"\u003eIntroducing Finite-State Transducers (FSTs)\u003c/h2\u003e\n\u003cp\u003eLetâs compare the following schematic diagram of an FST (Fig. 4) with the previous one of an FSM (Fig. 2) and see if we can spot a difference:\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"https://cdn.hashnode.com/res/hashnode/image/upload/v1641115365141/UcZxMwTlj.jpeg\" alt=\"1 oecW_d-OOCvYrzEUd4Awsg.jpg\" /\u003e\u003c/p\u003e\n\u003cp\u003eWe now have an actual output of Events that correspond to the states and Commands that were fed in. Exactly what we need to send our signals out into the world to wreak havoc! Again, letâs have a look at the formal definition of an \u003cstrong\u003eFinite-State Transducer\u003c/strong\u003e. It is a 7-tuple\u003c/p\u003e\n\u003cp\u003e\\[\nA = \\Big(S, C, E, \\delta\\colon S \\times C \\to S, \\omega\\colon S \\times C \\to E, S_0\\colon S_0 \\subset S, F\\colon F \\subset S \\Big)\n\\]\u003c/p\u003e\n\u003cp\u003ewhere:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eS\u003c/strong\u003e is a non-empty, finite set of states\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eC\u003c/strong\u003e is the \u003cstrong\u003eCommand language\u003c/strong\u003e, a non-empty, finite set of Commands\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eE\u003c/strong\u003e is the \u003cstrong\u003eEvent language\u003c/strong\u003e, a non-empty, finite set of Events\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eδ\u003c/strong\u003e is the set of \u003cstrong\u003eBehaviors\u003c/strong\u003e â a relation of a state and Command pair to a state of form \u003cstrong\u003eδ : S x Câ S\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eÏ\u003c/strong\u003e is the \u003cstrong\u003eoutput relation\u003c/strong\u003e of a state and Command pair to an Event of form \u003cstrong\u003eÏ : S x C â E\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eSâ\u003c/strong\u003e is the non-empty, finite set of initial states where \u003cstrong\u003eSâ â S\u003c/strong\u003e (Sâ is a subset of S)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eF\u003c/strong\u003e is the non-empty, finite set of final states where \u003cstrong\u003eF â S\u003c/strong\u003e (F is a subset of S)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eNow that we have Commands, Behaviors and Events we can model our processes as non-deterministic FSTs. Letâs get to action and use the math in an example scenario!\u003c/p\u003e\n\u003ch3 id=\"heading-a-short-excursion-on-the-output-relation-w-omega\"\u003eA short excursion on the output relation Ï (omega)\u003c/h3\u003e\n\u003cp\u003eI quickly want to mention that automata theory differs between two major types of transducers â the \u003ca target=\"_blank\" href=\"https://en.wikipedia.org/wiki/Moore_machine\" rel=\"noopener ugc\"\u003e\u003cstrong\u003eMoore\u003c/strong\u003e\u003c/a\u003e and \u003ca target=\"_blank\" href=\"https://en.wikipedia.org/wiki/Mealy_machine\" rel=\"noopener ugc\"\u003e\u003cstrong\u003eMealy\u003c/strong\u003e\u003c/a\u003e types.\u003c/p\u003e\n\u003cp\u003eThey are only different in the form of their output relation Ï. Our transducer definition above is a Mealy Transducer, because its output relation Ï depends on the state and Command as inputs, while a Moore Transducer's output relation would only depend on the state, and not the Command.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eMoore\u003c/strong\u003e form: \u003cstrong\u003eÏ : S â E\u003c/strong\u003e (Event generation depends only on state)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMealy\u003c/strong\u003e form: \u003cstrong\u003eÏ : S x C â E\u003c/strong\u003e (Event generation depends on Commands and state combined)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"heading-example-designing-a-user-registration-process\"\u003eExample: Designing a User Registration Process\u003c/h2\u003e\n\u003cp\u003eLetâs assume we have had a great Event Storming session and are now trying to apply the math to the crunched knowledge of a specific problem â a User Registration process. We have to define the Commands, States, Behaviors and the Events that should be written to the output in response to a specific Behavior. Since we have chosen Event Storming as our collaboration method of choice we'll start with the Events.\u003c/p\u003e\n\u003ch3 id=\"heading-speaking-the-event-language\"\u003eSpeaking the Event language!\u003c/h3\u003e\n\u003cp\u003eWe start with building our Event language.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cp\u003e\u003cstrong\u003eConfirmation was sent\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eAfter having started"])</script>
225<script>self.__next_f.push([1," the registration we want to make sure that the customer really has access to the provided email address, hence we send out a confirmation via email with a confirmation link.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cp\u003e\u003cstrong\u003eConfirmation resent\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eWhen the confirmation has expired we want to enable our customers to easily resend the confirmation, maybe the previous mail was caught by a spam filter.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cp\u003e\u003cstrong\u003eAccount was confirmed\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eWhen the confirmation was completed by the customer we say that the account is now confirmed.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cp\u003e\u003cstrong\u003eAccount was deleted through a GDPR request\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eWe are bound by European laws to delete all personal data.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cem\u003eIt follows that:\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003e\\[\nE = \\{\\small{ConfirmationSent},\\small{ConfirmationResent},\\small{AccountConfirmed},\\small{AccountDeleted}\\}\n\\]\u003c/p\u003e\n\u003ch3 id=\"heading-thou-command-shall-be-my-duty\"\u003eThou Command shall be my duty!\u003c/h3\u003e\n\u003cp\u003eWe have designed the following Commands analogous to our Events:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eStart registration\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eConfirm account\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eResend confirmation\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eFulfill GDPR request\u003c/strong\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cem\u003eIt follows that:\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003e\\[\nC = \\{\\small{StartRegistration},\\small{ConfirmAccount},\\small{ResendConfirmation},\\small{FulfillGDPRRequest}\\}\n\\]\u003c/p\u003e\n\u003ch3 id=\"heading-designing-the-states\"\u003eDesigning the States\u003c/h3\u003e\n\u003cp\u003eRemember that we have a principle that should always be on our mind when designing State:\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eThe states should consist of the smallest amount of information that together with the knowledge of the input can determine the output.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eOur goal is to find the minimum required amount of information to enable suitable reactions. Here less is always more.\u003c/p\u003e\n\u003cp\u003eThis example is not focusing on managing data, but it is possible to define properties on states â this will not have an effect on the general formulas.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cp\u003e\u003cstrong\u003ePotential customer\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eThis is our initial state \\(PotentialCustomer \\in S_0\\). Any unregistered customer is a potential!\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cp\u003e\u003cstrong\u003eRequires confirmation\u003c/strong\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eActive\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cp\u003e\u003cstrong\u003eDeleted\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eThis is a final state \\(Deleted \\in F\\)\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cem\u003eIt follows that:\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003e\\[\nS = \\{\n\\small{PotentialCustomer},\n\\small{RequiresConfirmation},\n\\small{Active},\n\\small{Deleted}\n\\}\n\\]\u003c/p\u003e\n\u003cp\u003eand\u003c/p\u003e\n\u003cp\u003e$$\nS_0 = \\{\\\\\n\\small{PotentialCustomer}\n\\}\n$$\u003c/p\u003e\n\u003cp\u003eand\u003c/p\u003e\n\u003cp\u003e$$\nF = \\{\\\\\n\\small{Deleted}\n\\}\n$$\u003c/p\u003e\n\u003ch3 id=\"heading-how-should-we-react\"\u003eHow should we react?\u003c/h3\u003e\n\u003cp\u003eThe last thing we need is to define our Behavior (δ) and Event (Ï) functions.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"lang-text\"\u003eδ : S x C â S = {\n (PotentialCustomer, StartRegistration) â RequiresConfirmation,\n (RequiresConfirmation, ResendConfirmation) â RequiresConfirmation,\n (RequiresConfirmation, ConfirmAccount) â Confirmed,\n (Active, FulfillGDPRRequest) â Deleted,\n (RequiresConfirmation, FulfillGDPRRequest) â Deleted\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eand\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"lang-text\"\u003eÏ : S x C â E = {\n (PotentialCustomer, StartRegistration) â ConfirmationSe
225nt,\n (RequiresConfirmation, ResendConfirmation) â ConfirmationResent,\n (RequiresConfirmation, ConfirmAccount) â AccountConfirmed,\n (Active, FulfillGDPRRequest) â AccountDeleted,\n (RequiresConfirmation, FulfillGDPRRequest) â ϵ,\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThe ϵ here is special. It says that there is no output for this specific Command-State pair. We will learn more about ϵ and ways we can model handling errors in the next post of this series.\u003c/p\u003e\n\u003ch3 id=\"heading-construction-of-our-transducer-aggregate\"\u003eConstruction of our Transducer Aggregate!\u003c/h3\u003e\n\u003cp\u003eNow we can finally construct our User Registration Aggregate (or rather non-deterministic Finite-State Transducer) as:\u003c/p\u003e\n\u003cp\u003e\\[\nT = \\Big(S, C, E, \\delta, \\omega, \\{PotentialCustomer\\}, \\{Deleted\\} \\Big)\n\\]\u003c/p\u003e\n\u003cp\u003eand send the following Commands to it:\u003c/p\u003e\n\u003cp\u003e$$\nC = \\{\\small{StartRegistration},\\small{ResendC"])</script>
225<script>self.__next_f.push([1,"onfirmation},\\small{ConfirmAccount},\\small{FulfillGDPRRequest}\\}\n$$\u003c/p\u003e\n\u003cp\u003eIn response we will receive the following Events:\u003c/p\u003e\n\u003cp\u003e$$\nE = \\{\\small{ConfirmationSent},\\small{ConfirmationResent},\\small{AccountConfirmed},\\small{AccountDeleted}\\}\n$$\u003c/p\u003e\n\u003ch4 id=\"heading-exercise\"\u003eExercise\u003c/h4\u003e\n\u003cp\u003eGiven the following commands:\u003c/p\u003e\n\u003cp\u003e$$\nC = \\{\\small{StartRegistration},\\small{ResendConfirmation},\\small{FulfillGDPRRequest}\\}\n$$\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eWhich sequence of events would we get?\u003c/li\u003e\n\u003cli\u003eWhich state is produced?\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"heading-conclusions\"\u003eConclusions\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eWe have learned that process-oriented, temporal models are a great match when dealing with the behaviors of complex systems â and how collaborative modelling techniques have shaped our understanding of these systems.\u003c/li\u003e\n\u003cli\u003eWe looked into the past of computing advances to rediscover automata theory as a means to model processes, explored different types of machines (FSA, DFA, NDFA, FST) and mapped these to desired properties of temporal Aggregate design.\u003c/li\u003e\n\u003cli\u003eWe put the math to action and designed a an User Registration Aggregate as a concrete example.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"heading-whats-next\"\u003eWhatâs next?\u003c/h2\u003e\n\u003cp\u003eIn the next post of the series we will cover the following topics:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eLearning about \u003cem\u003eAccpetors\u003c/em\u003e and \u003cem\u003eSequencers\u003c/em\u003e\u003c/li\u003e\n\u003cli\u003eExploring generic operations on FSAs like \u003cem\u003eunions\u003c/em\u003e, \u003cem\u003econcatenations\u003c/em\u003e and \u003cem\u003eprojections\u003c/em\u003e.\u003c/li\u003e\n\u003cli\u003eUsing these operations to naturally transform our current User Registration example into an event-sourced model.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"heading-personal-note\"\u003ePersonal note\u003c/h2\u003e\n\u003cp\u003eThese posts are a try to
225summarize my personal thoughts about this topic for quite some time. I encourage everyone to challenge me on these ideas, and I am the last one to claim that this is the right way to think about these problems.\u003c/p\u003e\n\u003cp\u003eThe hope I have is that readers have fun following me through my thinking process!\u003c/p\u003e\n\u003cp\u003eThank you.\u003c/p\u003e\n\u003cp\u003e\u003cem\u003eThis article was originally published on Medium, but unfortunately I don't want to support or use Medium as a publishing platform. Hence I am moving my blog posts to hashnode. The original article can be found \u003ca target=\"_blank\" href=\"https://medium.com/@tPl0ch/domain-driven-design-a-mathematical-model-for-process-oriented-aggregates-pt-i-6aecc8957865\" rel=\"noopener ugc\"\u003ehere\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n26:[\"$\",\"div\",null,{\"className\":\"relative\",\"children\":[[\"$\",\"aside\",null,{\"className\":\"hidden xl:block absolute top-0 left-0 h-full\",\"children\":[\"$\",\"nav\",null,{\"className\":\"sticky top-22 w-44\",\"children\":[\"$\",\"$L2a\",null,{\"headings\":[{\"id\":\"heading-the-need-for-process-oriented-models\",\"text\":\"The need for process-oriented models\",\"level\":2},{\"id\":\"heading-the-rise-of-collaborative-temporal-modelling\",\"text\":\"The rise of collaborative temporal modelling\",\"level\":3},{\"id\":\"heading-rediscovering-finite-state-machines\",\"text\":\"Rediscovering Finite-State Machines\",\"level\":2},{\"id\":\"heading-the-universe-is-a-messy-place\",\"text\":\"The universe is a messy place\",\"level\":3},{\"id\":\"heading-where-are-the-events\",\"text\":\"Where are the Events?\",\"level\":3},{\"id\":\"heading-introducing-finite-state-transducers-fsts\",\"text\":\"Introducing Finite-State Transducers (FSTs)\",\"level\":2},{\"id\":\"heading-a-short-excursion-on-the-output-relation-w-omega\",\"text\":\"A short excursion on the output relation Ï (omega)\",\"level\":3},{\"id\":\"heading-example-designing-a-user-registration-process\",\"text\":\"Example: Designing a User Registration Process\",\"level\":2},{\"id\":\"heading-speaking-the-event-language\",\"text\":\"Speaking the Event language!\",\"level\":3},{\"id\":\"heading-thou-command-shall-be-my-duty\",\"text\":\"Thou Command shall be my duty!\",\"level\":3},{\"id\":\"heading-designing-the-states\",\"text\":\"Designing the States\",\"level\":3},{\"id\":\"heading-how-should-we-react\",\"text\":\"How should we react?\",\"level\":3},{\"id\":\"heading-construction-of-our-transducer-aggregate\",\"text\":\"Construction of our Transducer Aggregate!\",\"level\":3},{\"id\":\"heading-exercise\",\"text\":\"Exercise\",\"level\":4},{\"id\":\"heading-conclusions\",\"text\":\"Concl"])</script>
225<script>self.__next_f.push([1,"usions\",\"level\":2},{\"id\":\"heading-whats-next\",\"text\":\"Whatâs next?\",\"level\":2},{\"id\":\"heading-personal-note\",\"text\":\"Personal note\",\"level\":2}]}]}]}],[\"$\",\"div\",null,{\"className\":\"max-w-2xl mx-auto min-w-0 contain-[inline-size]\",\"children\":[\"$\",\"div\",null,{\"className\":\"prose dark:prose-invert prose-pre:bg-foreground prose-pre:text-background prose-pre:border prose-pre:border-border prose-pre:rounded prose-pre:px-5 prose-pre:py-4 dark:prose-pre:bg-muted dark:prose-pre:text-foreground dark:prose-pre:border-border prose-pre:overflow-x-auto max-w-none text-base sm:text-lg [\u0026\u003ediv\u003ep:first-child]:mt-0 [\u0026\u003ediv\u003ep:first-child]:pt-0 min-w-0 wrap-break-word [\u0026_a]:break-all **:max-w-full\",\"children\":[[],[\"$\",\"div\",null,{\"suppressHydrationWarning\":true,\"dangerouslySetInnerHTML\":{\"__html\":\"$2b\"}}],[],\"$L2c\",\"$L2d\",\"$L2e\",\"$L2f\",\"$L30\"]}]}]]}]\n27:[\"$\",\"div\",null,{\"className\":\"max-w-2xl mx-auto border-t border-border pt-8 space-y-5\",\"children\":[[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-2\",\"children\":[[\"$\",\"$L21\",\"576b14ad41d2cbca360cf875\",{\"href\":\"/tag/ddd\",\"className\":\"inline-flex items-center gap-1.5 rounded-full border border-border px-3 py-1 text-sm text-muted-foreground transition hover:border-primary hover:text-primary\",\"children\":[\"#\",\"ddd\"]}],[\"$\",\"$L21\",\"568f5c6beea132481d017c36\",{\"href\":\"/tag/functional-programming\",\"className\":\"inline-flex items-center gap-1.5 rounded-full border border-border px-3 py-1 text-sm text-muted-foreground transition hover:border-primary hover:text-primary\",\"children\":[\"#\",\"functional-programming\"]}],[\"$\",\"$L21\",\"56744722958ef13879b9512b\",{\"href\":\"/tag/computer-science\",\"className\":\"inline-flex items-center gap-1.5 rounded-full border border-border px-3 py-1 text-sm text-muted-foreground transition hover:border-primary hover:text-primary\",\"children\":[\"#\",\"computer-science\"]}]]}],false]}]\n31:I[32478,[\"590\",\"static/chunks/0dbeb660-9e82e99813552576.js\",\"4554\",\"static/chunks/4554-984b480a9db5f3fe.js\",\"7563\",\"static/chunks/7563-4dfa0994a9b0e37c.js\",\"5001\",\"static/chunks/5001-fae0bebdd93f95e3.js\",\"2423\",\"static/chunks/2423-c8b1388240338d7d.js\",\"9216\",\"static/chunks/9216-9272709ba40c1cfd.js\",\"1545\",\"static/chunks/1545-7abf96433ff6553f.js\",\"3091\",\"static/chunks/3091-bf1537ff6571a1bd.js\",\"652\",\"static/chunks/652-f40dcb480b4e356f.js\",\"730\",\"static/chunks/730-8191af9e9424b148.js\",\"3048\",\"static/chunks/app/%5B...slug%5D/page-ce41bf29cdfb993a.js\"],\"CodeHighlighter\"]\n32:I[7714,[\"590\",\"static/chunks/0dbeb660-9e82e99813552576.js\",\"4554\",\"static/chunks/4554-984b480a9db5f3fe.js\",\"7563\",\"static/chunks/7563-4dfa0994a9b0e37c.js\",\"5001\",\"static/chunks/5001-fae0bebdd93f95e3.js\",\"2423\",\"static/chunks/2423-c8b1388240338d7d.js\",\"9216\",\"static/chunks/9216-9272709ba40c1cfd.js\",\"1545\",\"static/chunks/1545-7abf96433ff6553f.js\",\"3091\",\"static/chunks/3091-bf1537ff6571a1bd.js\",\"652\",\"static/chunks/652-f40dcb480b4e356f.js\",\"730\",\"static/chunks/730-8191af9e9424b148.js\",\"3048\",\"static/chunks/app/%5B...slug%5D/page-ce41bf29cdfb993a.js\"],\"EmbedHandler\"]\n33:I[54960,[\"590\",\"static/chunks/0dbeb660-9e82e99813552576.js\",\"4554\",\"static/chunks/4554-984b480a9db5f3fe.js\",\"7563\",\"static/chunks/7563-4dfa0994a9b0e37c.js\",\"5001\",\"static/chunks/5001-fae0bebdd93f95e3.js\",\"2423\",\"static/chunks/2423-c8b1388240338d7d.js\",\"9216\",\"static/chunks/9216-9272709ba40c1cfd.js\",\"1545\",\"static/chunks/1545-7abf96433ff6553f.js\",\"3091\",\"static/chunks/3091-bf1537ff6571a1bd.js\",\"652\",\"static/chunks/652-f40dcb480b4e356f.js\",\"730\",\"static/chunks/730-8191af9e9424b148.js\",\"3048\",\"static/chunks/app/%5B...slug%5D/page-ce41bf29cdfb993a.js\"],\"ImageZoom\"]\n34:I[6671,[\"590\",\"static/chunks/0dbeb660-9e82e99813552576.js\",\"4554\",\"static/chunks/4554-984b480a9db5f3fe.js\",\"7563\",\"static/chunks/7563-4dfa0994a9b0e37c.js\",\"5001\",\"static/chunks/5001-fae0bebdd93f95e3.
225js\",\"2423\",\"static/chunks/2423-c8b1388240338d7d.js\",\"9216\",\"static/chunks/9216-9272709ba40c1cfd.js\",\"1545\",\"static/chunks/1545-7abf96433ff6553f.js\",\"3091\",\"static/chunks/3091-bf1537ff6571a1bd.js\",\"652\",\"static/chunks/652-f40dcb480b4e356f.js\",\"730\",\"static/chunks/730-8191af9e9424b148.js\",\"3048\",\"static/chunks/ap"])</script>
225<script>self.__next_f.push([1,"p/%5B...slug%5D/page-ce41bf29cdfb993a.js\"],\"MathJaxHandler\"]\n35:I[91337,[\"590\",\"static/chunks/0dbeb660-9e82e99813552576.js\",\"4554\",\"static/chunks/4554-984b480a9db5f3fe.js\",\"7563\",\"static/chunks/7563-4dfa0994a9b0e37c.js\",\"5001\",\"static/chunks/5001-fae0bebdd93f95e3.js\",\"2423\",\"static/chunks/2423-c8b1388240338d7d.js\",\"9216\",\"static/chunks/9216-9272709ba40c1cfd.js\",\"1545\",\"static/chunks/1545-7abf96433ff6553f.js\",\"3091\",\"static/chunks/3091-bf1537ff6571a1bd.js\",\"652\",\"static/chunks/652-f40dcb480b4e356f.js\",\"730\",\"static/chunks/730-8191af9e9424b148.js\",\"3048\",\"static/chunks/app/%5B...slug%5D/page-ce41bf29cdfb993a.js\"],\"MermaidHandler\"]\n2c:[\"$\",\"$L31\",null,{}]\n2d:[\"$\",\"$L32\",null,{}]\n2e:[\"$\",\"$L33\",null,{}]\n2f:[\"$\",\"$L34\",null,{\"hasLatex\":true}]\n30:[\"$\",\"$L35\",null,{}]\n36:Tc98,M268.379 39q-6.322 0-10.35-4.108-4.002-4.134-4.002-10.483 0-6.296 4.002-10.43 4-4.135 10.163-4.135 6.028 0 9.817 3.734 3.814 3.735 3.814 9.497v2.8h-24.248v-4.054h17.633q-.187-2.747-2.054-4.508-1.868-1.76-4.962-1.76-3.28-.001-5.388 2.374-2.108 2.373-2.108 6.375 0 4.188 2.348 6.695 2.347 2.481 5.895 2.481 1.68 0 2.934-.453a8.5 8.5 0 0 0 2.321-1.307q1.041-.854 2.268-2.614l4.694 2.96q-1.707 2.748-3.494 4.135a12.7 12.7 0 0 1-3.975 2.081q-2.187.72-5.308.72m-33.496 0q-5.575 0-9.283-4.028-3.681-4.029-3.681-10.484 0-6.43 3.761-10.51 3.76-4.108 9.47-4.108 2.8 0 5.175 1.2 2.4 1.174 3.628 3.148l.026-.08V0h7.016v38.2h-6.722v-4.722l.64.8-.694.133q-1.28 2.108-3.788 3.361Q237.924 39 234.883 39m1.627-6.002q3.308 0 5.495-2.428t2.188-6.135q0-3.762-2.214-6.109-2.214-2.374-5.469-2.374-3.28 0-5.522 2.347-2.214 2.348-2.214 6.163 0 3.76 2.214 6.162 2.214 2.374 5.522 2.374M205.811 39q-6.376 0-10.537-4.161-4.161-4.188-4.161-10.404 0-6.321 4.161-10.456 4.188-4.135 10.537-4.135 6.348 0 10.537 4.161 4.188 4.161 4.188 10.43 0 6.216-4.188 10.404Q212.186 39 205.811 39m0-6.162q3.307 0 5.575-2.374 2.267-2.374 2.267-6.055 0-3.707-2.294-6.056-2.267-2.347-5.548-2.347-3.308 0-5.575 2.374-2.268 2.348-2.268 6.029t2.241 6.055q2.268 2.374 5.602 2.374M162.586 38.2V10.644h6.802v5.015l-.8-.987h.906q1.308-2.187 3.762-3.494 2.48-1.335 5.228-1.334 4.615 0 7.256 2.8 2.667 2.776 2.667 7.603V38.2h-7.069V21.794q0-2.854-1.387-4.401t-4.134-1.547q-2.614 0-4.402 1.974-1.76 1.974-1.76 4.881V38.2zm-30.181 0V0h6.962v14.698h.134q1.2-2.187 3.574-3.521 2.375-1.335 5.229-1.334 4.615 0 7.255 2.828 2.668 2.801 2.668 7.522V38.2h-7.069V21.794q0-2.827-1.387-4.402-1.387-1.573-4.055-1.573-2.587 0-4.428 2.027-1.814 2.027-1.814 4.962v15.391zm-14.416.8q-2.882 0-5.015-.64-2.108-.614-3.761-1.84-1.654-1.228-2.668-2.695l-.987-1.467 4.695-3.174.773 1.067a9.1 9.1 0 0 0 1.788 1.814 8.2 8.2 0 0 0 2.32 1.2q1.308.4 3.068.4 2.161 0 3.441-.8 1.308-.8 1.307-2.294 0-1.36-1.147-2.108-1.12-.747-5.068-1.654-5.335-1.253-7.656-3.334-2.32-2.107-2.321-5.362 0-3.76 3.148-6.002 3.148-2.267 7.923-2.267 2.454 0 4.348.507t3.388 1.493q1.493.988 2.454 2.188l.987 1.2-4.482 3.255-.667-.774a7.4 7.4 0 0 0-1.627-1.387 6.4 6.4 0 0 0-2.054-.88 9.5 9.5 0 0 0-2.401-.294q-1.974 0-3.201.8-1.2.774-1.2 1.921 0 1.254 1.12 2.027 1.147.748 5.229 1.681 5.334 1.227 7.629 3.308 2.294 2.055 2.294 5.308 0 4.029-3.228 6.43Q123.217 39 117.989 39M87.61 39q-4.508 0-7.335-2.454-2.828-2.481-2.828-6.482 0-4.188 3.254-6.669t8.483-2.48q2.082 0 4.028.426 1.974.427 3.361 1.12v-1.6q0-2.588-1.813-4.082-1.788-1.493-4.615-1.493-1.628 0-2.801.373a8.7 8.7 0 0 0-2.188.987q-.987.614-1.84 1.414l-.854.8-4.081-3.788 1.307-1.173a18.7 18.7 0 0 1 2.934-2.108q1.601-.933 3.601-1.44t4.589-.507q5.868 0 9.229 2.88 3.361 2.882 3.361 8.084V38.2h-6.749v-5.922l1.654 2.187h-1.76q-1.308 2.055-3.655 3.308Q90.545 39 87.611 39m1.814-4.988q3.148 0 5.149-2.187 2-2.215 2-5.309v-.08q-1.12-.693-2.72-1.094a13 13 0 0 0-3.388-.426q-2.828 0-4.562 1.2-1.734 1.173-1.734 3.521 0 2.028 1.468 3.201t3.787 1.174M49 38.2V0h6.962v14.698h.134q1.2-2.187 3.574-3.521 2.375-1.335 5.229-1.334 4.615 0 7.255 2.828 2.668 2.801 2.668 7.522V38.2h-7.07V21.794q0-2.827-1.386-4.402-1.387-1.573-4.055-1.573-2.587 0-4.428 2.027-1.815 2.027-1.814 4.962v15.391z1e:[\"$\",\"footer\",null,{\"className\":\"px-4 pt-8 pb-20 sm:px-8 text-muted-foreground\",\"aria-lab"])</script>
225<script>self.__next_f.push([1,"el\":\"Footer\",\"children\":[\"$\",\"div\",null,{\"className\":\"w-full max-w-4xl mx-auto\",\"children\":[\"$\",\"div\",null,{\"className\":\"flex flex-col items-center gap-4 text-center text-sm\",\"children\":[false,[\"$\",\"p\",null,{\"className\":\"font-medium\",\"children\":[[\"$\",\"time\",null,{\"dateTime\":\"2026\",\"children\":[[\"$\",\"span\",null,{\"className\":\"font-sans\",\"children\":\"©\"}],\" \",2026]}],\" \",\"Thomas Ploch's Blog - Systems, People \u0026 Technology\"]}],[\"$\",\"nav\",null,{\"aria-label\":\"Footer navigation\",\"children\":[\"$\",\"ul\",null,{\"className\":\"flex flex-wrap justify-center gap-4 text-sm tracking-wide\",\"children\":[[\"$\",\"li\",\"/archive\",{\"children\":[\"$\",\"$L21\",null,{\"href\":\"/archive\",\"className\":\"transition hover:text-foreground\",\"target\":\"$undefined\",\"rel\":\"$undefined\",\"children\":\"Archive\"}]}],[\"$\",\"li\",\"https://hashnode.com/privacy-policy\",{\"children\":[\"$\",\"$L21\",null,{\"href\":\"https://hashnode.com/privacy-policy\",\"className\":\"transition hover:text-foreground\",\"target\":\"_blank\",\"rel\":\"noopener\",\"children\":\"Privacy\"}]}],[\"$\",\"li\",\"https://hashnode.com/terms\",{\"children\":[\"$\",\"$L21\",null,{\"href\":\"https://hashnode.com/terms\",\"className\":\"transition hover:text-foreground\",\"target\":\"_blank\",\"rel\":\"noopener\",\"children\":\"Terms\"}]}]]}]}],[\"$\",\"div\",null,{\"className\":\"pt-8 flex justify-center gap-6\",\"children\":[[\"$\",\"$L21\",null,{\"href\":\"/sitemap.xml\",\"target\":\"_blank\",\"rel\":\"noopener\",\"className\":\"flex items-center gap-2 text-sm transition hover:text-foreground\",\"title\":\"Sitemap\",\"children\":[[\"$\",\"i\",null,{\"className\":\"fa-regular fa-sitemap\"}],[\"$\",\"span\",null,{\"children\":\"Sitemap\"}]]}],[\"$\",\"$L21\",null,{\"href\":\"/rss.xml\",\"target\":\"_blank\",\"rel\":\"noopener\",\"className\":\"flex items-center gap-2 text-sm transition hover:text-foreground\",\"title\":\"RSS Feed\",\"children\":[[\"$\",\"i\",null,{\"className\":\"fa-regular fa-rss\"}],[\"$\",\"span\",null,{\"children\":\"RSS\"}]]}]]}],[\"$\",\"div\",null,{\"className\":\"pt-10 text-center\",\"children\":[\"$\",\"$L21\",null,{\"href\":\"https://hashnode.com/?utm_source=https%3A%2F%2Ft-pl.io\u0026utm_medium=referral\u0026utm_campaign=blog_footer_logo\u0026utm_content=logo\",\"target\":\"_blank\",\"rel\":\"noopener\",\"aria-label\":\"Visit Hashnode (opens in a new tab)\",\"children\":[\"$\",\"svg\",null,{\"fill\":\"none\",\"viewBox\":\"0 0 282 39\",\"aria-hidden\":\"true\",\"className\":\"h-6 w-auto min-w-[9.5rem] text-muted-foreground transition hover:text-foreground\",\"children\":[[\"$\",\"path\",null,{\"fill\":\"currentColor\",\"d\":\"M2.68 13.032c-3.573 3.505-3.573 9.363 0 12.936L13.032 36.32c3.505 3.573 9.363 3.573 12.936 0L36.32 25.968c3.573-3.573 3.573-9.431 0-12.936L25.968 2.68c-3.573-3.573-9.431-3.573-12.936 0zm12.211 1.935c2.507-2.521 6.582-2.544 9.104-.038s2.544 6.582.038 9.104-6.582 2.544-9.104.038-2.544-6.582-.038-9.104\"}],[\"$\",\"path\",null,{\"fill\":\"currentColor\",\"d\":\"$36\"}]]}],\"className\":\"inline-flex items-center justify-center gap-2 whitespace-nowrap font-medium transition-colors focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [\u0026_svg]:pointer-events-none [\u0026_svg]:size-4 [\u0026_svg]:shrink-0 hover:bg-accent hover:text-accent-foreground h-10 rounded-md text-xl px-5 py-4\",\"ref\":null}]}]]}]}]}]\n"])</script>
225</body></html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.