
  <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
    <channel>
      <title>Tales from Dev</title>
      <link>https://talesfrom.dev/blog</link>
      <description>Tales about mistakes, learning, software, programming, philosophy, life</description>
      <language>en-us</language>
      <managingEditor>dam.plaza@gmail.com (Damian Płaza)</managingEditor>
      <webMaster>dam.plaza@gmail.com (Damian Płaza)</webMaster>
      <lastBuildDate>Sun, 27 Sep 2026 00:00:00 GMT</lastBuildDate>
      <atom:link href="https://talesfrom.dev/feed.xml" rel="self" type="application/rss+xml"/>
      
  <item>
    <guid>https://talesfrom.dev/blog/the-ambiguity-of-state-facts-interpretations-and-perspectives</guid>
    <title>The ambiguity of state: facts, interpretations and perspectives</title>
    <link>https://talesfrom.dev/blog/the-ambiguity-of-state-facts-interpretations-and-perspectives</link>
    <description>Is there an objective state?</description>
    <content:encoded><![CDATA[<div class="bg-slate-600 rounded-xl "><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Attention #1</span></div><div class="pb-2 px-3"><div class="break-words"><p>If you want to truly learn about Event Sourcing and really understand Event-Driven thinking, please visit <a href="https://event-driven.io/en/articles">Oskar Dudycz blog</a>.</p>
<p>I can&#x27;t recommend it enough.</p></div></div></div> <div class="bg-slate-600 rounded-xl mt-6"><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Attention #2</span></div><div class="pb-2 px-3"><div class="break-words"><p>This tale uses concepts discussed in <a href="https://talesfrom.dev/blog/the-ambiguity-of-nouns-absolutisms-transformations-and-nominalisations">The ambiguity of nouns: absolutisms, transformations and nominalisations</a>, so if you haven&#x27;t read it dear Reader, feel invited to do so before continuing.
(but nothing will happen if you don&#x27;t do so.)</p></div></div></div> <div class="bg-slate-600 rounded-xl mt-6"><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Attention #3</span></div><div class="pb-2 px-3"><div class="break-words"><p>This tale is dedicated to all parents who have faced the challenges of caring for sick children.</p></div></div></div><h3 id="oh-no-sick-kids"><a href="#oh-no-sick-kids" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Oh no, sick kids!</h3><p>Imagine that there two parents: <span class="bold italic text-red-500">Karen</span> and <span class="bold italic text-blue-500">John</span>.</p><p>They have two kids: <span class="bold italic text-green-500">Alice</span> and <span class="bold italic text-yellow-500">Dylan</span>.</p><p>The life was good, until one day when both got back from the school and had strange symptoms: vomitting, fatigue, diarrhea, and fever.</p><p>Well, not a pleasent situation for the kids.</p><p>And even more unpleasant for the parents, who had to deal with the sudden illness of their children (and in general with the situation at home).</p><p>What did the parents do in this situation?</p><p>Called the doctor, immediately.</p><p>Also what they did, before the doctor arrived, was to make sure the kids drank plenty of fluids.</p><p>But there was another problem which was not known from the beginning - whenever any of the children drank any fluid in a glass-volume amount that was too large, they would immediately vomit it back up.</p><p>This complicated the situation.</p><p>The doctor, <span class="bold italic text-purple-500">Mrs. Ivonne</span>, examined the kids, listened to what parents ellaborated about the situation.</p><p>She then diagnosed them with a strange viral infection.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Listen</div><div class="cursor-pointer border-2 border-l-0 border-b-0 border-gray-50 w-48 text-center text-gray-700">Listen carefully</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-red-500">Karen, mommy:</span><span>You said that the kids have a strange viral infection, what are the consequences of that?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-purple-500">Mrs. Ivonne, doctor:</span><span>They will get through, but you need to do not let them <span class="">dehydrate</span>and do not exceed certain <span class="">level of temperature</span>.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-blue-500">John, daddy:</span><span>Got it, but in details: what does it mean?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-purple-500">Mrs. Ivonne, doctor:</span><span>Each time the kids <span class="">vomit</span>, you need to make sure they <span class="">drink small amounts of fluids frequently</span>to prevent <span class="">dehydration</span>- <span class="">spoon amount of fluid</span>.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-red-500">Karen, mommy:</span><span>What about the <span class="">fever</span>?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-purple-500">Mrs. Ivonne, doctor:</span><span>For the <span class="">fever</span>, you need to <span class="">monitor their temperature closely</span>and give <span class="">fever-reducing medication</span>: each time <span class="">temperature exceeds 40°C (104°F)</span>, give <span class="">a dose</span>, but no more than <span class="">4 doses in 24 hours</span>. Also, whenever they <span class="">vomit</span>when having this <span class="">high fever</span><span class="">third time in the row within 5 minutes</span>, you need to give <span class="">another medicine</span>.</span></div></span></div><p>The doctor was pretty knowledgable and she know it&#x27;s good to <a href="https://talesfrom.dev/blog/keep-it-visible-smartass">visualize the knowledge</a>, even for a simple case like this.</p><p>She wrote the rules on the piece of paper and handed it to the parents, ensuring they are all <a href="https://talesfrom.dev/the-ambiguity-of-communication">aligned</a> - to achieve so, she asked both parents to explain her how they would administer the dosages.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-state-instructions.jpg" class="max-h-[28rem]"/></div><div class="italic mx-24">Instructions from the doctor (generated with LLM)</div></div><p>Even though the situation was really challenging, both parents were happy - they got pretty detailed instructions from the doctor on how to care for their sick children.</p><p>Now it was a matter of living through this sickness, with some disciplined administration.</p><h3 id="parents--engineering--"><a href="#parents--engineering--" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Parents + Engineering = ...?</h3><p><span class="bold italic text-red-500">Karen</span> and <span class="bold italic text-blue-500">John</span> wanted to approach this a little bit more structured and organized, applying some engineering principles to ensure they followed the doctor&#x27;s instructions accurately.</p><p>Fortunately, they had a whiteboard where they could keep all the information in the single, central place.</p><p>Such that they won&#x27;t administer something incorrectly, just by referring to the whiteboard for guidance.</p><p>They divided the whiteboard into two halves: one for <span class="bold italic text-green-500">Alice</span> and the other for <span class="bold italic text-yellow-500">Dylan</span>.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-state-whiteboard-as-database.jpg" class="max-h-[28rem]"/></div><div class="italic mx-24">Whiteboard as a central place for keeping all the information about kids. (generated with LLM)</div></div><p>Now, they needed to think a bit about how to organize the information, so that they can quickly find the relevant details when needed and avoid any mistakes in administering the medications.</p><p>Parents decided to devide everything into categories based on the discussion with the doctor: temperature, vomitting, hydration, meds.</p><p>Additionally, they thought maybe &quot;notes&quot; as a separate category might be useful to have - having more information sounds better, isn&#x27;t it?</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-state-whiteboard-as-database-structure.jpg" class="max-h-[28rem]"/></div><div class="italic mx-24">Whiteboard structured into categories for each child. (generated with LLM)</div></div><p>When they stood in front of the whiteboard, they felt proud of approaching the whole experience in this way.</p><h3 id="whiteboard-driven-sickness-management"><a href="#whiteboard-driven-sickness-management" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Whiteboard-driven sickness management</h3><p>The life was moving on and both parents were diligently following the structured approach they had set up on the whiteboard, ensuring that their children received the care they needed.</p><p>Everything was meticulously recorded and updated on the whiteboard, providing a clear and organized view of the children&#x27;s health status at any given moment.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-state-whiteboard-as-database-structure-with-information.jpg" class="max-h-[28rem]"/></div><div class="italic mx-24">Whiteboard updated with the latest information about the children&#x27;s health. (generated with LLM)</div></div><p>It looked both impressive, but also a bit...Messy?</p><p>It was definitely possible to <em>read the state of each child&#x27;s health</em> and how does <em>a recovery process</em> is progressing, even if the whiteboard appeared a bit chaotic at first glance.</p><p>Problems started araising when <span class="bold italic text-purple-500">Mrs. Ivonne</span> asked about a specific detail regarding one of the children&#x27;s medications, and it took a moment to locate the information on the whiteboard.</p><p>Additionally, she queries for a summary of last days which required juggling <em>TEMP</em>, <em>VOMIT</em>, <em>HYDRATION</em>, and <em>MEDS</em> sections on the whiteboard, making it a bit challenging to quickly compile the information.</p><p>The nail to the coffin came when the doctor came back with a conclusion that the fever temperature threshold over which a medicine needed to be administered was different from what she initially said.</p><p><span class="bold italic text-purple-500">Mrs. Ivonne</span> spoke with the lab and they clarified that this virus requires more careful treatment so the rule for dosing the medication for fever was not using 40°C as the threshold, but rather 38°C.</p><p>This meant that all the previous entries on the whiteboard regarding fever and medication needed to be re-evaluated and updated according to the new threshold of 38°C, adding to the complexity and potential for confusion.</p><p><span class="bold italic text-red-500">Karen</span> and <span class="bold italic text-blue-500">John</span> organized the whiteboard around <em>the information</em>, not about &quot;real&quot; <em>facts</em> they observed while taking care of their children.</p><p>Even though is seemed structured and organized, as the time passed, it was a bit rigid and less adaptable.</p><h3 id="constraints-liberate-liberations-constrain"><a href="#constraints-liberate-liberations-constrain" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Constraints liberate, liberations constrain?</h3><p>They became aware that what they are dealing with is not just a set of information with relationships, but rather <a href="https://talesfrom.dev/blog/the-ambiguity-of-nouns-absolutisms-transformations-and-nominalisations">a process</a> - something that flows, expands and contracts.</p><p>They still wanted to use the whiteboard as a tool for keeping the information, but this time the information they will gather and interpret is going to be different.</p><p><span class="bold italic text-red-500">Karen</span> suggested to focus on <strong>what is happening</strong>, rather <strong>what is changing</strong>.</p><p>This meant paying attention to <em>facts</em>, rather than <em>mere information</em>.</p><p>Also, what they learned from the whiteboard experience so far is that it&#x27;s very tempting to erase information or update information, because <a href="https://talesfrom.dev/blog/simple-isnt-easy">it seemed easy</a>.</p><p>Some of the entries from earlier got buried under other information, which basically made parents lose important insights about the progression of their children&#x27;s health and recovery.</p><p>The decision was made - entries cannot be erased or overwritten; instead new entries would be added to reflect the ongoing changes and observations, creating a chronological record of the children&#x27;s health and recovery process.</p><p>This single constraint fundamentally changed how they interacted with the whiteboard.</p><p>To achieve such constraint, <span class="bold italic text-blue-500">John</span> suggested using <span class="bold italic text-orange-500">orange sticky notes</span> so that they can treat each entry as unchangeable once it is added.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-state-events.jpg" class="max-h-[28rem]"/></div><div class="italic mx-24">Stickies representing the record of what happened when during the recovery process (generated with LLM)</div></div><p>After they established another way of organizing the information on the whiteboard, they started thinking what kind of facts they need to capture and keep track of.</p><p>They realized that capturing facts required a clear distinction between observations and interpretations. Observations are direct, verifiable occurrences, while interpretations are the meanings or conclusions drawn from those observations.</p><p>This distinction helped them understand that while observations could be recorded as immutable entries on the whiteboard, interpretations could be added as separate entries that provide use case and insight without altering the original facts.</p><p>So they came up with the following list of facts that were important in their situation:</p><ul><li>&quot;Temperature measured&quot; with details:<ul><li>which child</li><li>when measurement was captured</li><li>the measured temperature value</li><li>who measured the temperature</li><li>what device was used (they figured out that they used either a digital thermometer or an infrared thermometer)</li></ul></li><li>&quot;Vomited with fluid&quot; with details:<ul><li>which child</li><li>when it happened</li><li>the volume of vomit (small, medium, large)</li><li>who observed it</li></ul></li><li>&quot;Vomited with food&quot; with details:<ul><li>which child</li><li>when it happened</li><li>what food was vomited (if known)</li><li>the volume of vomit (small, medium, large)</li><li>who observed it</li></ul></li><li>&quot;Fluids offered&quot; with details:<ul><li>which child</li><li>when it was offered</li><li>what type of fluid was offered (e.g., water, juice, electrolyte solution)</li><li>the volume of fluid offered (spoon, glass, bottle)</li><li>who offered it</li></ul></li><li>&quot;Fluids consumed&quot; with details:<ul><li>which child</li><li>when it was consumed</li><li>what type of fluid was consumed (e.g., water, juice, electrolyte solution)</li><li>the volume of fluid consumed (spoon, glass, bottle)</li><li>who observed it</li></ul></li><li>&quot;Fluids refused&quot; with details:<ul><li>which child</li><li>when it was refused</li><li>what type of fluid was refused (e.g., water, juice, electrolyte solution)</li><li>the volume of fluid refused (spoon, glass, bottle)</li></ul></li><li>&quot;Dose administered&quot; with details:<ul><li>which child</li><li>when it was administered</li><li>what medication was given</li><li>the dosage</li><li>who administered it</li></ul></li><li>&quot;Urinated&quot; with details:<ul><li>which child</li><li>when it happened</li><li>the volume of urine (small, medium, large)</li><li>who observed it</li></ul></li></ul><p><span class="bold italic text-red-500">Karen</span> reviewed the important facts they considered as essential and additionally suggested the following:</p><ul><li>&quot;Symptom observed&quot; with details:<ul><li>which child</li><li>when it was observed</li><li>what symptom was observed (e.g. &quot;fatigue&quot;)</li><li>who observed it</li></ul></li><li>&quot;Slept&quot; with details:<ul><li>which child</li><li>when it happened</li><li>the duration of sleep</li><li>any wake periods during sleep</li><li>who observed it</li></ul></li></ul><p><span class="bold italic text-blue-500">John</span> was very happy that they focused on what they must observe during the care of the children.</p><p>Somehow it felt &quot;right&quot; from the start of using this way, because they didn&#x27;t need to focus on the structure of potential, future interpretations, like this inquiry from the doctor about the summary, or anticipating what they need to count.</p><p>By doing that, they were able to separate <em>observations</em> from <em>interpretations</em>.</p><p>He also highlighted that there is another important fact to consider: issuing instructions.</p><p>They received instructions and initially <span class="bold italic text-purple-500">Mrs. Ivonne</span> told them to use 40°C temperature as the threshold for administering medication.</p><p>Then, the rule changed and 38°C was the new threshold.</p><p>So additionally to previous meaningful observations-to-record, they decided to add one more:</p><ul><li>&quot;Care instructions received&quot; with details:<ul><li>which child</li><li>when it was received</li><li>what the instruction was</li><li>who issued it</li><li>when it was effective from</li></ul></li></ul><p>In case of changes to care instructions, they will be able to adjust how to make the decision regarding administering medication or other care actions accordingly.</p><p>After some time, that is how the whiteboard looked, filled with all the essential observations they captured:</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-state-events-whiteboard.jpg" class="max-h-[28rem]"/></div><div class="italic mx-24">Children&#x27;s health observations (generated with LLM)</div></div><p>They were able to use those facts to make decisions about next steps, when it came to assisting in the recovery process - whenever vomit occurred, the additional medicine should be administered (according to the care instructions received).</p><p>According to the rules, three vomits in a 5 minute window, under a fever threshold, triggers giving the medicine.</p><p>Parents could easily retrieve such information, just by going through all facts recorded on the whiteboard, for the kid who vomited.</p><p>The doctor calls to check the child&#x27;s condition based on some summary information?</p><p>Sure thing - just start from the left side of the kid&#x27;s whiteboard-half and follow the sequence of observations recorded there, creating the summary.</p><p>Finally, <span class="bold italic text-red-500">Karen</span> and <span class="bold italic text-blue-500">John</span> felt empowered by all the optionality offered by those facts, represented by stickies.</p><p>Previous approach was not bad and not evil, on its own.</p><p>It was not yielding the same level of options and flexibility, when it comes to adjusting based on the evolving situation.</p><p>And the most important constraint - no erasing and no overwriting of existing observations on the whiteboard - truly guided their behavior.</p><h3 id="the-process-of-healing"><a href="#the-process-of-healing" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The process of healing?</h3><p>One day <span class="bold italic text-purple-500">Mrs. Ivonne</span> called them to check what is the situation right now.</p><p>She told them how to take care of the children, but she was not clear on specifying when a child could be considered fully recovered.</p><p>The doctor expressed the following: &quot;whenever any of the following happen: fluid was consumed, temperature was measured, a child urinated, perform a check - full glass consumed, temperature below threshold, child has urinated - all in 2 hours, then recovery can be considered as completed.&quot;</p><p>Soon, <span class="bold italic text-blue-500">John</span> used this guidance to verify the state of the recovery process of both kids.</p><p>Finally, both <span class="bold italic text-green-500">Alice</span> and <span class="bold italic text-yellow-500">Dylan</span> were considered fully recovered according to the doctor&#x27;s criteria.</p><h3 id="the-model-of-everything"><a href="#the-model-of-everything" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The model of everything?</h3><p>Both parents fall in love with this approach for organizing &quot;things&quot; - even though it might have seem as overly complex and difficult to follow at first, they quickly realized the benefits it brought in terms of clarity, accountability, and flexibility in managing the children&#x27;s care.</p><p>It turned out it&#x27;s not only for managing the children&#x27;s care - but it fits other problems too.</p><p>One day, <span class="bold italic text-blue-500">John</span> noticed that <span class="bold italic text-red-500">Karen</span> appended <span class="bold italic text-orange-500">a new sticky note</span> to the whiteboard, in Alice&#x27;s half.</p><p>It caught John&#x27;s attention because it contained the following information:</p><ul><li>&quot;School project scheduled&quot; with details:<ul><li>what is the school subject</li><li>what is the topic of the project</li><li>due date</li><li>required materials</li><li>when it was scheduled</li></ul></li></ul><p>It was definitely worthy having such fact recorded, but at the same time it did not feel &quot;right&quot;.</p><p>&quot;So far, we were keeping observations about recovery process, and this new one is more about school-related activities?&quot;, thought <span class="bold italic text-blue-500">John</span>.</p><p>He decided to leave it for now and see how it would evolve.</p><h3 id="sick-kids-vomitting-diarrhea"><a href="#sick-kids-vomitting-diarrhea" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Sick kids? Vomitting? Diarrhea?</h3><p>&quot;Ok Damian, what the hell did just happen?&quot;, one could definitely ask angrily.</p><p>People are serious software professionals and I dare to tell a tale about sick kids, vomitting and parenting?</p><p>How disappointing it might seem to be!</p><p>But wait, let&#x27;s stop here and ask one important question.</p><p><strong>Do you know what this tale was about, dear Reader?</strong></p><p>Probably you have already guessed.</p><p>We saw event sourcing in action, but more on the conceptual level.</p><p>Our whiteboard played a role of persistent storage, initially acting as &quot;a general storage&quot;.</p><p>All the observations were events, capturing <strong>what happened over time</strong>.</p><p>Both parents played the role of <a href="many-faces-of-ddd-aggregates-in-fsharp">&quot;consistency boundaries&quot;</a>, ensuring that proper decisions are made based on the rules driving this &quot;tiny, toy domain&quot;.</p><p>They both were <a href="https://thinkbeforecoding.com/post/2021/12/17/functional-event-sourcing-decider">&quot;deciders&quot;</a>, using models for deciding - very specifically built ones, out of all facts that happened, but applying one by one until the correct set of information was obtained.</p><p>Throughout this tiny tale, we saw how parents were trying two approaches to managing the complexity of the situation.</p><p>Initially, they used structured approach for capturing snapshots of the state.</p><p>So it&#x27;s not that they did not put any effort in analyzing and planning <a href="https://talesfrom.dev/blog/the-ambiguity-of-software-architecture">the way of organizing</a>.</p><p>They represented information about each children, using categories they understood and found relevant for tracking the recovery process.</p><p>It was easy to start, but the more into the future, the harder it was to maintain consistency, especially when the requirements changed - new rules arrived, new inqueries appeared.</p><p>What could have mislead them was the assumption that they are facing a state of sickness of each kid, rather than a dynamic, flowing process that evolves over time.</p><p>One could say that they focused <a href="https://talesfrom.dev/blog/the-ambiguity-of-nouns-absolutisms-transformations-and-nominalisations">on nouns</a>, without checking how these nouns interact with each other, transform over time and form a flow of &quot;work&quot; (=a workflow).</p><p>They might have fallen into &quot;a nominalization trap&quot;.</p><p>So telling a story how they arrived at certain state was challenging, but not impossible.</p><p>When they realized they are dealing not with &quot;a state of sickness&quot;, but rather with a recovery process that unfolds over time, they adjusted their approach accordingly.</p><p>They switched into looking at important and meaningful facts that they could and needed to observe over time.</p><p>And there was no magic - parents needed to spend time to carefully analyze, structure and organize those facts-to-capture.</p><p>The quality of that process helped them gain a clearer understanding of the recovery journey and make informed decisions along the way.</p><p>Even though &quot;the requirements&quot; changed, like those instructions from the doctor, the approach was accomodating them quite easily, <strong>because</strong> parents were observant and skilled enough in defining the process.</p><p>They were able to adjust the way they interpreted the captured facts, depending on the evolving context and the specific needs of each moment.</p><p>And this &quot;one simple trick&quot; changes almost everything - separating <strong>facts</strong> from <strong>ways of interpreting them</strong> is so enormously powerful.</p><p>What does it teach us, dear Reader?</p><h3 id="facts-interpretations-perspectives"><a href="#facts-interpretations-perspectives" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Facts? Interpretations? Perspectives?</h3><p>Look around, dear Reader.</p><p>Our mind constantly interprets the facts happening in the external world (external to &quot;us&quot;), tricking us into believing that each &quot;thing&quot; in the surrounding environment is <a href="https://talesfrom.dev/blog/the-ambiguity-the-curse-and-the-fallacy-of-domain-model">fixed, static</a>.</p><p>A spoon that was placed in the pot of boiling water, and started heating up, might seem like &quot;the thing&quot;, but in reality, it is part of <strong>a continuous process</strong> of heating and cooling.</p><p>Continously flowing.</p><p><a href="https://en.wikipedia.org/wiki/Panta_rhei_(doctrine)">Panta rhei</a> - everything flows, nothing stands still.</p><p>But it is just one process - thermodynamical one.</p><p>And there are other processes to - manufacturing process, selling process, delivery process, claiming process, and so on.</p><p>So a single &quot;thing&quot; can be a subject of many, different flows.</p><p>That&#x27;s why we, as software professionals, need to pay attention to <a href="https://talesfrom.dev/blog/time-angle-and-depth-dimensions-in-software-design">dimensions</a> while we are analyzing, reasoning and designing systems.</p><p>An avid Reader might realize that <a href="https://youtu.be/M95uj0dEgUY?si=5ZwbZWMTYgsA5bt9">&quot;there is no spoon&quot;</a>, at least not <strong>the spoon</strong>.</p><p>There are many <a href="https://talesfrom.dev/blog/context-segregation-principle">spoons-in-different-contexts</a>, each undergoing various processes, and it&#x27;s our decision what is relevant, important and worth modelling.</p><p>One could say a spoon might be viewed from different perspectives.</p><p>And we already know that mixing different perspectives into <a href="https://talesfrom.dev/blog/bounded-contexts-from-compile-time-hierarchies-to-runtime-composition">&quot;the single thing&quot;</a> might create problems in the near future.</p><p>This absolutism-attracting force, <a href="https://talesfrom.dev/blog/the-knowledge-gravity-problem">&quot;the knowledge gravity&quot;</a> as I like to call it, will lead to another trap related to <em>state</em> - mistaking the current snapshot, needed in a given use case, as <strong>the state</strong> of a given &quot;thing&quot;.</p><p>The same nature was possible to be observed in the context of children recovery process, that Karen and John experienced.</p><p>Initially, they focused on dealing with sickness and recovery facts, but as soon as Karen noticed another important fact - &quot;school project scheduled&quot; - she needed to assign it somewhere.</p><p>Unfortunately, they named the whiteboard-halves after their children names, immediately anchoring themselves into thinking in &quot;absolutisms&quot;.</p><p><a href="https://talesfrom.dev/blog/the-ambiguity-of-naming">Naming is framing</a>, so this &quot;single, tiny event&quot;, related to the school, might have started the process of entropical information attraction.</p><p>Started with recovery concepts, this stream of facts might slowly, but steadily, acquire more concepts related to school, social life, and other aspects of the children&#x27;s daily activities.</p><p>And sooner or later, various perspectives will make the entire event stream:</p><ul><li>hard to maintain due to its length and coupling</li><li>hard to ensure consistency due to overbloated consistency boundary</li><li>hard to perform well due to its length</li><li>and more</li></ul><p>That&#x27;s why event sourcing might not help us if we incorrectly organize event streams, decomposing them along incorrect boundaries.</p><p>This means that just capturing events is not enough - one must use use calories to explore, discover and establish boundaries, watching out for <a href="https://talesfrom.dev/blog/boundaries-modularity-and-a-diaper-effect">the Diaper effect</a>.</p><h3 id="the-state-of-designing-systems"><a href="#the-state-of-designing-systems" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The state of designing systems?</h3><p>It&#x27;s easy to fall into a common trap of looking at absolute concepts, as well as focusing on the current snapshot of the system&#x27;s state.</p><p>Easy, because it requires little effort to grab what is immediately visible, without paying attention to <a href="https://talesfrom.dev/blog/time-angle-and-depth-dimensions-in-software-design">depth, perspectives and time</a>.</p><p><a href="https://en.wikipedia.org/wiki/Daniel_Kahneman">System 1</a> kicks in so blazingly fast that the judgment is done before noticing it&#x27;s all over.</p><p>That&#x27;s why we need to <a href="https://talesfrom.dev/blog/slow-down">slow down</a> and use quality time to <a href="https://talesfrom.dev/blog/the-ambiguity-of-communication">collaborate</a> with others to align and avoid hasty conclusions.</p><p>&quot;Haste makes waste&quot; which might not be initially visible.</p><p>So next time dear Reader, look for what happens when it comes to what you are analyzing and observing - whether this is a manufacturing process of a spoon, a child&#x27;s recovery journey, or the evolution of a software system - all in specific contexts (here: perspectives).</p><p>This framing is so powerful that influences <a href="https://talesfrom.dev/blog/from-concepts-to-architecture">the system architecture in a great extent</a>, because of the used language.</p><p>And this language <a href="https://talesfrom.dev/blog/the-ambiguity-of-thinking">frames</a> our thinking, either limiting or opening possibilities.</p><p>If we start naming things in the context of &quot;continously flowing&quot;, this would be the world we see.</p><p>If on the other hand we decide to name things as absolute, static entities, this would be the world we operate in.</p><p>So next time dear Reader, when you are presented with a business problem or an engineering challenge, ask yourself:</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>What can happen in this context?</p></div></div></div><p>And remember pay attention to <a href="https://talesfrom.dev/blog/language-of-the-problem">the language</a> and start naming various perspectives <a href="https://talesfrom.dev/blog/the-invisible-role-switching-problem-and-need-driven-design">you</a> and <a href="https://talesfrom.dev/blog/consumer-expected-need-driven-behavior-development">users</a> might look at this <a href="https://talesfrom.dev/blog/the-ambiguity-of-arrows">workflow</a>:</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>What perspectives meet each other in this workflow?</p></div></div></div>]]></content:encoded>
    <pubDate>Sun, 27 Sep 2026 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>design thinking</category><category>domain-driven design</category><category>language patterns</category><category>design patterns</category><category>object-oriented design</category><category>software architecture</category><category>mental models</category><category>communication</category><category>knowledge working</category><category>psychology</category><category>linguistics</category><category>event sourcing</category><category>event thinking</category><category>system design</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/the-ambiguity-of-nouns-absolutisms-transformations-and-nominalisations</guid>
    <title>The ambiguity of nouns: absolutisms, transformations and nominalisations</title>
    <link>https://talesfrom.dev/blog/the-ambiguity-of-nouns-absolutisms-transformations-and-nominalisations</link>
    <description>Is every noun the same kind of thing?</description>
    <content:encoded><![CDATA[<div class="bg-slate-600 rounded-xl "><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Attention!</span></div><div class="pb-2 px-3"><div class="break-words"><p>This tale assumes you&#x27;ve read <a href="https://talesfrom.dev/blog/time-angle-and-depth-dimensions-in-software-design">Time, angle and depth: dimensions in software design</a> - we&#x27;re going to lean heavily on the idea that &quot;absolute&quot; concepts like <code>User</code> or <code>Product</code> are a composition of multiple perspectives, at a certain point in time.</p></div></div></div><h3 id="going-out-to-find-some-nouns"><a href="#going-out-to-find-some-nouns" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Going out to find some nouns</h3><p>You might recall <span class="italic font-bold text-fuchsia-500">Derek</span> and <span class="italic font-bold text-blue-500">Diego</span> from <a href="https://talesfrom.dev/blog/the-ambiguity-of-naming">The ambiguity of naming</a> - two developers working for a company selling local, guided tours.</p><p>Multi-city tours shipped. Customers were happy. <span class="italic font-bold text-green-500">Paul</span>, their product owner, was happy too, for a while.</p><p>Then the <code>Tour</code> class started growing. And growing. Pricing rules bumped into scheduling rules, which bumped into navigation state, which bumped into guide availability.</p><p>Sounds familiar? (if it doesn&#x27;t, dear Reader, go check what happened to <a href="https://talesfrom.dev/blog/the-ambiguity-the-curse-and-the-fallacy-of-domain-model#are-you-interested-in-a-tour">poor Tom&#x27;s tourism platform</a>)</p><p>Now senior enough to know better, <span class="italic font-bold text-blue-500">Diego</span> had enough.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div><span class="italic font-bold text-blue-500">Diego, Senior Developer</span>: We keep adding fields and methods to <code>Tour</code> and calling it &quot;modeling the domain&quot;. I want to actually go and find out what a tour <em>is</em>, from the people who run them.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-fuchsia-500">Derek, Senior Developer</span>: Fine by me. Let&#x27;s go talk to the guides, do the collaborative modelling with back-office people, maybe shadow a booking or two.</div></span></div><p>So they did. Out into the wild.</p><h3 id="everyone-hands-a-noun"><a href="#everyone-hands-a-noun" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Everyone hands a noun</h3><p>Guides talked about &quot;the tour&quot;.</p><p>Back-office people talked about &quot;tour seats&quot; and &quot;the schedule of a tour&quot;.</p><p>Marketing talked about &quot;tours catalogue&quot;.</p><p>Participants talked about &quot;my tour&#x27;s itinerary&quot; and &quot;my tour booking&quot;.</p><p><span class="italic font-bold text-fuchsia-500">Derek</span> was taking notes furiously, circling anything that <a href="https://talesfrom.dev/blog/the-ambiguity-of-naming">sounded like a concept</a>.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div><span class="italic font-bold text-fuchsia-500">Derek, Senior Developer</span>: Ok, I&#x27;ve got it. Everyone keeps saying &quot;tour&quot;. That&#x27;s clearly the thing. Name, description, price, seats, guide, status - we put it all there and we&#x27;re done.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-blue-500">Diego, Senior Developer</span>: That&#x27;s... exactly what we did last time.</div></span></div><p>Why does this keep happening, even to senior people who (hopefully) know it&#x27;s a trap?</p><h3 id="a-noun-the-brain-grabs-first"><a href="#a-noun-the-brain-grabs-first" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>A noun the brain grabs first</h3><p><a href="https://en.wikipedia.org/wiki/Daniel_Kahneman">Daniel Kahneman</a> described two ways our brain operates (it&#x27;s a reductionistic perspective, but as with all models - still it&#x27;s useful).</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">System 1 and System 2</div><div class="pb-2 px-3"><div class="break-words"><p><strong>System 1</strong>: fast, automatic, cheap, effort-optimizing - it recognizes patterns instantly.</p>
<p><strong>System 2</strong>: slow, deliberate, expensive, effortful - it checks, verifies and reasons.</p></div></div></div><p>When you&#x27;re standing in a guide&#x27;s office and someone says &quot;the tour&quot;, System 1 does what it&#x27;s best at - it matches the sound &quot;tour&quot; to a ready-made mental box and hands it to you, instantly, no assembly required.</p><p>It basically boils down to &quot;what I see/there, there it is&quot;.</p><p>Asking questions requires effort, answering them requires even more of it too.</p><p>And effort is exactly what System 1 is built to avoid.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>We don&#x27;t pick the <em>currently fitting</em> noun.</p>
<p>We pick <strong>the cheapest</strong> one.</p></div></div></div><p>That&#x27;s the urge to &quot;find things&quot; out in the wild - we go looking, we collect words, and the loudest, earliest, most concrete-sounding word wins the naming contest, well before we&#x27;ve asked what it actually represents.</p><p>Whatever we find &quot;out there&quot; still needs <a href="https://talesfrom.dev/blog/time-angle-and-depth-dimensions-in-software-design">the software dimensions</a> applied to it - time, angle (perspective) and depth aren&#x27;t optional decoration, they&#x27;re what turns a word into a model.</p><h3 id="slow-down-on-purpose"><a href="#slow-down-on-purpose" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a><a href="https://talesfrom.dev/blog/slow-down">Slow down</a>, on purpose</h3><p><span class="italic font-bold text-blue-500">Diego</span> wasn&#x27;t satisfied.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div><span class="italic font-bold text-blue-500">Diego, Senior Developer</span>: Let&#x27;s slow down before we write a single line of code. When does someone even say &quot;tour&quot;?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-fuchsia-500">Derek, Senior Developer</span>: Ha. Funny, that&#x27;s literally what Kahneman calls thinking slow.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-blue-500">Diego, Senior Developer</span>: Coincidence. Or not. Anyway - focus.</div></span></div><p>That&#x27;s the switch from System 1 to System 2 - and it&#x27;s exactly what analysis is for: taking something whole and decomposing it into its <a href="https://talesfrom.dev/blog/composing-a-pie">elements</a>, so it can actually be understood, before it gets put back together.</p><p>They went through all of the material, one by one:</p><ul><li>Someone browsing options, before ever paying anything - marketing wants this searchable, filterable, fast.</li><li>Someone picking a date and a headcount, holding a spot, paying for it.</li><li>Back-office people checking how many spots are left, right now.</li><li>A participant, mid-tour, checking what happens next and where.</li></ul><p>Different moments in time.</p><p>Different perspectives.</p><p>Different <a href="https://talesfrom.dev/blog/consumer-expected-need-driven-behavior-development">needs</a>.</p><p>It all requires an aware, trained mind to notice all of that.</p><p>And it&#x27;s effort requiring.</p><p>It consumes time.</p><p>Eventually, four concepts emerged in the field of operator awareness: <code>Catalogue</code>, <code>Reservation</code>, <code>Seats</code>, <code>Itinerary</code>.</p><p><span class="italic font-bold text-fuchsia-500">Derek</span> looked relieved.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div><span class="italic font-bold text-fuchsia-500">Derek, Senior Developer</span>: Great, four concepts instead of one. Progress!</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-blue-500">Diego, Senior Developer</span>: Slow down. We just did the <em>analysis</em> part. We haven&#x27;t understood any of them yet.</div></span></div><h3 id="are-all-nouns-equal"><a href="#are-all-nouns-equal" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Are all nouns equal?</h3><p>Here&#x27;s the ambiguity, dear Reader - grammatically, all four words are nouns. Same part of speech, same shape, same &quot;box with fields&quot; instinct that System 1 wants to apply to every single one of them.</p><p>But are they the same <em>kind</em> of thing?</p><p>In <a href="https://talesfrom.dev/blog/modeling-maturity-levels">Modeling Maturity Levels</a>, we already established a small, useful correspondence:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p><strong>Being</strong> level corresponds to nouns.</p>
<p><strong>Behaving</strong> level corresponds to verbs.</p>
<p><strong>Becoming</strong> level corrensponds to adjective-noun collocations.</p></div></div></div><p>So, naively, a noun should mean &quot;Being&quot; - what something <em>has</em>, what it <em>is</em>.</p><p>A verb should mean &quot;Behaving&quot; or more deeply &quot;Becoming&quot; - what something <em>does</em>, what it <em>turns into</em>.</p><p>Except language cheats.</p><h3 id="verbs-in-a-nouns-clothing"><a href="#verbs-in-a-nouns-clothing" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Verbs in a noun&#x27;s clothing</h3><p>It might be that not every noun is equal.</p><p>Even if we use our analytical skills and correctly <a href="https://talesfrom.dev/blog/context-segregation-principle">segregate</a> an absolute noun into a set of contextual ones, still we might fail with designing a model around those concepts.</p><p>In linguistics and cognitive sciences, there&#x27;s an interesting concept behind a phenomenon called <strong>nominalisation</strong>.</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">a nominalisation</div><div class="pb-2 px-3"><div class="break-words"><p>A <strong>nominalisation</strong> is a noun formed out of a verb (or an adjective)</p></div></div></div><p>A verb gets frozen, packaged and handed to you as &quot;a thing&quot;.</p><p><em>to reserve</em> becomes <strong>a reservation</strong>.</p><p><em>to decide</em> becomes <strong>a decision</strong>.</p><p><em>to arrive</em> becomes <strong>an arrival</strong>.</p><p>So instead of &quot;looking at the motion&quot;, our focus gets placed on &quot;the thing that results from the motion&quot;.</p><p><code>Reservation</code> is exactly that - underneath its noun-shaped costume hides a verb, a whole sequence of them: request a spot, hold the seats, wait for payment, confirm, or expire, or get cancelled.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">Reservation</span> <span class="token operator">=</span>
</span><span class="code-line">    <span class="token operator">|</span> <span class="token punctuation">{</span> status<span class="token operator">:</span> <span class="token string">&quot;Requested&quot;</span><span class="token punctuation">;</span> participants<span class="token operator">:</span> ParticipantCount <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token operator">|</span> <span class="token punctuation">{</span> status<span class="token operator">:</span> <span class="token string">&quot;SeatsHeld&quot;</span><span class="token punctuation">;</span> holdExpiresAt<span class="token operator">:</span> Date <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token operator">|</span> <span class="token punctuation">{</span> status<span class="token operator">:</span> <span class="token string">&quot;AwaitingPayment&quot;</span><span class="token punctuation">;</span> amountDue<span class="token operator">:</span> Money <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token operator">|</span> <span class="token punctuation">{</span> status<span class="token operator">:</span> <span class="token string">&quot;Confirmed&quot;</span><span class="token punctuation">;</span> confirmedAt<span class="token operator">:</span> Date <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token operator">|</span> <span class="token punctuation">{</span> status<span class="token operator">:</span> <span class="token string">&quot;Expired&quot;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token operator">|</span> <span class="token punctuation">{</span> status<span class="token operator">:</span> <span class="token string">&quot;Cancelled&quot;</span><span class="token punctuation">;</span> reason<span class="token operator">:</span> CancellationReason <span class="token punctuation">}</span>
</span></code></pre></div></div><p>On the surface it might be <em>seen</em> (and then <em>understood</em>) as a noun, yet again as an absolute &quot;thing&quot;.</p><p>So even though we successfully identified a particular aspect that &quot;a Tour&quot; might be looked at, we might fall into the trap again.</p><p>This is a &quot;Becoming&quot; level, wearing &quot;Being&quot; clothes - a <a href="https://talesfrom.dev/blog/fsm-functional-state-machines">state machine</a>, disguised as a data bag.</p><p>It might be that we are dealing with a business workflow - going through various states, integrates a bunch of other concepts in order to deliver value, <a href="https://talesfrom.dev/blog/consumer-expected-need-driven-behavior-development">based on the needs of the consumer</a>.</p><p>So something that &quot;flows&quot; rather than &quot;is&quot;.</p><p>Model it as a flat class with a <code>status: string</code> field, and you&#x27;ve thrown away exactly the information that matters - which transitions are even legal, and when.</p><p><code>Seats</code>, on the other hand, isn&#x27;t hiding anything - it might be regarded as a countable resource with an invariant (you can&#x27;t hold more than what&#x27;s available) that <strong>must be protected</strong>, consistently (if you are looking into the challenge for designing a solution for such a problem dear Reader, please feel free to explore <a href="https://talesfrom.dev/blog/many-faces-of-ddd-aggregates-in-fsharp">this</a> blogpost).</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">class</span> <span class="token class-name">Seats</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token keyword">private</span> <span class="token keyword">readonly</span> total<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">,</span> <span class="token keyword">private</span> held<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token function">canHold</span><span class="token punctuation">(</span>count<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token builtin">boolean</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>held <span class="token operator">+</span> count <span class="token operator">&lt;=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>total<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token function">hold</span><span class="token punctuation">(</span>count<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">canHold</span><span class="token punctuation">(</span>count<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span><span class="token string">&quot;Not enough seats available&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">        <span class="token keyword">this</span><span class="token punctuation">.</span>held <span class="token operator">+=</span> count<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>And yet again, we might undersee important and subtle details, if we treat it as an absolute &quot;thing&quot;.</p><p>It truly requires a disciplined, mindful and skilled approach so that we continously challenge designer&#x27;s (which mean, ours) assumptions so that we verify we are designing <strong>a model</strong>, not <strong>the model</strong>.</p><p><code>Catalogue</code> is yet another substance entirely - a perspective, composed for a completely different moment in time (browsing, before any commitment exists), for a completely different audience and needs (a curious visitor, not yet a paying participant).</p><p>Denormalized, read-heavy, low on rules.</p><h3 id="naive-conceptual-check"><a href="#naive-conceptual-check" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Naive conceptual check?</h3><p>Analysis had done its job - it <a href="https://talesfrom.dev/blog/context-segregation-principle">segregated</a> <code>Tour</code>.</p><p>It would be good to have some heuristics so that we can &quot;shake&quot; the model candidate, to see if any hidden workflows reveal themselves through our perception.</p><p><span class="italic font-bold text-blue-500">Diego</span> had a shortcut for exactly that.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div><span class="italic font-bold text-blue-500">Diego, Senior Developer</span>: Here&#x27;s a cheap trick I run before committing to a whole modeling session. Take a noun, add &quot;-ing&quot; to it. Does it read as something happening, an activity?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-fuchsia-500">Derek, Senior Developer</span>: Sounds silly. Give me one.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-blue-500">Diego, Senior Developer</span>: <code>User</code> becomes &quot;User-ing&quot;. Doesn&#x27;t fit, right? <code>Product</code> becomes &quot;Product-ing&quot;. Doesn&#x27;t fit either. But <code>Tour</code> becomes &quot;Tour-ing&quot; - and that one does.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-fuchsia-500">Derek, Senior Developer</span>: Huh. And if it fits?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-blue-500">Diego, Senior Developer</span>: Then there&#x27;s probably a workflow hiding in there, and I go looking for it, instead of reaching for a class.</div></span></div><p>The mental tool is fairly simple - try adding &quot;-ing&quot; to a noun and see if it reads as an ongoing activity.</p><p>If not, you might want to go to deeper levels and try to check &quot;what is hidden&quot; behind this &quot;absolute&quot; thing.</p><p>There might be something hidden, which is more workflow-based, around.</p><p>Another approach of the same kind is to prefix an absolute noun with &quot;ongoing&quot; - &quot;ongoing User&quot;, &quot;ongoing Product&quot;, &quot;ongoing Tour&quot;.</p><p>The main idea is to &quot;see it in motion&quot;, not &quot;laying down on the shelf&quot;.</p><p>We, designers, want to interact with the concept to see how does it behaves.</p><p>Imagine that heroes of our tiny tale ran it against <code>Catalogue</code> next - &quot;Cataloguing&quot; fits too.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div><span class="italic font-bold text-fuchsia-500">Derek, Senior Developer</span>: Wait, so <code>Catalogue</code> is a workflow too, now?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-blue-500">Diego, Senior Developer</span>: Not the one we&#x27;re looking at, no. &quot;Cataloguing&quot; is real, but it&#x27;s someone else&#x27;s workflow - whoever curates and publishes the thing we browse. The challenge to the concept just told us a workflow exists somewhere nearby. It didn&#x27;t tell us which noun it belongs to. That part&#x27;s still on us.</div></span></div><p>This is the whole point of these &quot;tricks&quot;, dear Reader - they are not a golden hammer.</p><p>Say a word to a noun, watch it wobble (or not), and decide what to do with what you just &quot;saw&quot; - what information it reveals.</p><p>Hammer blindly - &quot;if &#x27;-ing&#x27; fits, it&#x27;s a workflow, full stop&quot; - and it might hurt you, dear Reader.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>The power isn&#x27;t in the &quot;-ing&quot;. It&#x27;s in interacting with a concept, inducing a small change, and paying attention to what comes back.</p></div></div></div><h3 id="what-about-itinerary"><a href="#what-about-itinerary" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What about Itinerary?</h3><p><span class="italic font-bold text-fuchsia-500">Derek</span> wasn&#x27;t ready to let this go.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div><span class="italic font-bold text-fuchsia-500">Derek, Senior Developer</span>: Ok, &quot;reservation&quot; hides &quot;to reserve&quot;. What does &quot;itinerary&quot; hide? &quot;To itinerary&quot;? That&#x27;s not even a verb.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-blue-500">Diego, Senior Developer</span>: Ha, good catch. It doesn&#x27;t come from a verb at all - it&#x27;s just Latin for &quot;of a journey&quot;.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-fuchsia-500">Derek, Senior Developer</span>: So it&#x27;s a &quot;Being&quot; noun then? Just an ordered list of stops?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-blue-500">Diego, Senior Developer</span>: Once it&#x27;s confirmed - sure, it&#x27;s a plan, a value to be read while the guide is walking people around. But it came <em>from somewhere</em>. Someone, or something, sequenced those stops, checked opening hours, checked the guide&#x27;s route. That&#x27;s a workflow too - we just don&#x27;t have a tidy nominalisation for it in English.</div></span></div><p>That&#x27;s the twist, dear Reader - checking whether a noun is a nominalisation isn&#x27;t a spelling exercise, it&#x27;s not about etymology at all.</p><p>The question is never &quot;does this word grammatically descend from a verb?&quot; - it&#x27;s:</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>Is there a hidden verb - a process, a sequence of steps, a set of legal transitions - underneath this noun, regardless of how it happens to be spelled?</p></div></div></div><p><code>Itinerary</code>-the-plan is a &quot;Being&quot; noun.</p><p>&quot;Itinerary planning&quot; is a &quot;Becoming&quot; process.</p><p>Language just doesn&#x27;t give us a single clean word for the second one, so we default to naming the <em>output</em> / the <em>result</em>, and quietly forget the <em>workflow</em> that produced it ever existed.</p><h3 id="analysis-then-synthesis"><a href="#analysis-then-synthesis" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Analysis, then synthesis</h3><p>Decomposing <code>Tour</code> into those four was the <em>analysis</em> - taking the whole apart into elements we could actually reason about, one perspective and one moment in time, at a time.</p><p>But analysis alone isn&#x27;t design. <span class="italic font-bold text-blue-500">Diego</span> and <span class="italic font-bold text-fuchsia-500">Derek</span> still needed to <strong>put it back together</strong>, with the understanding they just gained - <em>synthesis</em>.</p><p><code>Reservation</code>, once confirmed, is what makes <code>Seats.hold(...)</code> lasting forever, and eventually what causes an <code>Itinerary</code> to be produced for that specific booking. <code>Catalogue</code> doesn&#x27;t participate in any of this - it just gets refreshed, later, from whatever changed.</p><p>None of the four nouns disappeared.</p><p>There&#x27;s no single <code>Tour</code> class anywhere holding them together - there&#x27;s a <code>TourId</code>, threading through all four, at runtime (you might recognize this from <a href="https://talesfrom.dev/blog/the-ambiguity-the-curse-and-the-fallacy-of-domain-model#where-is-tour-entity">where is &quot;Tour&quot; entity?</a>).</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Analysis decomposes, synthesis recomposes - but only when the effort was put in building the understanding.</p></div></div></div><h3 id="the-ambiguity-of-nouns"><a href="#the-ambiguity-of-nouns" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The ambiguity of nouns</h3><p>We can&#x27;t design, or even talk, without nouns - they&#x27;re how we carve &quot;the wild&quot;, the undifferentiated reality out there, into things we can point at and reason about.</p><p>Not every noun refers to the same <em>kind</em> of thing, though - some are resources, some are views, some are plans, and some are verbs that learned to dress up as nouns to sneak past our attention.</p><p>System 1 can&#x27;t tell them apart - they&#x27;re grammatically identical, so it treats them identically, reaching for whichever one was loudest, earliest, or easiest - the one requiring the least effort to accept.</p><p>System 2 is what asks the second question - not &quot;what is this called?&quot; but &quot;what does it hide?&quot;.</p><p>We&#x27;ve seen how a single concept (&quot;a Tour&quot;) go transformed into a set of interacting concepts - seats availability, reservations, itineraries, and catalogues.</p><p>Each of newly organized terms could be further transformed - either &quot;going up&quot; (generalizing) or going down (specializing), when it comes to a business area.</p><p>But it all takes the effort, especially when a designer (an LLM operator) is not trained enough.</p><p>If we don&#x27;t put enough attention and skills, we are going to base on &quot;the reflexes&quot; - which naturally tend to seeing whatever we already know.</p><p>Nouns are not inherently evil - it is always <a href="https://talesfrom.dev/blog/systems-by-with-for-people">an operator&#x27;s &quot;fault&quot; (ekhm, or responsibility)</a>.</p><p>Watch for absolute-sounding ones, dear Reader.</p><p>Slice them using time, perspectives, and then look for the depth.</p><p>So next time, dear Reader, when the world presents you a bunch of &quot;things&quot;, <a href="https://talesfrom.dev/blog/slow-down">slow down</a> and ask yourself:</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>What absolutism am I looking at?</p>
<p>What perspectives are hidden from my sight?</p>
<p>Where is the time component hidden in this absolutism?</p></div></div></div>]]></content:encoded>
    <pubDate>Sun, 06 Sep 2026 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>design thinking</category><category>domain-driven design</category><category>language patterns</category><category>design patterns</category><category>object-oriented design</category><category>software architecture</category><category>mental models</category><category>communication</category><category>knowledge working</category><category>psychology</category><category>linguistics</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/hands-heads-and-hearts-from-coding-to-caring</guid>
    <title>Hands, heads and hearts: from coding to caring</title>
    <link>https://talesfrom.dev/blog/hands-heads-and-hearts-from-coding-to-caring</link>
    <description>can tokens replace hands, heads or hearts?</description>
    <content:encoded><![CDATA[<h3 id="ship-it"><a href="#ship-it" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Ship it&quot;</h3><p>Imagine <span class="italic font-bold text-cyan-500">Nadia</span>, a few months into her first job, and <span class="italic font-bold text-amber-500">Marek</span>, who reviews her pull requests.</p><p>The codebase is C#. A pragmatic, mid-sized system that calculates discounts for orders.</p><p><span class="italic font-bold text-cyan-500">Nadia</span> was asked to add a new rule - a seasonal discount that stacks with loyalty points, but only under certain conditions.</p><p>She wrote it. Tested it. It worked.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name return-type"><span class="token keyword">decimal</span></span> <span class="token function">ApplySeasonalDiscount</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">decimal</span></span> total<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">int</span></span> loyaltyPoints<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">bool</span></span> isSeasonActive<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>isSeasonActive<span class="token punctuation">)</span> <span class="token keyword">return</span> total<span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> discount <span class="token operator">=</span> loyaltyPoints <span class="token operator">&gt;</span> <span class="token number">100</span> <span class="token punctuation">?</span> <span class="token number">0.15m</span> <span class="token punctuation">:</span> <span class="token number">0.10m</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">return</span> total <span class="token operator">-</span> <span class="token punctuation">(</span>total <span class="token operator">*</span> discount<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div><span class="italic font-bold text-amber-500">Marek, the Lead</span>: This PR looks fine. Tests green?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-cyan-500">Nadia, the Engineer</span>: Yeah, all fifteen scenarios pass. I found a neat way to handle the edge case with zero loyalty points too.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-amber-500">Marek, the Lead</span>: Nice. How long did it take you?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-cyan-500">Nadia, the Engineer</span>: Couple hours. I read up on <code>decimal</code> rounding so I wouldn&#x27;t lose a cent anywhere.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-amber-500">Marek, the Lead</span>: Good instinct. Ship it.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-cyan-500">Nadia, the Engineer</span>: There are already three other methods that look almost like this one, for other discount types. Should I look into that?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-amber-500">Marek, the Lead</span>: Not today. We need this live before the campaign starts.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-cyan-500">Nadia, the Engineer</span>: Ok, makes sense.</div></span></div><p><span class="italic font-bold text-cyan-500">Nadia</span> shipped it.</p><p>The code was clean, the tests were meaningful, the rounding was correct to the cent.</p><p>By any craft standard, this was good work.</p><p>She even noticed the duplication with the other discount methods - a genuinely good catch.</p><p>But she asked, got waved off, and moved on to the next ticket.</p><h3 id="why-does-it-work-this-way"><a href="#why-does-it-work-this-way" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Why does it work this way?&quot;</h3><p>Two years later.</p><p><span class="italic font-bold text-cyan-500">Nadia</span> is no longer new. She has shipped dozens of features, fixed her share of production incidents, and by now she has opinions.</p><p>A new request lands - a fifth discount type, this time combinable with two others under specific business rules that nobody wrote down anywhere.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div><span class="italic font-bold text-amber-500">Marek, the Lead</span>: Same pattern as before - a static method, apply the discount, done. Should be quick.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-cyan-500">Nadia, the Engineer</span>: I want to push back on that a bit. We now have six of these methods, and three of them silently break if you call them in the wrong order.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-amber-500">Marek, the Lead</span>: They&#x27;ve worked fine so far.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-cyan-500">Nadia, the Engineer</span>: They&#x27;ve worked because whoever wired them up in the handler happened to get the order right, by accident, not by design. Nothing stops the next person from getting it wrong.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-amber-500">Marek, the Lead</span>: Fair. What would you do differently?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-cyan-500">Nadia, the Engineer</span>: I think &quot;discount&quot; isn&#x27;t a function, it&#x27;s a concept that deserves its own model - something that knows how to combine with other discounts, or refuse to. Instead of us remembering the rules in our heads every time.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-amber-500">Marek, the Lead</span>: That&#x27;s a bigger change than the ticket asks for.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-cyan-500">Nadia, the Engineer</span>: It is. But if we don&#x27;t do it now, the sixth method becomes the seventh, and eventually nobody can tell you what actually happens to a given order without running it.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-amber-500">Marek, the Lead</span>: Sketch it out. Let&#x27;s look at it together before you write a line of code.</div></span></div><p>Notice what changed.</p><p><span class="italic font-bold text-cyan-500">Nadia</span> was no longer asking &quot;does this compile, do the tests pass&quot; - she was asking &quot;is this the right shape for the problem, and what will it cost us later if it isn&#x27;t&quot;.</p><p>She doubted the given approach.</p><p>She proposed an alternative, defended it, and accepted that it needed a conversation before any code got written.</p><p>She was reasoning about structure, not just output.</p><p>Notice what she did not ask.</p><p>She did not ask whether a fifth discount type made business sense, or whether pricing should be this configurable in the first place.</p><p>She trusted that someone above her had already answered that, and stayed entirely inside the solution space - given that this needs to be built, what is the right way to build it.</p><p>That boundary matters. She was designing. She was not yet questioning why there was anything to design at all.</p><h3 id="would-you-bet-your-money-on-this"><a href="#would-you-bet-your-money-on-this" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Would you bet your money on this?&quot;</h3><p>Another few years pass.</p><p>Same title. Same desk, more or less. <span class="italic font-bold text-cyan-500">Nadia</span> is still an engineer on the same team, and <span class="italic font-bold text-amber-500">Marek</span> is still the lead who reviews her work.</p><p>Nobody promoted her into caring about what happens next. A new initiative arrives from above - a loyalty tier system with five levels, gamified badges, and a leaderboard.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div><span class="italic font-bold text-amber-500">Marek, the Lead</span>: Leadership wants this for the next quarterly release. Big visibility item.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-cyan-500">Nadia, the Engineer</span>: Before we start - what problem does this solve for customers? We haven&#x27;t heard a single complaint about not having a leaderboard.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-amber-500">Marek, the Lead</span>: It&#x27;s meant to increase engagement. Competitors have something similar.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-cyan-500">Nadia, the Engineer</span>: What do you mean by &quot;something similar&quot;?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-amber-500">Marek, the Lead</span>: A points-and-badges thing on their loyalty page. It was in the competitive analysis deck. I haven&#x27;t used it myself, but someone flagged it as a gap versus us.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-cyan-500">Nadia, the Engineer</span>: We have three months of churn data suggesting people leave because checkout is slow during sales, not because they lack a badge. I&#x27;d rather we spend the quarter there.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-amber-500">Marek, the Lead</span>: This came from pretty high up. It&#x27;s not really ours to reprioritize.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-cyan-500">Nadia, the Engineer</span>: I&#x27;m not refusing to build it - nobody asked me to decide, and it&#x27;s not my call to make. I&#x27;m telling you what I&#x27;d bet on with our actual customers, if it were my money. Whatever gets decided, I&#x27;ll build it properly. We make a bet it matters, but it&#x27;s a bet. But I want that data in front of whoever does decide.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-amber-500">Marek, the Lead</span>: Fair. Bring the checkout numbers to the planning meeting and I&#x27;ll make sure the case gets heard.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-cyan-500">Nadia, the Engineer</span>: I&#x27;ll pair with someone from support this week to get the real numbers, not the ones from the dashboard nobody trusts.</div></span></div><p><span class="italic font-bold text-cyan-500">Nadia</span> had no more authority in this room than she had in the first scene. (well, she probably earned something through that time - do you know what it is, dear Reader?)</p><p>Nobody made her responsible for the roadmap. Nobody had to.</p><p>She questioned whether the request was the right one anyway, brought evidence anyway, and committed to building whatever got decided anyway - properly, without sulking about being overruled.</p><p>She cared whether the company&#x27;s money and the customer&#x27;s time were spent well - not just whether her part of the system was elegant, and not because a title told her to.</p><p>She cared about understanding <span class="italic font-bold text-amber-500">Marek</span>&#x27;s point of view and his words - his mental model.</p><h3 id="hands-heads-hearts"><a href="#hands-heads-hearts" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Hand(s), Head(s), Heart(s)</h3><p>Three scenes.</p><p>Same person.</p><p>Different capability each time.</p><p>The first scene - a clean, well-tested discount rule, a good catch on duplication that got waved off - was <strong>Hand(s)</strong>.</p><p>The second - doubting the given approach, proposing a real model instead of a sixth near-identical method - was <strong>Head(s)</strong>.</p><p>The third - questioning whether the leaderboard deserved the quarter at all, and putting her name on that answer - was <strong>Heart(s)</strong>.</p><p>You probably suspected as much while reading them.</p><p>That&#x27;s the point - the labels were never the interesting part. What <span class="italic font-bold text-cyan-500">Nadia</span> actually communicated was.</p><p>How could we explain each lens, in slightly reductionist terms?</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">Hand(s) level</div><div class="pb-2 px-3"><div class="break-words"><p>Execution of a known plan with a given tool - correct, well-crafted, tested.</p>
<p>Exemplary question: &quot;What should I implement?&quot;</p></div></div></div><p> </p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">Head(s) level</div><div class="pb-2 px-3"><div class="break-words"><p>Reasoning about the solution space - design, trade-offs, structure - without yet asking if the problem is worth solving.</p>
<p>Exemplary question: &quot;What are the alternative designs?&quot;</p></div></div></div><p> </p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">Heart(s) level</div><div class="pb-2 px-3"><div class="break-words"><p>Caring whether the plan was worth executing at all - ownership of outcomes, not just output.</p>
<p>Exemplary question: &quot;What is the problem?&quot;</p></div></div></div><p>Notice something about those three definitions, dear Reader.</p><p>You can point at <strong>Hand(s)</strong> - it&#x27;s the diff. You can point at <strong>Head(s)</strong> - it&#x27;s the sketch on the board, the alternative that got argued for in the meeting nobody wanted to sit through.</p><p><strong>Heart(s)</strong> leaves no artifact of its own. It never shows up in the pull request, and no reviewer can approve it into existence.</p><p>It&#x27;s the one ingredient in this whole potion that never makes it onto the label - and the only one that decides whether what you built was worth drinking.</p><p>Together, they&#x27;re the lenses you compose, one on top of another: <strong>Hand(s)</strong>, <strong>Head(s)</strong>, <strong>Heart(s)</strong>.</p><p>Unlike <a href="https://talesfrom.dev/blog/the-ambiguity-of-communication">TEA</a>, this is not a spectrum you move across depending on the situation.</p><p>It&#x27;s a set of lenses, composed together - not swapped one for another.</p><p><span class="italic font-bold text-amber-500">Marek</span> could not have asked <span class="italic font-bold text-cyan-500">Nadia</span> for a design opinion in her first week, because she had nothing yet to doubt with.</p><p>She had to first know what &quot;correct&quot; looked like, with her hands, before she could sense that something was structurally wrong.</p><p>And she had to be trusted with structure, with <strong>Head(s)</strong>, before her opinion on &quot;should we build this at all&quot; carried any weight in the room - no title required either time, just enough demonstrated judgment for people to want to hear it.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Heart(s) require Head(s). Head(s) require Hand(s). You cannot install a lens before the one beneath it and expect the image to focus.</p></div></div></div><h3 id="hands-are-necessary-not-sufficient"><a href="#hands-are-necessary-not-sufficient" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Hand(s) are necessary, not sufficient</h3><p>Let&#x27;s be fair to <strong>Hand(s)</strong>, dear Reader.</p><p>Nobody gets to skip it.</p><p>A designer who cannot write the C# that expresses their own idea is not designing - they&#x27;re speculating, and someone else pays for the gap between the speculation and reality.</p><p>A person with a strong opinion about ownership who cannot ship a working feature is not exercising <strong>Heart(s)</strong> - they&#x27;re just having opinions, which is a much cheaper thing to do.</p><p><span class="italic font-bold text-cyan-500">Nadia</span>&#x27;s clean rounding logic, her fifteen test scenarios, her instinct to notice duplication - none of that stopped mattering once she reached <strong>Head(s)</strong> and <strong>Heart(s)</strong>.</p><p>It became the foundation everything else stands on.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Hand(s) is not the wrong level. Staying at only the Hand(s) level is the wrong choice.</p></div></div></div><h3 id="the-hidden-cost-of-staying-at-hands"><a href="#the-hidden-cost-of-staying-at-hands" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The hidden cost of staying at Hand(s)</h3><p>Here is what should worry you, dear Reader, if you have ever taken pride in shipping fast, and stopped there.</p><p>For a while, it works. It works remarkably well, even.</p><p>Tickets close. Velocity charts go up and to the right. Someone calls you &quot;reliable&quot;.</p><p>Nobody tells us that reliability, at the <strong>Hand(s)</strong> level, is measured by how faithfully you execute someone else&#x27;s understanding of the problem - not by whether that understanding was any good.</p><p>You are not asked &quot;should we build this&quot; because you have not yet earned the standing to be asked, and you have not yet practiced having an opinion worth defending.</p><p><span class="italic font-bold text-cyan-500">Nadia</span> noticed the duplication in her first scene and got told &quot;not today&quot;.</p><p>That&#x27;s not a failure of hers - that&#x27;s simply what <strong>Hand(s)</strong> sounds like from the outside.</p><p>Competent, correct, and not yet invited into the room where the shape of the problem gets decided.</p><p>The codebase does not punish you for staying at <strong>Hand(s)</strong> immediately.</p><p>It punishes whoever is still there in three years, still confident that well-written code and passing tests were the whole job.</p><p>That&#x27;s the dark side of staying at <strong>Hand(s)</strong> too long, dear Reader - not incompetence, but a comfortable kind of invisibility. You get very good at not being asked, and eventually you stop noticing that you&#x27;ve stopped being asked.</p><h3 id="heads-without-hearts"><a href="#heads-without-hearts" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Head(s) without Heart(s)</h3><p>The second failure mode is a bit more subtle, and in some ways more comfortable, which makes it more dangerous.</p><p>You&#x27;ve grown into <strong>Head(s)</strong>. You doubt, you architect, you see the abstraction three moves ahead. People bring you problems because you&#x27;re good at reshaping them.</p><p>And somewhere along the way, it stops mattering to you whether the thing gets built at all, or whether it was worth building.</p><p>You optimize the design of features you don&#x27;t believe in.</p><p>You elegantly implement a leaderboard nobody asked for, because the elegance itself became the reward, detached from whether the customer&#x27;s actual problem</p><p>This is the architect who can defend any decision technically and cannot tell you why the business or consumers should care.</p><p><span class="italic font-bold text-cyan-500">Nadia</span> in her second scene was already close to this - a genuinely better design, argued well, for a ticket she had not yet questioned the existence of.</p><p>It took another round or rounds, and a willingness to say &quot;I don&#x27;t think this deserves our quarter&quot;, to close that gap.</p><p>That&#x27;s the dark side of staying at <strong>Head(s)</strong> too long - skill without meaning.</p><p>The trade-offs get sharper. The diagrams get cleaner.</p><p>Nobody asks anymore whether any of it was worth doing - least of all the person best equipped to ask.</p><h3 id="hearts---investment-or-cost"><a href="#hearts---investment-or-cost" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Heart(s) - investment or cost?</h3><p>The third scene cost <span class="italic font-bold text-cyan-500">Nadia</span> something the first two did not.</p><p>The comfort of just doing what was asked. The safety of being able to say later &quot;I only built what I was told to, it&#x27;s not my call&quot;.</p><p>She traded that comfort for visible disagreement - for going on record against a decision that had already been made above her, with no title obligating her to try and no guarantee anyone would listen.</p><p>This is why so few people arrive at <strong>Heart(s)</strong> (and why organizations often prefer they don&#x27;t?).</p><p>A room full of <strong>Hand(s)</strong> and <strong>Head(s)</strong> executes predictably.</p><p>Probably with the decent quality (whatever it means to you, dear Reader).</p><p>A room with <strong>Heart(s)</strong> in it argues, questions the premise, sometimes says no - and is, over any long enough horizon, the only kind of room that reliably builds things worth having built.</p><p>They argue, because they care.</p><p>Care about what?</p><p>About other <a href="https://talesfrom.dev/blog/systems-by-with-for-people">people</a> - whether they are customers or their colleagues.</p><p>Because nothing great (and valuable) was built when all agreed.</p><p><a href="https://en.wikipedia.org/wiki/Extreme_programming">Extreme Programming</a> was never a set of technical rituals adopted for their own sake - pairing, collective ownership, sustainable pace, whole-team responsibility for the outcome are what <strong>Heart(s)</strong>, practiced daily, actually looks like from the outside.</p><p>You cannot mandate caring with a policy document.</p><p><strong>Heart(s)</strong> requires mutual trust, and mutual is the part organizations skip in favor of procedures, control and governance.</p><p>What came first, dear Reader - the governance, or the lack of trust it was quietly built to compensate for?</p><p><span class="italic font-bold text-cyan-500">Nadia</span> had to trust that &quot;I&#x27;d rather we spend the quarter on checkout&quot; wouldn&#x27;t cost her the next uncomfortable conversation she needed to have. <span class="italic font-bold text-amber-500">Marek</span> had to trust that her pushback was an honest read of the data, not insubordination wearing a lanyard. Remove either half of that trust and the exact same words curdle into either silence or noise.</p><p>You can only build the conditions where people who&#x27;ve already grown through <strong>Hand(s)</strong> and <strong>Head(s)</strong> are trusted enough to start caring out loud - and where that trust is returned, not just extended.</p><p>Quite too idealistic, isn&#x27;t it?</p><p>Maybe.</p><p><strong>Heart(s)</strong> has a dark side too, and it shows up when someone stays there without ever going back down to do the work.</p><p>Caring out loud is cheap once it stops costing you anything.</p><p>Opinions about every decision. Delivered from the sidelines. By someone who hasn&#x27;t shipped a feature or sketched a design in years.</p><p>That still sounds like <strong>Heart(s)</strong>.</p><p>It&#x27;s trust, spent on volume, long after it stopped being earned.</p><p>Everyone in the room can tell the difference. Nobody says it out loud.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Hand(s) make it work (for now).</p>
<p>Head(s) make it right (for now).</p>
<p>Heart(s) make it matter (for now).</p></div></div></div><h3 id="where-does-the-llm-fit-in-this"><a href="#where-does-the-llm-fit-in-this" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Where does the LLM fit in this?</h3><p>I bet, you knew this question was coming, dear Reader.</p><p>Here is the uncomfortable part: an LLM is remarkably good at <strong>Hand(s)</strong>.</p><p>Give it a clear specification (by the way, dear Reader, what is a &quot;clear specification&quot;? How do you know it&#x27;s &quot;clear&quot; - clear to whom, and clear until which surprise arrives?), a language, a test - and it will produce something that compiles, sometimes something well-designed, occasionally something you&#x27;d have written yourself given enough coffee.</p><p>As explored in <a href="https://talesfrom.dev/blog/llms-3d-printers-amplifiers">LLMs, 3D printers and amplifiers</a> - it works as an amplifier of whoever is directing it, not as a replacement for the judgment doing the directing.</p><p>An amplifier has no opinion about whether the song is worth playing.</p><p>It plays whatever signal it is fed, louder.</p><p>There&#x27;s a reason the fit is this good, and it isn&#x27;t flattering to how the profession has treated <strong>Hand(s)</strong>.</p><p>Stripped of <strong>Head(s)</strong> and <strong>Heart(s)</strong>, <strong>Hand(s)</strong> was always a mercenary way of working.</p><p>Grunt labor, however well-crafted.</p><p>Take the specification. Produce the artifact. Move to the next ticket.</p><p>No opinion required. Frequently none welcome.</p><p>It was already transactional - and transactional work is exactly what a model trained on transactions reproduces well.</p><p><strong>Head(s)</strong> asks for something it cannot manufacture on demand.</p><p>Reasoning about optionality. About <a href="https://talesfrom.dev/blog/composing-a-pie">the structure - elements, interactions and purpose</a> - an architecture should have. About which trade-off costs less in eighteen months.</p><p>It can list you three options when asked.</p><p>It cannot sit with the discomfort of not yet knowing which one is right.</p><p>It has no stake in being wrong about it.</p><p><strong>Heart(s)</strong> sits further out still.</p><p>It isn&#x27;t really a technical faculty to begin with - it&#x27;s a humane, social one.</p><p>Whether a leaderboard deserves a quarter of a real team&#x27;s time is not a question about code.</p><p>It&#x27;s a question about people - what a company owes the customer in front of it, versus what it owes its own comfort.</p><p>And people doesn&#x27;t stop at the customer. It includes the teammate who inherits whatever gets decided here.</p><p>&quot;What do you have in mind?&quot;</p><p>&quot;What does it mean to you?&quot;</p><p>&quot;What is it important to you?&quot;</p><p>Ask them of a customer. Ask them of a colleague. The question doesn&#x27;t change - only who&#x27;s answering it does.</p><p>It&#x27;s <a href="https://talesfrom.dev/blog/systems-by-with-for-people">by, with, and for people</a>, all the way down.</p><p>A model has no colleagues to let down. No customer to fail. No finite quarter of its own working life to spend on the wrong bet.</p><p>It cannot care, in any sense worth the word.</p><p>Caring requires something to lose.</p><p>Which means the era in which &quot;I write well-crafted code quickly&quot; was, on its own, a durable professional identity is quietly closing - not because writing it well stopped mattering, but because the scarce part of that sentence was never the typing.</p><p>But <strong>Heart(s)</strong> does not get to skip looking at what <strong>Hand(s)</strong> produced.</p><p>Someone still has to read the diff.</p><p>It makes no difference whether the <strong>Hand(s)</strong> that typed it were biological or virtual - a person&#x27;s, or a model&#x27;s, prompted by that same person.</p><p>If <strong>Hand(s)</strong>, purely as execution speed, is now something you can rent by the token, then the only thing left that was ever actually yours is the <strong>Head(s)</strong> that decided what to build, and the <strong>Heart(s)</strong> that decided whether it deserved to exist (and how you are communicating with other human beings).</p><p>That should not read as a threat, dear Reader, though I understand if it does.</p><p>&quot;Typing was never the bottleneck&quot;, some might boldly say so.</p><p>Even if it was not the bottleneck, building understanding through fast feedback loops was.</p><p>Learning is a real bottleneck.</p><p>Knowledge acquisition is a real bottleneck too.</p><p>Insights and conceptual framing are bottlenecks as well.</p><p>Typing might and often helps with that.</p><p>Why?</p><p>Typing is thinking.</p><p>It was simply the most visible part of the job, and the easiest one to reward.</p><p>We tricked ourselves, stakeholders included, into thinking that coding, <strong>Hand(s)</strong>, was the entirety of the work.</p><p>There&#x27;s more to it than that, we just need to escape <a href="https://talesfrom.dev/blog/the-inverse-matrix-problem">the matrix</a>.</p><h3 id="composing-not-switching"><a href="#composing-not-switching" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Composing, not switching</h3><p>In <a href="https://talesfrom.dev/blog/the-ambiguity-of-communication">TEA</a>, where you consciously move between <strong>Telling</strong>, <strong>Explaining</strong> and <strong>Aligning</strong> depending on what a given conversation needs, <strong>Hand(s)</strong>, <strong>Head(s)</strong> and <strong>Heart(s)</strong> don&#x27;t offer you that choice in the same way.</p><p>You do not wake up and decide to &quot;do some <strong>Heart(s)</strong> today&quot; the way you might decide to explain something more carefully.</p><p>You add a lens, and mostly, you don&#x27;t remove the ones beneath it - you keep looking through every lens you&#x27;ve already installed, every day, for the rest of your career.</p><p><span class="italic font-bold text-cyan-500">Nadia</span> at the <strong>Heart(s)</strong> level still writes C# on a Tuesday when the team needs her to - through the <strong>Hand(s)</strong> lens, same as always.</p><p>She still doubts a design on a Wednesday - through <strong>Head(s)</strong>.</p><p>The difference is that she no longer sees through either lens alone. <strong>Heart(s)</strong> sits on top now, and everything below it gets seen through it too.</p><h3 id="what-are-you-doing"><a href="#what-are-you-doing" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;What are you doing?&quot;</h3><p>You&#x27;ve heard some version of this one already, dear Reader.</p><p>Three stonemasons, same building site, same question put to each of them: &quot;What are you doing?&quot;</p><p>The first says: &quot;I&#x27;m laying bricks.&quot;</p><p>The second says: &quot;I&#x27;m building a wall.&quot;</p><p>The third says: &quot;I&#x27;m building a cathedral.&quot;</p><p>Same bricks. Same mortar. Same hands.</p><p>Really same?</p><p>&quot;The level is in the eyes of the beholder.&quot;</p><p>The first looks through <strong>Hand(s)</strong> - one brick set correctly after another, according to the pattern he was handed. (sometimes without care and understanding, unfortunately)</p><p>The second looks through <strong>Head(s)</strong> - the brick matters because of the wall, the load it carries, the plan it has to satisfy. (sometimes without seeing the bigger picture, unfortunately)</p><p>The third looks through <strong>Heart(s)</strong> - the wall matters because of the cathedral, and the cathedral matters because of who will stand inside it, long after his own name is forgotten.</p><p>None of the three is lying.</p><p>None of them is wrong, exactly.</p><p>Same as with this well-known motivational tale about stonemasons,<strong>Hand(s)</strong>, <strong>Head(s)</strong> and <strong>Heart(s)</strong> are here to communicate something more profound over a simple metaphor.</p><p>Metaphors are imperfect, but they can help us see the world in new ways.</p><p>Looking for logical holes and inconsistencies in metaphors can be a useful exercise, but it&#x27;s not the primary goal.</p><p>Be free with your interpretations.</p><p>Be free with your tempo.</p><p>Be free.</p><p>Play with that.</p><p>Let yourself flow with the uncharted sensations that are true vessels of understanding.</p><p>Understanding of thyself.</p><p>Understanding of the world around you.</p><h3 id="starting-small"><a href="#starting-small" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Starting small</h3><p>You don&#x27;t need a promotion to start installing the next lens.</p><p>It starts with a single question the next time you&#x27;re handed a ticket.</p><p>Or more general, questioning.</p><p>The gap between <strong>Hand(s)</strong> and the lenses stacked above it is not talent, dear Reader.</p><p>It is curiosity.</p><p>It is hard work.</p><p>It is <a href="https://talesfrom.dev/blog/slow-down">slowing down</a>.</p><p>It is saying <a href="https://talesfrom.dev/blog/i-dont-know">&quot;I don&#x27;t know&quot;</a>.</p><p>It is mostly the accumulated habit of not being asked, and therefore never practicing the answer.</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>Which level do you usually operate at?</p></div></div></div>]]></content:encoded>
    <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>software architecture</category><category>mental models</category><category>craftsmanship</category><category>extreme programming</category><category>knowledge working</category><category>tools and capabilities</category><category>psychology</category><category>philosophy</category><category>career growth</category><category>ownership</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/the-ambiguity-of-requirements</guid>
    <title>The ambiguity of requirements: features, questions, understanding</title>
    <link>https://talesfrom.dev/blog/the-ambiguity-of-requirements</link>
    <description>what can a simple calculator teach you about business?</description>
    <content:encoded><![CDATA[<h3 id="how-can-we-help"><a href="#how-can-we-help" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>How can we help?</h3><p>Meet Tom (you might recall him from <a href="https://talesfrom.dev/blog/many-faces-of-ddd-aggregates-in-fsharp">Many Faces of DDD Aggregates in F#</a>) and from <a href="https://talesfrom.dev/blog/the-ambiguity-the-curse-and-the-fallacy-of-domain-model">The ambiguity, the curse and the fallacy of domain model</a>).</p><p>As a successful businessman, after he earned tons of money with disco clubs and creating video games, with his business nose, he felt there&#x27;s a niche in the market.</p><div class="flex flex-col "><div class="flex flex-col"><div class="flex justify-center items-center flex-col"><div class="flex max-sm:flex-col justify-between items-center"><img src="https://talesfrom.dev/static/images/business-man.png" class="max-h-[30rem]"/><div class="flex flex-col justify-between text-left"><span>Tom says:</span><span class="my-4 italic"><span class=""><p>Hi there! Long time, no see.</p></span><span class=""><p>I got an amazing idea - &quot;thanks&quot; to LLMs and AI technologies people forget things easily.</p></span><div class="my-3"><span class="">Sooner or later, they will forget how to </span><span class="mr-2">calculate a simple division</span><span class="">!</span></div><span class=""><p>Can you help me with building a service around it?</p></span><span class=""><p>It will have a bunch of features, but nothing too complicated.</p></span></span></div></div></div></div><div class="flex justify-around mt-10 lg:mx-32"><button class="bg-gray-600 border-gray-100 text-gray-400 p-2 rounded">Just talk</button><button class="bg-green-700 text-white border-2 p-2 rounded">Listening carefully</button></div></div><p>A division?</p><p>It seems we need to explore this area a bit more.</p><p>Good that we have Tom to guide us and we are pretty skilled with collaborative exploration.</p><p>Let&#x27;s have a quick event storming session! (because that&#x27;s what cool kids do, right?)</p><p>&quot;Ok, tell us more about the division - what is it all about?&quot;, we asked.</p><p>After this little question, we spent 1 hour exploring Tom&#x27;s idea (during which Tom mostly rambled about how great it is) and it turned out we didn&#x27;t capture that many business facts.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-requirements-naive-exploration.png" class="max-h-[20rem]"/></div><div class="italic mx-24">the output from our exploration</div></div><p>It was quite hard to cut in Tom&#x27;s enthusiastic monologue, so we ended up with not-so-clear idea of his idea (pun intended).</p><h3 id="specification-by-example-to-the-rescue"><a href="#specification-by-example-to-the-rescue" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Specification by example to the rescue!</h3><p>Maybe it&#x27;s time to involve Tom in more concrete examples and scenarios to clarify his idea?</p><p>Definitely we should go and ask him to walk us through a few specific cases.</p><p>It will help us with implementing this feature.</p><div class="flex flex-col "><div class="flex flex-col"><div class="flex justify-center items-center flex-col"><div class="flex max-sm:flex-col justify-between items-center"><img src="https://talesfrom.dev/static/images/business-man.png" class="max-h-[30rem]"/><div class="flex flex-col justify-between text-left"><span>Tom says:</span><span class="my-4 italic"><span class=""><p>Special cases?</p></span><div class="my-3"><span class="">I don&#x27;t know what might be special in </span><span class="mr-2">the division</span><span class="">, but let me try to explain it!</span></div></span></div></div></div></div><div class="flex justify-around mt-10 lg:mx-32"><button class="bg-gray-600 border-gray-100 text-gray-400 p-2 rounded">Just talk</button><button class="bg-green-700 text-white border-2 p-2 rounded">Listening carefully</button></div></div><p>And we went into executable specifications mode, trying to nail down the details of his idea.</p><p><a href="consumer-expected-need-driven-behavior-development">Outside-In development</a> perspective is deeply rooted in our heart, so we started from writing down a need-driven, executable, acceptance criteria.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line">    <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Theory</span></span><span class="token punctuation">]</span>
</span><span class="code-line">    <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">InlineData</span><span class="token attribute-arguments"><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">)</span></span></span><span class="token punctuation">]</span>
</span><span class="code-line">    <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">InlineData</span><span class="token attribute-arguments"><span class="token punctuation">(</span><span class="token number">9</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span></span></span><span class="token punctuation">]</span>
</span><span class="code-line">    <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">InlineData</span><span class="token attribute-arguments"><span class="token punctuation">(</span><span class="token number">7</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3.5</span><span class="token punctuation">)</span></span></span><span class="token punctuation">]</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">given_dividend_and_divisor_when_dividing_then_returns_expected_result</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">int</span></span> x<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">int</span></span> y<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">double</span></span> expected<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> response <span class="token operator">=</span> <span class="token keyword">await</span> _client<span class="token punctuation">.</span><span class="token function">GetAsync</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;/divide/</span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">x</span><span class="token punctuation">}</span></span><span class="token string">/by/</span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">y</span><span class="token punctuation">}</span></span><span class="token string">&quot;</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">        response<span class="token punctuation">.</span><span class="token function">EnsureSuccessStatusCode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> result <span class="token operator">=</span> <span class="token keyword">await</span> response<span class="token punctuation">.</span>Content<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">ReadFromJsonAsync</span><span class="token class-name generic"><span class="token punctuation">&lt;</span><span class="token keyword">double</span><span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        Assert<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span>expected<span class="token punctuation">,</span> result<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span></code></pre></div></div><p>Next step in our <a href="https://talesfrom.dev/blog/tdd-specify-satisfy-simplify">3S workflow</a> is to satisfy the specification, we write down the implementation to make the tests pass.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line">app<span class="token punctuation">.</span><span class="token function">MapGet</span><span class="token punctuation">(</span><span class="token string">&quot;/divide/{x}/by/{y}&quot;</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">int</span></span> x<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">int</span></span> y<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">(</span><span class="token keyword">double</span><span class="token punctuation">)</span>x <span class="token operator">/</span> y<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre></div></div><p>And puff, tests got green.</p><p>Tom gave us happy-path examples and of course we asked him about &quot;the special case&quot;.</p><p>&quot;You don&#x27;t know what is the &#x27;special&#x27; case of division? I told you people will forget that!&quot;, he yelled.</p><p>&quot;Dividing by zero, of course!&quot;, he continued, a bit calmer this time.</p><p>So we captured that as an executable specification too.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line">    <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">given_a_dividend_and_zero_as_divisor_when_dividing_then_returns_unprocessable_entity_with_problem_details</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> response <span class="token operator">=</span> <span class="token keyword">await</span> _client<span class="token punctuation">.</span><span class="token function">GetAsync</span><span class="token punctuation">(</span><span class="token string">&quot;/divide/10/by/0&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">        Assert<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span>HttpStatusCode<span class="token punctuation">.</span>UnprocessableEntity<span class="token punctuation">,</span> response<span class="token punctuation">.</span>StatusCode<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> problemDetails <span class="token operator">=</span> <span class="token keyword">await</span> response<span class="token punctuation">.</span>Content<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">ReadFromJsonAsync</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>ProblemDetails<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        Assert<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span><span class="token string">&quot;Cannot divide by zero.&quot;</span><span class="token punctuation">,</span> problemDetails<span class="token punctuation">?.</span>Detail<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span></code></pre></div></div><p>Back to satisfying the specification, we extend the handler to cover the zero-divisor case.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line">app<span class="token punctuation">.</span><span class="token function">MapGet</span><span class="token punctuation">(</span><span class="token string">&quot;/divide/{x}/by/{y}&quot;</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">int</span></span> x<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">int</span></span> y<span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
</span><span class="code-line">    y <span class="token operator">==</span> <span class="token number">0</span>
</span><span class="code-line">        <span class="token punctuation">?</span> Results<span class="token punctuation">.</span><span class="token function">Problem</span><span class="token punctuation">(</span><span class="token punctuation named-parameter">detail</span><span class="token punctuation">:</span> <span class="token string">&quot;Cannot divide by zero.&quot;</span><span class="token punctuation">,</span> <span class="token punctuation named-parameter">statusCode</span><span class="token punctuation">:</span> StatusCodes<span class="token punctuation">.</span>Status422UnprocessableEntity<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">:</span> Results<span class="token punctuation">.</span><span class="token function">Ok</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token keyword">double</span><span class="token punctuation">)</span>x <span class="token operator">/</span> y<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre></div></div><p>It&#x27;s a bit of a shame that we didn&#x27;t figure it out earlier, but at least we have a clear specification now, right?</p><p>Close collaboration definitely helped distilling the domain part of the problem. We could follow the <a href="https://talesfrom.dev/blog/tdd-specify-satisfy-simplify">3S workflow</a> and follow up the simplification phase and refactor toward a real <a href="https://talesfrom.dev/blog/the-ambiguity-the-curse-and-the-fallacy-of-domain-model">domain model</a>.</p><p>So the arithmetic and its failure mode moved out of the handler and into a <code>Calculation</code> that knows how to <code>Divide</code>.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">Calculation</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name return-type">Result<span class="token punctuation">&lt;</span><span class="token keyword">double</span><span class="token punctuation">&gt;</span></span> <span class="token function">Divide</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">int</span></span> x<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">int</span></span> y<span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
</span><span class="code-line">        y <span class="token operator">==</span> <span class="token number">0</span>
</span><span class="code-line">            <span class="token punctuation">?</span> Result<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Failure</span><span class="token class-name generic"><span class="token punctuation">&lt;</span><span class="token keyword">double</span><span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token string">&quot;Cannot divide by zero.&quot;</span><span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token punctuation">:</span> Result<span class="token punctuation">.</span><span class="token function">Success</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token keyword">double</span><span class="token punctuation">)</span>x <span class="token operator">/</span> y<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>And the handler shrunk down to translating that result into an HTTP response.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line">app<span class="token punctuation">.</span><span class="token function">MapGet</span><span class="token punctuation">(</span><span class="token string">&quot;/divide/{x}/by/{y}&quot;</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">int</span></span> x<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">int</span></span> y<span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> result <span class="token operator">=</span> Calculation<span class="token punctuation">.</span><span class="token function">Divide</span><span class="token punctuation">(</span>x<span class="token punctuation">,</span> y<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">return</span> <span class="token class-name return-type">result<span class="token punctuation">.</span>IsSuccess
</span></span><span class="code-line"><span class="token class-name return-type">        <span class="token punctuation">?</span></span> Results<span class="token punctuation">.</span><span class="token function">Ok</span><span class="token punctuation">(</span>result<span class="token punctuation">.</span>Value<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">:</span> Results<span class="token punctuation">.</span><span class="token function">Problem</span><span class="token punctuation">(</span><span class="token punctuation named-parameter">detail</span><span class="token punctuation">:</span> result<span class="token punctuation">.</span>Error<span class="token punctuation">,</span> <span class="token punctuation named-parameter">statusCode</span><span class="token punctuation">:</span> StatusCodes<span class="token punctuation">.</span>Status422UnprocessableEntity<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre></div></div><p>Tests stayed green, but now the rule &quot;you cannot divide by zero&quot; lives in one obvious place instead of being tangled with routing and HTTP status codes.</p><p>That&#x27;s the software engineering way: yeehaa!</p><p>Because we were modelling together, Tom saw <a href="https://talesfrom.dev/blog/the-ambiguity-of-code">the code</a> and wasn&#x27;t even impressed by the usage of <code>Result</code>.</p><p>Poor Tom is not aware of monads.</p><p>We could also improve <a href="https://talesfrom.dev/blog/the-ambiguity-of-code">the code</a> and <a href="https://talesfrom.dev/blog/map-dont-ask">map, don&#x27;t ask</a>.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line">app<span class="token punctuation">.</span><span class="token function">MapGet</span><span class="token punctuation">(</span><span class="token string">&quot;/divide/{x}/by/{y}&quot;</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">int</span></span> x<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">int</span></span> y<span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
</span><span class="code-line">    Calculation<span class="token punctuation">.</span><span class="token function">Divide</span><span class="token punctuation">(</span>x<span class="token punctuation">,</span> y<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Match</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token punctuation named-parameter">onSuccess</span><span class="token punctuation">:</span> <span class="token keyword">value</span> <span class="token operator">=&gt;</span> Results<span class="token punctuation">.</span><span class="token function">Ok</span><span class="token punctuation">(</span><span class="token keyword">value</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token punctuation named-parameter">onFailure</span><span class="token punctuation">:</span> error <span class="token operator">=&gt;</span> Results<span class="token punctuation">.</span><span class="token function">Problem</span><span class="token punctuation">(</span><span class="token punctuation named-parameter">detail</span><span class="token punctuation">:</span> error<span class="token punctuation">,</span> <span class="token punctuation named-parameter">statusCode</span><span class="token punctuation">:</span> StatusCodes<span class="token punctuation">.</span>Status422UnprocessableEntity<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre></div></div><p>Functional-first thinking baby!</p><p>This time we don&#x27;t even show it to Tom, he wouldn&#x27;t admire the greatness of it.</p><p>Ah, we also forgot about publishing events - as we explored the domain earlier, wouldn&#x27;t it be a waste if we didn&#x27;t do it?</p><p>Let&#x27;s add missing specs.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line">    <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">given_a_dividend_and_a_non_zero_divisor_when_dividing_then_publishes_division_calculation_completed</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> eventTracker <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">FakeEventTracker</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> client <span class="token operator">=</span> _factory
</span><span class="code-line">            <span class="token punctuation">.</span><span class="token function">WithWebHostBuilder</span><span class="token punctuation">(</span>builder <span class="token operator">=&gt;</span> builder<span class="token punctuation">.</span><span class="token function">ConfigureServices</span><span class="token punctuation">(</span>services <span class="token operator">=&gt;</span>
</span><span class="code-line">                services<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">AddSingleton</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>IPublishEvent<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span>eventTracker<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token punctuation">.</span><span class="token function">CreateClient</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token keyword">await</span> client<span class="token punctuation">.</span><span class="token function">GetAsync</span><span class="token punctuation">(</span><span class="token string">&quot;/divide/10/by/2&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> completed <span class="token operator">=</span> Assert<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">IsType</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>DivisionCalculationCompleted<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span>Assert<span class="token punctuation">.</span><span class="token function">Single</span><span class="token punctuation">(</span>eventTracker<span class="token punctuation">.</span>Events<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        Assert<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">,</span> completed<span class="token punctuation">.</span>Dividend<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        Assert<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> completed<span class="token punctuation">.</span>Divisor<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        Assert<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">,</span> completed<span class="token punctuation">.</span>Result<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">given_a_dividend_and_zero_as_divisor_when_dividing_then_publishes_calculating_division_failed</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> eventTracker <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">FakeEventTracker</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> client <span class="token operator">=</span> _factory
</span><span class="code-line">            <span class="token punctuation">.</span><span class="token function">WithWebHostBuilder</span><span class="token punctuation">(</span>builder <span class="token operator">=&gt;</span> builder<span class="token punctuation">.</span><span class="token function">ConfigureServices</span><span class="token punctuation">(</span>services <span class="token operator">=&gt;</span>
</span><span class="code-line">                services<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">AddSingleton</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>IPublishEvent<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span>eventTracker<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token punctuation">.</span><span class="token function">CreateClient</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token keyword">await</span> client<span class="token punctuation">.</span><span class="token function">GetAsync</span><span class="token punctuation">(</span><span class="token string">&quot;/divide/10/by/0&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> failed <span class="token operator">=</span> Assert<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">IsType</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>CalculatingDivisionFailed<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span>Assert<span class="token punctuation">.</span><span class="token function">Single</span><span class="token punctuation">(</span>eventTracker<span class="token punctuation">.</span>Events<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        Assert<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">,</span> failed<span class="token punctuation">.</span>Dividend<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        Assert<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> failed<span class="token punctuation">.</span>Divisor<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        Assert<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span><span class="token string">&quot;Cannot divide by zero.&quot;</span><span class="token punctuation">,</span> failed<span class="token punctuation">.</span>Reason<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">private</span> <span class="token keyword">class</span> <span class="token class-name">FakeEventTracker</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">IPublishEvent</span></span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">public</span> <span class="token class-name return-type">List<span class="token punctuation">&lt;</span><span class="token keyword">object</span><span class="token punctuation">&gt;</span></span> Events <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token keyword">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token keyword">public</span> <span class="token class-name return-type">Task</span> <span class="token generic-method"><span class="token function">Publish</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>TEvent<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token class-name">TEvent</span> @<span class="token keyword">event</span><span class="token punctuation">)</span> <span class="token keyword">where</span> <span class="token class-name">TEvent</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token keyword">notnull</span></span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            Events<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span>@<span class="token keyword">event</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token keyword">return</span> Task<span class="token punctuation">.</span>CompletedTask<span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span></code></pre></div></div><p>Specs complete!</p><p>Are we done?</p><h3 id="the-m-word"><a href="#the-m-word" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The M-word?</h3><p>What is the M-word that Tom is mostly interested in?</p><p>No, it&#x27;s not Monads, sorry.</p><p>It&#x27;s M-oney.</p><div class="flex flex-col "><div class="flex flex-col"><div class="flex justify-center items-center flex-col"><div class="flex max-sm:flex-col justify-between items-center"><img src="https://talesfrom.dev/static/images/business-man.png" class="max-h-[30rem]"/><div class="flex flex-col justify-between text-left"><span>Tom says:</span><span class="my-4 italic"><span class=""><p>Finally, we talk about money.</p></span><span class=""><p>I saw this division in action, but it&#x27;s nothing amazing, to be fair.</p></span><span class=""><p>As soon as people start forgetting how to divide because of LLMs, we are going to be rich.</p></span><span class=""><p>You might wonder - how?</p></span><span class=""><p>That is simple.</p></span><div class="my-3"><span class="mr-2">Whenever a calculation is performed, we charge the user a small amount of money</span><span class="">, that&#x27;s it.</span></div><span class=""><p>They will not notice it, because it&#x27;ll be so small.</p></span><span class=""><p>Millions of users, times a small amount, adds up quickly.</p></span></span></div></div></div></div><div class="flex justify-around mt-10 lg:mx-32"><button class="bg-gray-600 border-gray-100 text-gray-400 p-2 rounded">Just talk</button><button class="bg-green-700 text-white border-2 p-2 rounded">Listening carefully</button></div></div><p>Division feature was super <a href="https://talesfrom.dev/blog/simple-isnt-easy">easy</a>, the domain was trivial - we know how to divide.</p><p>Ok, charging users might be more interesting.</p><p>Thankfully, we know that <a href="https://talesfrom.dev/blog/the-ambiguity-of-communication">communication</a> at the right level is vastly important and that <a href="https://talesfrom.dev/blog/the-ambiguity-of-team-work">collaboration</a> is the key to success - that&#x27;s why we invited Tom back to the event storming board.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-requirements-naive-exploration-with-policy.png" class="max-h-[20rem]"/></div><div class="italic mx-24">the output from our exploration</div></div><p>If you listened carefully, dear Reader, you might have noticed that there &quot;whenever&quot; keyword appeard in Tom&#x27;s message.</p><p>If we take <a href="https://leanpub.com/introducing_eventstorming">an interpretation of Alberto&#x27;s picture that explains (almost) everything</a>, you might recall we might be talking about <strong>a policy</strong>.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/functions-and-facts-describe-the-world-interpretation-albertos-picture.png" class="max-h-[35rem]"/></div></div><p>It sounded as if we are going to transform <code>DivisionCalculationCompleted</code> into a command <code>ChargeUser</code> that will eventually lead to a fact <code>UserCharged</code> happening.</p><p>That&#x27;s definitely our a brilliant observation - domain modelling in its fullness!</p><p>Tom was not that impressed - we put some more stickies, but for him it was pretty obvious - that&#x27;s what he <em>exactly said</em>, isn&#x27;t it?</p><p>We tried to <a href="https://talesfrom.dev/blog/the-ambiguity-of-communication">tell</a> him what we have discovered, why <span class="italic text-orange-500">events</span> are important, what is a <span class="italic text-blue-500">command</span>, and what a <span class="italic text-violet-400">policy</span> means - but he wasn&#x27;t that interested.</p><p>It&#x27;s not his area of expertise, maybe that&#x27;s why he is not seeing <em>the depth</em> of our work.</p><p>To complete the session, let&#x27;s add missing commands.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-requirements-naive-exploration-with-policy-and-commands.png" class="max-h-[20rem]"/></div></div><p>Seems like we understood what is required by Tom, let&#x27;s finally go to the code.</p><p>We are charging a user, so definitely we need to create <a href="https://talesfrom.dev/blog/the-ambiguity-the-curse-and-the-fallacy-of-domain-model">the domain model</a> that will represent this concept of <code>a User</code>.</p><p><a href="https://talesfrom.dev/blog/modeling-maturity-levels">What information</a> do we need <code>User</code> to have in order to satisfy Tom&#x27;s requirements?</p><p>Definitely some identification - who they are.</p><p>Then some details needed to charge them - for transferring money.</p><p>We quickly sketched what &quot;charging a user&quot; probably needs. Surely, a <code>User</code> with some billing details bolted on will do?</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">User</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">Guid</span> Id <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> FirstName <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> LastName <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> Email <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> CreditCardNumber <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">DateTime</span> CreditCardExpiry <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Looks reasonable, doesn&#x27;t it? A name, an email, and just enough fields to charge someone.</p><p>Of course we know that our models should be focused on behaviors rather than just data.</p><p>But we will express it as an executable spec!</p><h3 id="whenever"><a href="#whenever" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Whenever&quot;</h3><p>Thankfully, we listened carefully and we know that a policy means a reaction - so we need to create an event listener that will do the proper transformation of incoming <span class="italic text-orange-500">event</span> into a <span class="italic text-blue-500">command</span>.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line">    <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">given_a_dividend_and_a_non_zero_divisor_when_division_calculation_completed_then_user_is_charged_with_tiny_fee</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> user <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">User</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            CreditCardNumber <span class="token operator">=</span> <span class="token string">&quot;4111111111111111&quot;</span><span class="token punctuation">,</span>
</span><span class="code-line">            CreditCardExpiry <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">DateTime</span><span class="token punctuation">(</span><span class="token number">2030</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
</span><span class="code-line">            BaseCalculationFee <span class="token operator">=</span> <span class="token number">0.01m</span>
</span><span class="code-line">        <span class="token punctuation">}</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> gateway <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">FakePaymentGateway</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> client <span class="token operator">=</span> _webApplicationFactory
</span><span class="code-line">            <span class="token punctuation">.</span><span class="token function">WithWebHostBuilder</span><span class="token punctuation">(</span>builder <span class="token operator">=&gt;</span> builder<span class="token punctuation">.</span><span class="token function">ConfigureServices</span><span class="token punctuation">(</span>services <span class="token operator">=&gt;</span>
</span><span class="code-line">            <span class="token punctuation">{</span>
</span><span class="code-line">                services<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">AddSingleton</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>IUsersRepository<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name constructor-invocation">FakeUsersRepository</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">                services<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">AddSingleton</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>IPaymentGateway<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span>gateway<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token punctuation">.</span><span class="token function">CreateClient</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token keyword">await</span> client<span class="token punctuation">.</span><span class="token function">GetAsync</span><span class="token punctuation">(</span><span class="token string">&quot;/divide/10/by/2&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> transfer <span class="token operator">=</span> Assert<span class="token punctuation">.</span><span class="token function">Single</span><span class="token punctuation">(</span>gateway<span class="token punctuation">.</span>Transfers<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        Assert<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span>user<span class="token punctuation">.</span>CreditCardNumber<span class="token punctuation">,</span> transfer<span class="token punctuation">.</span>CardNumber<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        Assert<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span>user<span class="token punctuation">.</span>CreditCardExpiry<span class="token punctuation">,</span> transfer<span class="token punctuation">.</span>CardExpiry<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        Assert<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span>user<span class="token punctuation">.</span>BaseCalculationFee<span class="token punctuation">,</span> transfer<span class="token punctuation">.</span>Amount<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">private</span> <span class="token keyword">class</span> <span class="token class-name">FakeUsersRepository</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">IUsersRepository</span></span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">private</span> <span class="token keyword">readonly</span> <span class="token class-name">User</span> _user<span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token keyword">public</span> <span class="token function">FakeUsersRepository</span><span class="token punctuation">(</span><span class="token class-name">User</span> user<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> _user <span class="token operator">=</span> user<span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token keyword">public</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>User<span class="token punctuation">&gt;</span></span> <span class="token function">GetAsync</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> id<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> Task<span class="token punctuation">.</span><span class="token function">FromResult</span><span class="token punctuation">(</span>_user<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">private</span> <span class="token keyword">class</span> <span class="token class-name">FakePaymentGateway</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">IPaymentGateway</span></span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">public</span> <span class="token class-name return-type">List<span class="token punctuation">&lt;</span>PaymentDetails<span class="token punctuation">&gt;</span></span> Transfers <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token keyword">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token keyword">public</span> <span class="token class-name return-type">Task</span> <span class="token function">Transfer</span><span class="token punctuation">(</span><span class="token class-name">PaymentDetails</span> details<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            Transfers<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span>details<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token keyword">return</span> Task<span class="token punctuation">.</span>CompletedTask<span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Of course, the spec fails as there is no logic built-in that will ensure the required behavior - let&#x27;s add it!</p><p>First, <code>IPublishEvent</code> needs a partner in crime - something that lets a reaction subscribe to the events flowing through it.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">IHandleEvent<span class="token punctuation">&lt;</span>TEvent<span class="token punctuation">&gt;</span></span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name return-type">Task</span> <span class="token function">Handle</span><span class="token punctuation">(</span><span class="token class-name">TEvent</span> @<span class="token keyword">event</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Object providing this <a href="https://talesfrom.dev/blog/cocoa-from-ports-and-adapters-to-concepts-capabilities-providers">capability</a> will get the easiest (requiring the lowest effort) implementation - so we&#x27;ll omit it for brevity.</p><p><code>User</code> is going to be much more interesting element, because we want it to be fully <a href="https://talesfrom.dev/blog/the-ambiguity-of-objects">object-oriented</a>.</p><p>What does it actually mean?</p><p>A <code>User</code> knows how to charge itself, given a gateway and its own tiny fee - behavioral modelling for the win!</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">User</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">Guid</span> Id <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> FirstName <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> LastName <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> Email <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> CreditCardNumber <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">DateTime</span> CreditCardExpiry <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">decimal</span></span> BaseCalculationFee <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">Charge</span><span class="token punctuation">(</span><span class="token class-name">IPaymentGateway</span> @<span class="token keyword">using</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> gateway <span class="token operator">=</span> @<span class="token keyword">using</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">await</span> gateway<span class="token punctuation">.</span><span class="token function">Transfer</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name constructor-invocation">PaymentDetails</span><span class="token punctuation">(</span>CreditCardNumber<span class="token punctuation">,</span> CreditCardExpiry<span class="token punctuation">,</span> BaseCalculationFee<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>The policy, the event handler, works with its collaborators to actually deliver specified behavior.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">record</span> <span class="token class-name">DivisionCalculationCompletedEventHandler</span><span class="token punctuation">(</span>
</span><span class="code-line">    <span class="token class-name">IUsersRepository</span> Users<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">IPaymentGateway</span> Gateway
</span><span class="code-line"><span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">IHandleEvent<span class="token punctuation">&lt;</span>DivisionCalculationCompleted<span class="token punctuation">&gt;</span></span></span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">Handle</span><span class="token punctuation">(</span><span class="token class-name">DivisionCalculationCompleted</span> @<span class="token keyword">event</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> user <span class="token operator">=</span> <span class="token keyword">await</span> Users<span class="token punctuation">.</span><span class="token function">GetAsync</span><span class="token punctuation">(</span>@<span class="token keyword">event</span><span class="token punctuation">.</span>CustomerId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">await</span> user<span class="token punctuation">.</span><span class="token function">Charge</span><span class="token punctuation">(</span>@<span class="token keyword">using</span><span class="token punctuation">:</span> Gateway<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">await</span> Users<span class="token punctuation">.</span><span class="token function">SaveAsync</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>And finally, the policy subscribes to a particular event - <code>DivisionCalculationCompleted</code>.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line">builder<span class="token punctuation">.</span>Services<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">AddScoped</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>DivisionCalculationCompletedEventHandler<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">builder<span class="token punctuation">.</span>Services<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">AddSingleton</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>IPublishEvent<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span>services <span class="token operator">=&gt;</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">InMemoryMessageBus</span><span class="token punctuation">(</span>services<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token class-name"><span class="token keyword">var</span></span> bus <span class="token operator">=</span> <span class="token punctuation">(</span>InMemoryMessageBus<span class="token punctuation">)</span>app<span class="token punctuation">.</span>Services<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">GetRequiredService</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>IPublishEvent<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">bus<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Subscribe</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>DivisionCalculationCompleted<span class="token punctuation">,</span> DivisionCalculationCompletedEventHandler<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre></div></div><p>We execute the specification we wrote earlier and...It&#x27;s ✅.</p><p>Software works exactly as we <em>understood</em> it to, from the expectations we were <a href="https://talesfrom.dev/blog/the-ambiguity-of-communication">told</a> to represent.</p><p>How cool is that?!</p><p>We presented the specifications to Tom so that he could approve our understanding - because we used business language in the spec names, it should be straightforward for Tom to verify.</p><p>We got ✅ from him too.</p><p>Nice!</p><p>A side-effect of our design with events is that in case of scaling - we can distribute the event handling across multiple instances or services, allowing for better performance and reliability.</p><p>Our architecture is very simple - it contains two <a href="https://talesfrom.dev/blog/composing-a-pie">elements</a>:</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-requirements-naive-architectural-elements.png" class="max-h-[15rem]"/></div></div><p>It does not look like those overengineered architectures you often see in presentations.</p><p>Simple requirements, simple architecture, right?!</p><h3 id="change-change-never-changes"><a href="#change-change-never-changes" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Change, change never changes</h3><p>Tom went out to check our newly developed services.</p><p>Some time passed and he came back with interesting observations.</p><div class="flex flex-col "><div class="flex flex-col"><div class="flex justify-center items-center flex-col"><div class="flex max-sm:flex-col justify-between items-center"><img src="https://talesfrom.dev/static/images/business-man.png" class="max-h-[30rem]"/><div class="flex flex-col justify-between text-left"><span>Tom says:</span><span class="my-4 italic"><span class=""><p>Our users love the new service!</p></span><span class=""><p>As I predicted, people started forgetting how division is working and they got hooked!</p></span><span class=""><p>Some users are not happy with charging by the usage.</p></span><div class="my-3"><span class="">Those </span><span class="mr-2">users</span><span class="">would rather </span><span class="mr-2">put some money in advance and control</span><span class="">how much money they spend.</span></div><div class="my-3"><span class="">This might be very interesting, because we could </span><span class="mr-2">offer some seasonal bargains</span><span class="">- instead of charging 1 dollar from your prepaid money, we take half of it.</span></div><span class=""><p>Nice idea, isn&#x27;t it?</p></span></span></div></div></div></div><div class="flex justify-around mt-10 lg:mx-32"><button class="bg-gray-600 border-gray-100 text-gray-400 p-2 rounded">Just talk</button><button class="bg-green-700 text-white border-2 p-2 rounded">Listening carefully</button></div></div><p>Preloaded money seems like a good idea - our architecture could definitely support it out of the box.</p><p>We designed <a href="https://talesfrom.dev/blog/the-ambiguity-the-curse-and-the-fallacy-of-domain-model">the domain model</a> taking into the account <a href="https://talesfrom.dev/blog/modeling-maturity-levels">the behavioral level</a> everything will be <a href="https://talesfrom.dev/blog/the-ambiguity-of-encapsulation">encapsulated</a> in the <code>Charge</code> behavior of <code>User</code>.</p><p>It looks as an easy feature, so we don&#x27;t bother Tom with event storming session - we asked him directly about how to determine charging method.</p><div class="flex flex-col "><div class="flex flex-col"><div class="flex justify-center items-center flex-col"><div class="flex max-sm:flex-col justify-between items-center"><img src="https://talesfrom.dev/static/images/business-man.png" class="max-h-[30rem]"/><div class="flex flex-col justify-between text-left"><span>Tom says:</span><span class="my-4 italic"><div class="my-3"><span class="">To me, it looks like some kind of </span><span class="mr-2">configuration that users can set up</span></div><div class="my-3"><span class="">We should not overcomplicate things - </span><span class="mr-2">a user chooses either prepaid or not</span><span class="">.</span></div></span></div></div></div></div><div class="flex justify-around mt-10 lg:mx-32"><button class="bg-gray-600 border-gray-100 text-gray-400 p-2 rounded">Just talk</button><button class="bg-green-700 text-white border-2 p-2 rounded">Listening carefully</button></div></div><p>Configuration - of course!</p><p>Can you figure it our dear Reader where how this change is going to look?</p><p>I bet you can.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">User</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">Guid</span> Id <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> FirstName <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> LastName <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> Email <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> CreditCardNumber <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">DateTime</span> CreditCardExpiry <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">decimal</span></span> BaseCalculationFee <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">bool</span></span> IsPrepaid <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// 👈 new information!</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">decimal</span></span> PrepaidAmount <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// 👈 new information!</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">Charge</span><span class="token punctuation">(</span><span class="token class-name">IPaymentGateway</span> @<span class="token keyword">using</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">if</span><span class="token punctuation">(</span>IsPrepaid<span class="token punctuation">)</span> <span class="token comment">// 👈 new section!</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">if</span><span class="token punctuation">(</span>PrepaidAmount <span class="token operator">&gt;=</span> BaseCalculationFee<span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token punctuation">{</span>
</span><span class="code-line">                PrepaidAmount <span class="token operator">-=</span> BaseCalculationFee<span class="token punctuation">;</span>
</span><span class="code-line">                <span class="token keyword">return</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token punctuation">}</span>
</span><span class="code-line">            <span class="token keyword">else</span>
</span><span class="code-line">            <span class="token punctuation">{</span>
</span><span class="code-line">                <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">InvalidOperationException</span><span class="token punctuation">(</span><span class="token string">&quot;Insufficient prepaid amount.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token punctuation">}</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> gateway <span class="token operator">=</span> @<span class="token keyword">using</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">await</span> gateway<span class="token punctuation">.</span><span class="token function">Transfer</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name constructor-invocation">PaymentDetails</span><span class="token punctuation">(</span>CreditCardNumber<span class="token punctuation">,</span> CreditCardExpiry<span class="token punctuation">,</span> BaseCalculationFee<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>It turned out quickly that with the current <a href="https://talesfrom.dev/blog/the-ambiguity-of-software-architecture">organization</a> of <a href="https://talesfrom.dev/blog/composing-a-pie">elements</a>, when a user has prepaid charging configured, they go below the limit after the division calculation was completed - so they already have used the service.</p><p>The worst thing was that we didn&#x27;t want to couple calculating division with information about users - in order to control it on the calculation side, we would need to read the user&#x27;s prepaid status and amount.</p><p>We tried to explain it to Tom in terms of best practices, but Tom wasn&#x27;t particularly happy about not earning money.</p><p>Also, after the initial testing with the real users, it might be that we would need to introduce some kind of a limits for each user? At least that&#x27;s what Tom said briefly.</p><div class="flex flex-col "><div class="flex flex-col"><div class="flex justify-center items-center flex-col"><div class="flex max-sm:flex-col justify-between items-center"><img src="https://talesfrom.dev/static/images/business-man.png" class="max-h-[30rem]"/><div class="flex flex-col justify-between text-left"><span>Tom says:</span><span class="my-4 italic"><span class=""><p>I have another brilliant idea for a feature.</p></span><div class="my-3"><span class="">Next to limits, we will </span><span class="mr-2">apply a delay</span><span class="">so that if a user wants to get his division results sooner, they need to pay extra!</span></div></span></div></div></div></div><div class="flex justify-around mt-10 lg:mx-32"><button class="bg-gray-600 border-gray-100 text-gray-400 p-2 rounded">Just talk</button><button class="bg-green-700 text-white border-2 p-2 rounded">Listening carefully</button></div></div><p>This is very interesting feature.</p><p>How will a <code>User</code> look like after introducing that change?</p><p>High chances are that there will be some kind of a <code>BaseDelay</code>.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">User</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">Guid</span> Id <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> FirstName <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> LastName <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> Email <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> CreditCardNumber <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">DateTime</span> CreditCardExpiry <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">decimal</span></span> BaseCalculationFee <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">TimeSpan</span> BaseDelay <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// 👈 new information!    </span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Ok, after this change we would definitely couple users and calculations.</p><p>We swallow a hard pill and let it be - if a fellow architect asks, we would tell them that Tom wanted that, according to his specs, right?</p><div class="flex flex-col "><div class="flex flex-col"><div class="flex justify-center items-center flex-col"><div class="flex max-sm:flex-col justify-between items-center"><img src="https://talesfrom.dev/static/images/business-man.png" class="max-h-[30rem]"/><div class="flex flex-col justify-between text-left"><span>Tom says:</span><span class="my-4 italic"><div class="my-3"><span class="">Ah, and by the way, I also want to </span><span class="mr-2">apply a precision trimming when returning a calculation result for the user</span><span class="">that requested it.</span></div><span class=""><p>So if they want to get more precision, they need to pay us.</p></span><span class=""><p>The sooner we ship it, the better.</p></span></span></div></div></div></div><div class="flex justify-around mt-10 lg:mx-32"><button class="bg-gray-600 border-gray-100 text-gray-400 p-2 rounded">Just talk</button><button class="bg-green-700 text-white border-2 p-2 rounded">Listening carefully</button></div></div><p>Even though it might sound complicated, it is fairly easy and straightforward.</p><p>It sounds like yet another configurable parameter that user can select and pay for.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">User</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">Guid</span> Id <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> FirstName <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> LastName <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> Email <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> CreditCardNumber <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">DateTime</span> CreditCardExpiry <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">decimal</span></span> BaseCalculationFee <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">TimeSpan</span> BaseDelay <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">int</span></span> Precision <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// 👈 new information!</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Ok, seems like we need to go and implement features in the core logic.</p><p>Since delay and precision now live directly on the <code>User</code>, the handler needs to know <em>who</em> is asking - a customer identifier joins the route, and the handler reaches straight into their record for the numbers it needs.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line">app<span class="token punctuation">.</span><span class="token function">MapGet</span><span class="token punctuation">(</span><span class="token string">&quot;/divide/{customerId}/{x}/by/{y}&quot;</span><span class="token punctuation">,</span> <span class="token keyword">async</span> <span class="token punctuation">(</span>
</span><span class="code-line">    <span class="token class-name">Guid</span> customerId<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">int</span></span> x<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">int</span></span> y<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">IUsersRepository</span> users<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">IPublishEvent</span> events<span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> result <span class="token operator">=</span> Calculation<span class="token punctuation">.</span><span class="token function">Divide</span><span class="token punctuation">(</span>x<span class="token punctuation">,</span> y<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>result<span class="token punctuation">.</span>IsSuccess<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">await</span> events<span class="token punctuation">.</span><span class="token function">Publish</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name constructor-invocation">CalculatingDivisionFailed</span><span class="token punctuation">(</span>x<span class="token punctuation">,</span> y<span class="token punctuation">,</span> result<span class="token punctuation">.</span>Error<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">return</span> Results<span class="token punctuation">.</span><span class="token function">Problem</span><span class="token punctuation">(</span><span class="token punctuation named-parameter">detail</span><span class="token punctuation">:</span> result<span class="token punctuation">.</span>Error<span class="token punctuation">,</span> <span class="token punctuation named-parameter">statusCode</span><span class="token punctuation">:</span> StatusCodes<span class="token punctuation">.</span>Status422UnprocessableEntity<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> user <span class="token operator">=</span> <span class="token keyword">await</span> users<span class="token punctuation">.</span><span class="token function">GetAsync</span><span class="token punctuation">(</span>customerId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">await</span> Task<span class="token punctuation">.</span><span class="token function">Delay</span><span class="token punctuation">(</span>user<span class="token punctuation">.</span>BaseDelay<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> trimmed <span class="token operator">=</span> Math<span class="token punctuation">.</span><span class="token function">Round</span><span class="token punctuation">(</span>result<span class="token punctuation">.</span>Value<span class="token punctuation">,</span> user<span class="token punctuation">.</span>Precision<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">await</span> events<span class="token punctuation">.</span><span class="token function">Publish</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name constructor-invocation">DivisionCalculationCompleted</span><span class="token punctuation">(</span>customerId<span class="token punctuation">,</span> x<span class="token punctuation">,</span> y<span class="token punctuation">,</span> trimmed<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">return</span> Results<span class="token punctuation">.</span><span class="token function">Ok</span><span class="token punctuation">(</span>trimmed<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre></div></div><h3 id="whats-next-boss"><a href="#whats-next-boss" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;What&#x27;s next boss?&quot;</h3><p>Let&#x27;s <a href="https://talesfrom.dev/blog/slow-down">slow down</a> for a while and think.</p><p>We rolled out so many features, we used collaborative methods, applied functional programming, object-oriented design and many more.</p><p>We tried to control coupling between services.</p><p>Everything seems fine.</p><p>But what are the predictions about our little system?</p><p><code>User</code> <a href="https://talesfrom.dev/blog/concepts-entities-data">entity</a> is getting bigger, attracts more and more information.</p><p>At the beginning, we focused so much of our quality time into exploring the details of dividing, but it somehow feels odd.</p><p>The more features we got on our plate, the more it seems it is just an element of the entire puzzle.</p><p>Hm, we tried to apply all those industry best practices, at least when it comes to working together, as <a href="https://talesfrom.dev/blog/the-ambiguity-of-team-work">a team</a>.</p><p>Literally, whatever Tom brought to us, we listened carefully and tried to build up understanding and <a href="https://talesfrom.dev/blog/the-ambiguity-of-application">apply it</a>, representing important concepts like <code>Calculation</code>, <code>User</code>.</p><p>&quot;It is a toy example Damian, in <em>real</em> systems no one is so naive as you tried to be&quot;, some might actually say.</p><p>Well, I didn&#x27;t say we are going to build a big system during this tale.</p><p>If we take John Gall&#x27;s law:</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">Gall&#x27;s law</div><div class="pb-2 px-3"><div class="break-words"><p>A complex system that works is invariably found to have evolved from a simple system that worked.</p></div></div></div><p>It might be that our toy example will eventually grow into something bigger, even if it looks deceivly simple at the moment.</p><p>We started with a simple, but central division feature, and ended up as it being pushed to the side, in favor of other aspects of the system.</p><p>Aspects of the system or aspects of the business?</p><h3 id="what-a-calculator-has-to-do-with-a-business"><a href="#what-a-calculator-has-to-do-with-a-business" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What a calculator has to do with a business?</h3><p>Imagine that our initial conversation with Tom looked slightly different.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div><span class="italic font-bold text-orange-500">Tom</span>: Sooner or later, they will forget how to calculate a simple division!</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Us</span>: Ok, but what we are going to actually offer?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-orange-500">Tom</span>: I think it will be a service that helps people with their calculations.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Us</span>: So it won&#x27;t be a <span class="italic">calculation</span>, but rather an <span class="italic">access</span>?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-orange-500">Tom</span>: I haven&#x27;t thought about it in that terms, but yes, it sounds right</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Us</span>: We offer the access to calculations, how do we earn money based on that?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-orange-500">Tom</span>: I think initially it will be a tiny fee.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Us</span>: And after initially? Do we plan introducing any limits, special subscriptions or something like that?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-orange-500">Tom</span>: Well, maybe, but I don&#x27;t want to overcomplicate things from the start.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Us</span>: What do you mean by &quot;overcomplicate things?&quot;</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-orange-500">Tom</span>: I saw you IT people tend to focus on things that do not matter and then we are getting lost in details.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Us</span>: Excuse me if we were not clear with our intentions - we are not going to implement everything we discussed right away - we are trying to simulate scenarios in order to understand the direction. It will help us make better decisions in the long run.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-orange-500">Tom</span>: So you don&#x27;t want to implement it now? Ok, then I am good. So eventually yes, there will be some kind of subscriptions - users will be able to choose how they want to be charged, and so on.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Us</span>: Users or customers?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-orange-500">Tom</span>: Huh?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Us</span>: We can imagine a scenario where a customer is an organization and a user is an individual within that organization. So customer buys the access, but it is the user who uses division.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-orange-500">Tom</span>: Ah, that&#x27;s sharp point! I haven&#x27;t thought about it in that way.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Us</span>: Next question - it is quite speculative, but when it comes to charging the users - we said that they will get <span class="italic">the access</span> - but what they are going to consume?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-orange-500">Tom</span>: Sorry, I don&#x27;t get it.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Us</span>: Think about it - imagine we wrote it as if it was a brochure - &quot;you will be charged for the division you consumed&quot; - doesn&#x27;t it sound ridiculously?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-orange-500">Tom</span>: I still don&#x27;t get it...</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Us</span>: How can you <em>consume</em> a division? We think we need to be a little more precise in our language. We give <span class="italic">access</span> to the service, users <span class="italic">consume</span> <em>something-we-did-not-yet-define</em> and based on that we charge them.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-orange-500">Tom</span>: Ok, I think I get it, but I don&#x27;t have the name for it.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Us</span>: As said, it is speculative, but what do you think about <em>calculation tokens</em>? &quot;you will be charged for consumed calculation tokens&quot;</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-orange-500">Tom</span>: Hm, this sounds really good. This means users will be able to prepay <em>calculation tokens</em> or pay as they go?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Us</span>: Exactly! What&#x27;s more, you will be able to decide on the pricing and usage limits for these tokens. Imagine that there is a loyal customer who uses high precision results, but does not care about when they get the results. Wouldn&#x27;t it be nice to tell them that they get better token discounts?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-orange-500">Tom</span>: This is brilliant!</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Us</span>: Another point - we know that our system will <em>calculate division</em> on behalf of the user, but we think it might be valuable to change the language here too.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-orange-500">Tom</span>: What do you mean by that?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Us</span>: Their goal is to calculate division using our system, but imagine two users trying to get their division at the same time, during high traffic hours. We need to prioritize one over another and say for the unlucky one that we couldn&#x27;t deliver the results.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-orange-500">Tom</span>: And what? We just say &quot;sorry, try again later&quot;?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Us</span>: But we brand it as a simple division - you give two numbers, you get back the result. When they use our API, they will experience it as &quot;calculating division&quot;, but sometimes we know we will not be able to handle it immediately. What do you think if we are explicit in our language and say they <em>order a division calculation</em>?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-orange-500">Tom</span>: And handling orders can be delayed, cancelled, and so on?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Us</span>: Exactly. By framing it as an order, we set the expectation that there might be various obstacles, just like any other order in a system.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-orange-500">Tom</span>: Hmmm, taking into account our previous insights, just a mere idea, if we want to delay providing the results, in fact we are going to delay handling the order?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Us</span>: Yes, something like that. The most important aspect is to communicate the ideas clearly to the users.</div></span></div><p>Tom had his ideas, brilliant ones, not to diminish them.</p><p>But they needed to be worked on, at least slightly.</p><p>We used our way of thinking to understand and refine them.</p><p>Analyze how to <a href="https://talesfrom.dev/blog/context-segregation-principle">decompose</a> concepts firstly, sometimes suggesting, a bit speculatively, how to <a href="https://talesfrom.dev/blog/from-concepts-to-architecture">organize them</a>.</p><p>After a short discussion which started from a simple division and users, we ended up with <strong>ideas</strong> about:</p><ul><li>users</li><li>customers</li><li>calculation tokens</li><li>calculation orders</li><li>billing</li></ul><p>&quot;This is so Big Design Up-Front Damian!&quot;, some might resist.</p><p>Well, what if those concepts were there, but uncovered?</p><p>Many of the businesses and human activities have common ideas, especially when it comes to universal concepts like selling/ordering/billing, and so on.</p><p>Who&#x27;s <del>fault</del>, I mean responsibility, is to make those concepts explicit?</p><p>Often times, our domain experts or business owners are the ones who have the most knowledge about their area of expertise, but they are not trained in abstract thinking.</p><p>A particular way of <em>experiencing</em> the world around.</p><p>So what a calculator has to do with a business?</p><p>In a way, nothing and everything at the same time.</p><p>It is <em>a basic capability</em> that we are selling <em>an access to</em>.</p><p>Initially, Tom did not reveal us &quot;the depth&quot; of this area - but when we consciously explored it, trying to understand the main ideas driving the whole endeavor, it seems we saw this &quot;depth&quot;.</p><p>Of course it required being proactive and also suggest organizing the concepts in the certain way.</p><p>Not only receiving what Tom <a href="https://talesfrom.dev/blog/the-ambiguity-of-communication">told</a> us, but also process, reflect and pushback.</p><p>&quot;The depth&quot; that got mentioned, might be directly related to different levels at which our concepts live.</p><p>Those <a href="https://herbertograca.com/2016/06/13/ddd-16-large-scale-structure/">&quot;levels&quot;</a> appear in the literature in various forms, but the universal pattern is similar - our systems are not &quot;flat&quot;, and there are various <a href="https://talesfrom.dev/blog/time-angle-and-depth-dimensions-in-software-design">dimensions</a> that we should use while we&#x27;re analyzing, understanding, decomposing systems.</p><p>Same with our tiny tale:</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-requirements-concept-levels.png" class="max-h-[20rem]"/></div><div class="italic mx-24">Domain responsibility layers</div></div><p>Doing all of that work will eventually lead to <code>User</code> concept disappearing, at least in the form we experienced it in this tale.</p><p>It also enriches the language we might use while talking to each other.</p><p>An avid Reader might have already noticed a subtle <a href="https://talesfrom.dev/blog/the-ambiguity-of-implementation-details">feedback</a> given by <a href="https://talesfrom.dev/blog/the-ambiguity-of-requirements#whenever">earlier specs</a>, when it comes to a concept of <code>User</code>:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token class-name"><span class="token keyword">var</span></span> user <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">User</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    CreditCardNumber <span class="token operator">=</span> <span class="token string">&quot;4111111111111111&quot;</span><span class="token punctuation">,</span>
</span><span class="code-line">    CreditCardExpiry <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">DateTime</span><span class="token punctuation">(</span><span class="token number">2030</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
</span><span class="code-line">    BaseCalculationFee <span class="token operator">=</span> <span class="token number">0.01m</span>
</span><span class="code-line"><span class="token punctuation">}</span><span class="token punctuation">;</span>
</span></code></pre></div></div><p>Even though we create a new instance of <code>User</code> object, the information used in the test are focusing on a very specific <a href="https://talesfrom.dev/blog/context-segregation-principle">perspective</a> of it.</p><p>Coincidentally mixing up aspects and creating <a href="https://talesfrom.dev/blog/the-curse-the-ambiguity-and-the-fallacy-of-domain-model"><strong>the</strong> domain model</a> might sound easy, but definitely it is <a href="https://talesfrom.dev/blog/simple-isnt-easy">not simple</a>.</p><p>Even tests were whispering to us, giving diagnostic signals, but it strongly depends on our ability to listen to them.</p><h3 id="requirements-features-concepts"><a href="#requirements-features-concepts" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Requirements? Features? Concepts?</h3><p>Often times, we get &quot;the requirements&quot; which turn out to be unprocessed thoughts - they might have their value, but still they need a little bit more effort when it comes to ensuring they fit the conceptual integrity of our system.</p><p>Those &quot;requirements&quot; or &quot;features&quot;, branded as &quot;simple&quot;, hide interesting and important abstract ideas behind.</p><p>And this is our job to check how they interact with the rest of the system.</p><p>But when I say &quot;interact&quot;, it does not only mean &quot;technically interact&quot; - method calls, sending HTTP requests and so on.</p><p>It also means &quot;conceptually interact&quot; - as you experienced that earlier dear Reader, when we had a lengthy discussion with Tom.</p><p>Before <a href="https://talesfrom.dev/blog/the-inverse-matrix-problem">jumping to any coding</a> or solutioning, we should think about composing a <a href="https://talesfrom.dev/blog/composing-a-pie">PIE</a>.</p><p>Two questions I find particularly interesting, powerful and useful, are:</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>What does X mean to me?</p></div></div></div><p>or</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>How do I understand X?</p></div></div></div><p>They require me to enter analysis mode where I try to purposefully explore the problem area.</p><p>Each requirement, feature or expectation, has deeper structure buried underneath.</p><p>Unfortunately, they don&#x27;t communicate this conceptual structure explicitly and immediately.</p><p>It requires an investment, human effort, to lean over it and start <em>seeing</em> underlying ideas.</p><p>Recall dear Reader what Tom initially told us - &quot;it is a simple division&quot; - we got hooked in by this framing and the rest is just history.</p><p>That&#x27;s why <a href="https://talesfrom.dev/blog/the-ambiguity-of-naming">naming is framing</a> - as soon as the label/name appears, it shapes the world we experience and we see.</p><p>It requires stepping outside of the invisible box, the invisible frame, and start asking questions:</p><ul><li>&quot;Why is it important?&quot;</li><li>&quot;What are the main questions are we looking answers to?&quot;</li><li>&quot;What is the goal?&quot;</li><li>&quot;What do we try to accomplish when doing X?&quot;</li><li>And so on...</li></ul><p>Those questions are there not to critique, but to understand.</p><p>To synthesize the knowledge, and frame the right conceptual structure that will hold the rest of the system.</p><p>We must do it, because the information we often initially get is unstructured, ambiguious and contradicting.</p><p>Ambiguity has no problems with getting compiled.</p><p>Also, ambiguity does not throw <code>NonsenseException</code>.</p><p><a href="https://ian-cooper.writeas.com/coding-is-dead-long-live-programming">Software design</a> is about untangling ambiguity and organizing various structures - but please don&#x27;t conflate them with <a href="https://talesfrom.dev/blog/concepts-entities-data">&quot;data structures&quot;</a>.</p><p>It&#x27;s far more than that.</p><p>More like building <a href="https://pages.cs.wisc.edu/~remzi/Naur.pdf">theories</a>, however, I would rather brand it as &quot;conceptual structuring&quot; or &quot;organizing conceptual structures&quot;.</p><p>It is necessary effort, but insufficient, on its own.</p><p>Our software systems live in numerous dimensions - and conceptual is only one of them.</p><p>We have runtime as well.</p><p>So those technical matters are still greatly important, because slowly responding, but perfectly modeled systems is not particularly useful for users or customers.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Ambiguity has no problems with getting compiled.</p></div></div></div><p>Software design might be regarded as a continuous process of searching deeper conceptual structures.</p><p>It strongly depends on the problem area we are operating in - tools solving a particular problem might be bounded enough so that the search might end pretty quickly, whereas business environments can cause neverending forces that will require concepts to die, emerge and transform.</p><h3 id="everything-starts-with-a-question"><a href="#everything-starts-with-a-question" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Everything starts with a question</h3><p>The quality of questions is the quality of answers.</p><p>As someone once said, &quot;A question contains the half of the answer&quot;.</p><p>As <a href="https://talesfrom.dev/blog/the-ambiguity-of-naming">naming is framing</a>, framing questions is framing the way we think.</p><p>We can use various tool like event storming, example mapping, specification by example and more, but if we don&#x27;t look for deeper conceptual structures, &quot;the theories&quot;, we might just slight on the surface.</p><p>If we remember that <a href="https://talesfrom.dev/blog/tools-make-fools">tools make fools</a>, we might resist the temptation to rely solely on them.</p><p>Clearly thinking operator, the designer who know how to build, is the secret sauce here.</p><p>Clear thinking gets <a href="https://talesfrom.dev/blog/llms-3d-printers-amplifiers">amplified</a>, noisy thinking gets amplified too.</p><p>Often times the clarity comes from collaboration, but as we saw, at least one side of the conversation needs to be able to exercise the deep conceptual thinking.</p><p>A simple division might hide the complexities of business systems, only if the operator is capable of reasoning using the variety of <a href="https://talesfrom.dev/blog/time-angle-and-depth-dimensions-in-software-design">dimensions</a>.</p><p>Domain-Driven Design might be frequently conflated with &quot;tactical patterns&quot;, but essentially it is a simple (but not easy, which means effort-requiring) call to collaborate in order to establish conceptual organization, where the ambiguity is primarly observed.</p><p>It might be that we are facing a basic business capability, like division, that is surrounded by other <a href="https://talesfrom.dev/blog/context-segregation-principle">contexts</a>, which in the first glance are invisible.</p><p>There are certain business operations that utilize those capabilities, and the specificity of the logical order of interactions, is what might be truly volatile, hence requires encapsulation - <a href="https://www.cs.colostate.edu/~france/CS314/Readings/Parnas-decomposition.pdf">a true criteria for decomposing a system</a>.</p><p>So next time dear Reader, when you hear &quot;a simple requirement&quot;, ask yourself:</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>What does it mean to me?</p></div></div></div>]]></content:encoded>
    <pubDate>Sun, 26 Jul 2026 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>domain-driven design</category><category>language patterns</category><category>design patterns</category><category>software architecture</category><category>mental models</category><category>communication</category><category>knowledge working</category><category>tools and capabilities</category><category>psychology</category><category>philosophy</category><category>visual thinking</category><category>perception</category><category>perspectives</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/the-ambiguity-of-communication</guid>
    <title>The ambiguity of communication</title>
    <link>https://talesfrom.dev/blog/the-ambiguity-of-communication</link>
    <description>why telling is not enough and what are other important levels?</description>
    <content:encoded><![CDATA[<h3 id="but-i-told-you"><a href="#but-i-told-you" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;But I told you&quot;</h3><p>Imagine two senior software engineers, <span class="italic font-bold text-violet-500">Sarah</span> and <span class="italic font-bold text-teal-500">Sam</span>, sitting in a call.</p><p>Both have been in the industry for years.</p><p>Both know their craft.</p><p><span class="italic font-bold text-violet-500">Sarah</span> has been at the company for years - she knows every corner of the system, every decision, every failed experiment that led to where things are today.</p><p><span class="italic font-bold text-teal-500">Sam</span> has just joined. Experienced engineer, but new to this particular system.</p><p><span class="italic font-bold text-violet-500">Sarah</span> is doing the onboarding.</p><p>The topic is complex - an event-driven, distributed architecture with multiple bounded contexts and asynchronous message flows.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div><span class="italic font-bold text-violet-500">Sarah, the Senior Engineer</span>: Ok, so here&#x27;s the deal. We have three main BCs - BDG, KLP and the Fulfillment core. Each is a separate deployable, communicating via EDA. We use Kafka as the broker and we follow CE spec for all events on the wire.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Sam, the Senior Engineer</span>: Ok.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-violet-500">Sarah, the Senior Engineer</span>: The tricky part is the WORF layer. We do CQRS inside each BC - so Commands go in, Events come out, read side is eventually consistent. We had idempotency issues before so now every handler in BDG has an outbox and a deduplication table. Consumer groups are partitioned by WORF root id so ordering is preserved inside a single stream.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Sam, the Senior Engineer</span>: Right, right.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-violet-500">Sarah, the Senior Engineer</span>: The MTR Saga orchestrates across all three - it listens on <code>BDGSettled</code>, does a compensating transaction if <code>KLPRejected</code> arrives before the SLA window closes. We track state in the saga store, which is basically a WORF projection. The whole thing is idempotent because we slap ETags on entity level and use optimistic concurrency on every write against the FLX schema.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Sam, the Senior Engineer</span>: Sounds solid.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-violet-500">Sarah, the Senior Engineer</span>: One more thing - the BFF in front of KLP does token exchange via the GXR provider, so don&#x27;t go calling KLP directly from the UI. Route it through the AGW, it handles the RBAC policies and rate limiting for us.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Sam, the Senior Engineer</span>: Got it.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-violet-500">Sarah, the Senior Engineer</span>: Good. Any questions?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Sam, the Senior Engineer</span>: No, I think I got it.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-violet-500">Sarah, the Senior Engineer</span>: Great. Did you get it?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Sam, the Senior Engineer</span>: Yeah, yeah.</div></span></div><p>How do you think, dear Reader, did <span class="italic font-bold text-teal-500">Sam</span> get it?</p><p>He didn&#x27;t even know what question to ask.</p><p>A few days later, <span class="italic font-bold text-teal-500">Sam</span> sat down alone to implement his first change.</p><p>No one around.</p><p>Just him, the codebase, and a mental model assembled from thirty minutes of acronyms.</p><p>He touched the wrong layer entirely.</p><p>When <span class="italic font-bold text-violet-500">Sarah</span> found out, she said: &quot;But I told you - BDG doesn&#x27;t own that, it goes through the MTR Saga.&quot;</p><p>She was right.</p><p>She did tell him.</p><p>Alone, <a href="https://talesfrom.dev/blog/the-ambiguity-of-team-work">isolated from the heads</a> that held the real context, <span class="italic font-bold text-teal-500">Sam</span> had only the words - not the understanding behind them.</p><p><span class="italic font-bold text-violet-500">Sarah</span> had no idea.</p><p>She was too fluent in the language of the system to notice that each sentence she spoke was an acronym stacked on an assumption, with no shared ground beneath.</p><p>Because she was only at the <strong>Telling</strong> level.</p><h3 id="does-it-make-sense-so-far"><a href="#does-it-make-sense-so-far" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Does it make sense so far?&quot;</h3><p>A week later, <span class="italic font-bold text-violet-500">Sarah</span> noticed something after hearing back from a colleague that <span class="italic font-bold text-teal-500">Sam</span> had been asking very basic questions in team chat for days.</p><p>Questions that the onboarding was supposed to answer.</p><p>So she tried something slightly different.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div><span class="italic font-bold text-violet-500">Sarah, the Senior Engineer</span>: Do you know what the system does?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Sam, the Senior Engineer</span>: Not really, I only had a brief look at the docs before joining.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-violet-500">Sarah, the Senior Engineer</span>: Ok, let me start with the high level. We have three main areas - Payments, Orders, and Fulfillment. Each of them is a separate service. Does that make sense so far?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Sam, the Senior Engineer</span>: Yes, three separate services. Got it.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-violet-500">Sarah, the Senior Engineer</span>: They talk to each other using events, through a message broker - Kafka. So instead of direct HTTP calls, they publish and consume events. Following so far?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Sam, the Senior Engineer</span>: Yes, I know Kafka. Events instead of direct calls.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-violet-500">Sarah, the Senior Engineer</span>: Good. Inside each service we do CQRS - does that ring a bell?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Sam, the Senior Engineer</span>: Command Query Responsibility Segregation, yes - separate models for reading and writing.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-violet-500">Sarah, the Senior Engineer</span>: Exactly. And on top of that, to coordinate across all three services - we have a Saga. It&#x27;s the thing that knows the overall flow and handles failures. Make sense?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Sam, the Senior Engineer</span>: I think so. The Saga is like a coordinator?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-violet-500">Sarah, the Senior Engineer</span>: Yes, exactly - we can think of it as an integrator of various contexts. And it listens on specific events and reacts. If something fails, it can trigger compensating actions to undo what was already done. Clear?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Sam, the Senior Engineer</span>: Ok, I think I follow. But I am not entirely sure about the &quot;compensating actions&quot; part. What does that look like in practice?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-violet-500">Sarah, the Senior Engineer</span>: Good question. So imagine payment succeeded but fulfillment failed - we need to refund. The saga listens for <code>FulfillmentFailed</code>, then issues a <code>RefundPayment</code> command. Does that help?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Sam, the Senior Engineer</span>: Yes! That makes sense now. So the saga basically reacts to what goes wrong.</div></span></div><p>This time, <span class="italic font-bold text-teal-500">Sam</span> walked away with something real.</p><p>Not everything, but enough to ask the right questions.</p><p><span class="italic font-bold text-violet-500">Sarah</span> was now at the <strong>Explaining</strong> level - checking if the signal was getting through, adjusting based on what came back.</p><p>Still, there was something missing.</p><p>She was the one drawing the picture.</p><p><span class="italic font-bold text-teal-500">Sam</span> was receiving it.</p><h3 id="can-you-tell-me-what-you-understood"><a href="#can-you-tell-me-what-you-understood" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Can you tell me what you understood?&quot;</h3><p>Another session.</p><p>This time <span class="italic font-bold text-violet-500">Sarah</span> decided to approach it differently.</p><p>She opened a shared canvas - a blank <a href="https://excalidraw.com/">excalidraw</a> board - and put it in front of both of them.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div><span class="italic font-bold text-violet-500">Sarah, the Senior Engineer</span>: Ok, I want to try something today. I&#x27;ll explain the system, but instead of me doing all the talking, I want you to draw what you hear. Does that work?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Sam, the Senior Engineer</span>: Sure, though I might get things wrong.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-violet-500">Sarah, the Senior Engineer</span>: That&#x27;s exactly the point. We start with three services. I&#x27;ll give you names, you draw boxes.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Sam, the Senior Engineer</span>: (<em>draws three boxes, labels them: Payments, Orders, Fulfillment</em>)</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-violet-500">Sarah, the Senior Engineer</span>: Good. Now - they don&#x27;t call each other directly. They publish events to a broker, and other services consume from it. How would you draw that?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Sam, the Senior Engineer</span>: (<em>draws a central box labeled &quot;Kafka&quot;, arrows going from each service into it, and arrows going back out</em>) Like this?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-violet-500">Sarah, the Senior Engineer</span>: Almost. The arrows going in represent publishing. What do the ones going out represent?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Sam, the Senior Engineer</span>: Consuming... but then which services consume from which? I don&#x27;t know that yet.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-violet-500">Sarah, the Senior Engineer</span>: Exactly - that&#x27;s the interesting part. Let me tell you about the main flow, and you draw what you understand. Payments publishes <code>PaymentInitiated</code>. Fulfillment listens. If it succeeds, it publishes <code>FulfillmentConfirmed</code>. If not, <code>FulfillmentFailed</code>.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Sam, the Senior Engineer</span>: (<em>draws and narrates</em>) So Payments puts this event into Kafka... Fulfillment picks it up... and then publishes one of two outcomes. (<em>pauses</em>) But who reacts to <code>FulfillmentFailed</code>?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-violet-500">Sarah, the Senior Engineer</span>: That&#x27;s the Saga. Where would you put that on the board?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Sam, the Senior Engineer</span>: (<em>draws another box, labeled &quot;Saga&quot;</em>) Is it another service?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-violet-500">Sarah, the Senior Engineer</span>: Yes. And based on what you know now - what do you think the Saga does when it sees <code>FulfillmentFailed</code>?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Sam, the Senior Engineer</span>: It needs to undo the payment somehow. So maybe it publishes a command back to Payments? Like <code>RefundPayment</code>?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-violet-500">Sarah, the Senior Engineer</span>: Exactly. Now look at your drawing. What does it tell you?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Sam, the Senior Engineer</span>: (<em>stares at the board</em>) That the Saga is... the only thing that sees the whole picture. The other services don&#x27;t know about each other.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-violet-500">Sarah, the Senior Engineer</span>: Yes. That&#x27;s exactly why it exists.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Sam, the Senior Engineer</span>: Ok, let me try to use my own words to check if I got it right, according to your understanding. We have three services - Payments, Fulfillment, and the Saga. They don&#x27;t call each other. Instead, they publish events to Kafka and consume from it. Payments starts the flow by publishing <code>PaymentInitiated</code>. Fulfillment picks it up and either confirms or reports failure. The Saga listens to those outcomes and is the only one that knows the whole story - so if something fails, it&#x27;s the Saga that decides what to undo and how. Is that roughly it?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-violet-500">Sarah, the Senior Engineer</span>: That&#x27;s exactly it. And now you also know why we don&#x27;t call services directly.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-teal-500">Sam, the Senior Engineer</span>: Because if they called each other, they&#x27;d each need to know what the other does. And then you&#x27;d have no Saga - you&#x27;d have chaos.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-violet-500">Sarah, the Senior Engineer</span>: (<em>smiles</em>) Now you got it.</div></span></div><p><span class="italic font-bold text-teal-500">Sam</span> drew it.</p><p><span class="italic font-bold text-teal-500">Sam</span> discovered it.</p><p><span class="italic font-bold text-violet-500">Sarah</span> guided him there, but the understanding belonged to <span class="italic font-bold text-teal-500">Sam</span> now.</p><p>Because they were collaborating on the <strong>Aligning</strong> level.</p><h3 id="what-is-tea"><a href="#what-is-tea" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What is TEA?</h3><p>Three conversations.</p><p>Same topic.</p><p>Very different outcomes.</p><p>What distinguished them was not the information - it was the direction of the communication and who was responsible for creating the conditions for growing the understanding.</p><p>Let&#x27;s bring some definitions, because they might be useful.</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">Telling - a definition</div><div class="pb-2 px-3"><div class="break-words"><p>One-way conveyance of information. The sender speaks, the receiver listens. Feedback is not actively sought nor incorporated. Understanding is assumed, not verified.</p></div></div></div><p> </p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">Explaining - a definition</div><div class="pb-2 px-3"><div class="break-words"><p>Two-way conveyance of information. The sender speaks and actively probes - &quot;does this make sense?&quot;, &quot;are you following?&quot;. Feedback is collected and used to adjust the message. Understanding is checked but still sender-driven.</p></div></div></div><p> </p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">Aligning - a definition</div><div class="pb-2 px-3"><div class="break-words"><p>Collaborative construction of shared understanding. The sender invites the receiver to articulate, draw, rephrase - to externalize their internal model. Gaps and mismatches are surfaced and resolved together. Understanding is co-created.</p></div></div></div><p>Together, they form <strong>TEA</strong> - <strong>T</strong>elling, <strong>E</strong>xplaining, <strong>A</strong>ligning.</p><p>Three levels of communication intensity when it comes to conveying abstract ideas and collaborating with others.</p><p>Not a ladder to climb once and stay at the top.</p><p>A range to move through, consciously, depending on what the situation demands.</p><h3 id="why-does-it-matter"><a href="#why-does-it-matter" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Why does it matter?</h3><p>&quot;Communication always fails, except by accident&quot; - as <a href="https://en.wikipedia.org/wiki/Wiio&#x27;s_laws">Wiio&#x27;s laws</a> remind us.</p><p>And as we explored in <a href="https://talesfrom.dev/blog/keep-it-visible-smartass">Keep it visible, smartass</a> - words are volatile, invisible by nature.</p><p>Spoken words are impermanent.</p><p>They dissipate.</p><p>The mental model built in the sender&#x27;s head and the one assembled in the receiver&#x27;s head might share a few words, but diverge significantly in meaning.</p><p>And neither side knows it.</p><p>Because it is invisible.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Communication always fails, except by accident</p></div></div></div><p>The first conversation between <span class="italic font-bold text-violet-500">Sarah</span> and <span class="italic font-bold text-teal-500">Sam</span> - pure <strong>Telling</strong> - is the most common mode of illusionary knowledge transfer in software teams.</p><p>Architecture reviews, onboarding sessions, design discussions, incident post-mortems.</p><p>Someone talks.</p><p>Others nod.</p><p>And everyone leaves with a slightly different map of the same territory.</p><p>Then the codebase pays for it.</p><h3 id="telling-is-not-wrong"><a href="#telling-is-not-wrong" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Telling is not wrong</h3><p>Let&#x27;s be fair to <strong>Telling</strong>.</p><p>It has its place.</p><p>When context is genuinely shared, when the audience is already aligned, when speed is the constraint - <strong>Telling</strong> is appropriate and efficient.</p><p>But how do you know, dear Reader, that we can stay at the <strong>Telling</strong> level?</p><p>A standup update is <strong>Telling</strong>.</p><p>A well-written ADR is <strong>Telling</strong>.</p><p>Briefing a team that already lived through the same decisions is <strong>Telling</strong>.</p><p>The problem is not <strong>Telling</strong> itself.</p><p>The problem is defaulting to the <strong>Telling</strong> level when the <strong>Explaining</strong> or <strong>Aligning</strong> level is needed - because it feels <a href="https://talesfrom.dev/blog/simple-isnt-easy">easier</a> - which might seem faster - or because we assume shared context that isn&#x27;t there.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Telling is not wrong. Misapplied Telling is wrong.</p></div></div></div><h3 id="the-hidden-cost-of-assumed-understanding"><a href="#the-hidden-cost-of-assumed-understanding" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The hidden cost of assumed understanding</h3><p>Notice what <span class="italic font-bold text-teal-500">Sam</span> said in the first conversation.</p><p>&quot;Yeah, yeah.&quot;</p><p>Not because he understood.</p><p>Because he didn&#x27;t know what he didn&#x27;t know.</p><p>This is <a href="https://en.wikipedia.org/wiki/Dunning%E2%80%93Kruger_effect">Dunning-Kruger</a> applied to receiving information - you cannot ask about the gaps you cannot see.</p><p>And <span class="italic font-bold text-violet-500">Sarah</span> filled the silence with confidence.</p><p>Silence is not agreement.</p><p>Silence is not understanding.</p><p>Silence is what happens when someone doesn&#x27;t have the vocabulary to ask.</p><p>Provide the context.</p><p>Provide the vocabulary.</p><p>Provide <a href="https://talesfrom.dev/blog/from-concepts-to-architecture">abstract ideas</a> supported by examples.</p><p><a href="https://talesfrom.dev/blog/keep-it-visible-smartass">Visualize the language</a> - put it on the board, write down the words as they appear, draw the boxes as the concepts emerge.</p><p>When <span class="italic font-bold text-teal-500">Sam</span> sees &quot;BDG&quot; and &quot;MTR Saga&quot; written down next to each other with an arrow between them, he has something to point at.</p><p>He can say &quot;what is this arrow and what does it mean?&quot; instead of not knowing what he doesn&#x27;t know.</p><p>The board doesn&#x27;t just capture ideas - it creates the vocabulary that makes questions possible.</p><p>The first conversation produced an illusion of alignment.</p><p>Both parties left feeling good about it.</p><p>The team chat told the truth a week later.</p><h3 id="explaining-is-not-enough-either"><a href="#explaining-is-not-enough-either" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Explaining is not enough either</h3><p>The second conversation was better.</p><p><span class="italic font-bold text-violet-500">Sarah</span> asked &quot;does it make sense?&quot; and waited.</p><p><span class="italic font-bold text-teal-500">Sam</span> even pushed back on the compensating transaction part.</p><p>Real signal came through.</p><p>But notice who held the pen.</p><p><span class="italic font-bold text-violet-500">Sarah</span> owned the mental model and was handing pieces of it to <span class="italic font-bold text-teal-500">Sam</span>.</p><p><span class="italic font-bold text-teal-500">Sam</span> was receiving, validating, acknowledging.</p><p>His understanding was still a pale copy of hers - not a structure he built.</p><p>When he would sit down to implement something a week later, he would be working from a received model.</p><p>Received models are fragile.</p><p>They don&#x27;t survive contact with new information well.</p><p>And they are easy to misremember.</p><h3 id="aligning-is-the-investment"><a href="#aligning-is-the-investment" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Aligning is the investment</h3><p>The third conversation was slower.</p><p>It required a shared canvas.</p><p>It required <span class="italic font-bold text-violet-500">Sarah</span> to give up control and let <span class="italic font-bold text-teal-500">Sam</span> drive the drawing.</p><p>It required <span class="italic font-bold text-teal-500">Sam</span> to be wrong in front of her and not feel bad about it.</p><p>But something happened at the end of that conversation that didn&#x27;t happen in the previous two.</p><p><span class="italic font-bold text-teal-500">Sam</span> made an inference on his own.</p><p>&quot;The Saga is the only thing that sees the whole picture. The other services don&#x27;t know about each other.&quot;</p><p><span class="italic font-bold text-violet-500">Sarah</span> didn&#x27;t say that.</p><p><span class="italic font-bold text-teal-500">Sam</span> derived it.</p><p>That&#x27;s the difference.</p><p>When someone can derive the conclusion from the structure they built themselves, the understanding is theirs.</p><p>It can be extended.</p><p>It can survive contact with new information.</p><p>It can be taught to the next person.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Understanding you built yourself is yours. Understanding you received belongs to someone else.</p></div></div></div><h3 id="from-invisible-to-visible"><a href="#from-invisible-to-visible" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>From invisible to visible</h3><p>All three levels of TEA benefit from making things visible - but the <strong>Aligning</strong> level depends on it.</p><p>You cannot align on an invisible mental model.</p><p>The canvas in the third conversation was not a nice-to-have.</p><p>It was the mechanism through which alignment became possible.</p><p><span class="italic font-bold text-teal-500">Sam</span>&#x27;s drawing was wrong in places.</p><p>That was the point.</p><p>The assumptions became visible.</p><p>It could be corrected.</p><p>As Alberto Brandolini wisely noted - don&#x27;t talk about invisible things.</p><p>And as we know from <a href="https://talesfrom.dev/blog/keep-it-visible-smartass">Keep it visible, smartass</a> - making things visible is what surfaces assumptions, gaps and misunderstandings that would otherwise remain hidden forever.</p><p>In <strong>Telling</strong>, nothing is visible.</p><p>In <strong>Explaining</strong>, the sender&#x27;s model is visible.</p><p>In <strong>Aligning</strong>, the receiver&#x27;s model becomes visible - and that&#x27;s where the real work happens.</p><h3 id="which-mode-to-use"><a href="#which-mode-to-use" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Which mode to use?</h3><p>This is not about always doing full <strong>Aligning</strong> level sessions.</p><p>That would be exhausting and inefficient.</p><p>TEA is a spectrum, not a prescription.</p><p>The question to ask is: &quot;what is the cost of misalignment here?&quot;</p><p>If <span class="italic font-bold text-teal-500">Sam</span> misunderstands a team social event - low cost, <strong>Telling</strong> level is fine.</p><p>If <span class="italic font-bold text-teal-500">Sam</span> misunderstands why <a href="https://talesfrom.dev/blog/boundaries-modularity-and-a-diaper-effect">boundaries are organized in a certain way</a>, or what <a href="https://talesfrom.dev/blog/the-ambiguity-of-software-architecture">event-driven thinking really means</a> for <a href="https://talesfrom.dev/blog/the-ambiguity-of-software-architecture">how things are structured</a> - the cost is high, and it grows with time. Every decision made on top of a misunderstood foundation adds another layer of drift. Weeks later, no single change is cheap anymore.</p><p>The less shared context there is, the more abstract the topic, the higher the stakes - the further along the TEA spectrum the investment should go.</p><p>&quot;We only have 30 minutes&quot; is often said precisely in the situations where the <strong>Aligning</strong> level matters most.</p><p>And 30 days of work can save 30 minutes of <strong>Aligning</strong>.</p><h3 id="starting-small"><a href="#starting-small" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Starting small</h3><p>You don&#x27;t need to organize a full collaborative modeling session to practice <strong>Aligning</strong>.</p><p>It starts with a single sentence.</p><p>Instead of &quot;did you get it?&quot; - try &quot;can you tell me what you understood?&quot;.</p><p>Instead of &quot;does this make sense?&quot; - try &quot;can you draw what you heard?&quot;.</p><p>Instead of assuming the nod means understanding - treat it as a signal to probe further.</p><p>We are <a href="https://talesfrom.dev/blog/keep-it-visible-smartass">two boxes and an arrow</a> away from surfacing the first gap.</p><p>And the gaps are always there.</p><p>In every technical discussion.</p><p>In every design session.</p><p>In every architecture review.</p><p>Invisible, until someone makes them visible.</p><p>So next time, dear Reader, when you are about to present something important to a colleague, pause before the closing &quot;any questions?&quot;, and try this instead:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Can you tell me what you understood so far - in your own words?</p></div></div></div><p>Then listen.</p><p>Not for agreement.</p><p>For their model.</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>Which level of TEA are you defaulting to?</p>
<p>And what is the cost of that default?</p>
<p>How to change the levels?</p></div></div></div>]]></content:encoded>
    <pubDate>Mon, 29 Jun 2026 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>domain-driven design</category><category>language patterns</category><category>design patterns</category><category>software architecture</category><category>mental models</category><category>communication</category><category>knowledge working</category><category>tools and capabilities</category><category>psychology</category><category>philosophy</category><category>visual thinking</category><category>perception</category><category>perspectives</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/the-ambiguity-of-implementation-details</guid>
    <title>The ambiguity of implementation details: mocking, interactions and abstractions</title>
    <link>https://talesfrom.dev/blog/the-ambiguity-of-implementation-details</link>
    <description>Even if you don&#39;t use mocks, why do you use mocking?</description>
    <content:encoded><![CDATA[<h3 id="just-send-e-mail"><a href="#just-send-e-mail" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Just send e-mail&quot;</h3><p>Imagine that two developers - <span class="italic font-bold text-blue-500">Daniel</span> and <span class="italic font-bold text-yellow-500">Alice</span> - are working on a new feature for their application.</p><p>It is related to sending e-mails, whenever an order was placed.</p><p>Sounds quite typical, right?</p><p>It does not need to be explained, as it&#x27;s a common feature in many applications.</p><p>Of course, they are following <a href="https://talesfrom.dev/blog/tdd-specify-satisfy-simplify">3S</a> workflow (also known as TDD), so they use consumer-expected needs to drive the implementation.</p><p>Fortunately for them, an executable specification was there already:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span>
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">given_an_order_when_placing_order_then_order_is_saved</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> orderToPlace <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token punctuation">{</span> OrderId <span class="token operator">=</span> <span class="token string">&quot;order-123&quot;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> orders <span class="token operator">=</span> _factory<span class="token punctuation">.</span>Services<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">GetRequiredService</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>Orders<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> orderAwaitingPlacing <span class="token operator">=</span> 
</span><span class="code-line">        Order
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">AnyAwaitingPlacing</span><span class="token punctuation">(</span><span class="token punctuation named-parameter">withId</span><span class="token punctuation">:</span> orderToPlace<span class="token punctuation">.</span>OrderId<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">Build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    orders
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span>orderToPlace<span class="token punctuation">.</span>OrderId<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">Returns</span><span class="token punctuation">(</span>orderAwaitingPlacing<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">await</span> _client<span class="token punctuation">.</span><span class="token function">PlaceOrder</span><span class="token punctuation">(</span><span class="token string">&quot;/orders&quot;</span><span class="token punctuation">,</span> orderToPlace<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">await</span> orders<span class="token punctuation">.</span><span class="token function">Received</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>Arg<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Is</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>Order<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span>o <span class="token operator">=&gt;</span> o<span class="token punctuation">.</span>Id <span class="token operator">==</span> <span class="token string">&quot;order-123&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>They needed to grow the system by introducing the new, required behavior.</p><p>But they didn&#x27;t want to express all consumer requirements in a single test, so that <a href="https://talesfrom.dev/blog/the-invisible-role-switching-problem-and-need-driven-design">from designer&#x27;s perspective</a> they could <a href="blog/the-ambiguity-of-easy">more easily</a> locate the problems using very precise specifications:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span>
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">given_an_order_when_placing_order_then_confirmation_email_is_sent</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> orderToPlace <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token punctuation">{</span> OrderId <span class="token operator">=</span> <span class="token string">&quot;order-123&quot;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> orders <span class="token operator">=</span> _factory<span class="token punctuation">.</span>Services<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">GetRequiredService</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>Orders<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> orderAwaitingPlacing <span class="token operator">=</span> 
</span><span class="code-line">        Order
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">AnyAwaitingPlacing</span><span class="token punctuation">(</span><span class="token punctuation named-parameter">withId</span><span class="token punctuation">:</span> orderToPlace<span class="token punctuation">.</span>OrderId<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">WithCustomerEmail</span><span class="token punctuation">(</span><span class="token string">&quot;a@b.com&quot;</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">Build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    orders
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span>orderToPlace<span class="token punctuation">.</span>OrderId<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">Returns</span><span class="token punctuation">(</span>orderAwaitingPlacing<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">await</span> _client<span class="token punctuation">.</span><span class="token function">PlaceOrder</span><span class="token punctuation">(</span><span class="token string">&quot;/orders&quot;</span><span class="token punctuation">,</span> orderToPlace<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> emailSender <span class="token operator">=</span> _factory<span class="token punctuation">.</span>Services<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">GetRequiredService</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>IEmailSender<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">await</span> emailSender<span class="token punctuation">.</span><span class="token function">Received</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Send</span><span class="token punctuation">(</span><span class="token string">&quot;a@b.com&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;Your order has been placed.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span> 
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p><span class="italic font-bold text-blue-500">Daniel</span> wasn&#x27;t happy that compiler was buzzing, as <span class="text-red-500">red color</span> is associated with something &quot;bad&quot;.</p><p>However, <span class="italic font-bold text-yellow-500">Alice</span> calmed him down by saying that they just expressed (or specified) <a href="https://talesfrom.dev/blog/consumer-expected-need-driven-behavior-development">needs</a>, which now requires satisfying.</p><p><code>Orders</code> interface was already there, so they could focus on implementing the missing, new behavior.</p><p>To make everything compiling, <span class="italic font-bold text-blue-500">Daniel</span> firstly created missing interface:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">IEmailSender</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name return-type">Task</span> <span class="token function">Send</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> recipient<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">string</span></span> message<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Right after that, they went to <a href="blog/the-ambiguity-of-easy">the easiest</a> implementation, that satisfies the requirements.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line">app<span class="token punctuation">.</span><span class="token function">MapPost</span><span class="token punctuation">(</span><span class="token string">&quot;/orders&quot;</span><span class="token punctuation">,</span> <span class="token keyword">async</span> <span class="token punctuation">(</span>
</span><span class="code-line">    <span class="token class-name">PlaceOrderRequest</span> request<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">Orders</span> orders<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">IEmailSender</span> emailSender
</span><span class="code-line"><span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> order <span class="token operator">=</span> orders<span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span>request<span class="token punctuation">.</span>OrderId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    order<span class="token punctuation">.</span><span class="token function">Place</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">await</span> orders<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>order<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">await</span> emailSender<span class="token punctuation">.</span><span class="token function">Send</span><span class="token punctuation">(</span>order<span class="token punctuation">.</span>CustomerEmail<span class="token punctuation">,</span> <span class="token string">&quot;Your order has been placed.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">return</span> Results<span class="token punctuation">.</span><span class="token function">Ok</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">record</span> <span class="token class-name">PlaceOrderRequest</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> OrderId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">Orders</span> <span class="token comment">// ✅ it was already here, so no need to create it again</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name return-type">Order</span> <span class="token function">Get</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> id<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token class-name return-type">Task</span> <span class="token function">Save</span><span class="token punctuation">(</span><span class="token class-name">Order</span> order<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>They ran both tests and got <span class="text-green-500">green lights</span>.</p><p>But <span class="italic font-bold text-blue-500">Daniel</span> wasn&#x27;t happy - he heard that using mocks to verify if methods on objects were invoked is a bad practice.</p><p>He suggested going with WireMock and testcontainers in order to not worry about &quot;internals&quot;, also known as &quot;implementation details&quot;.</p><p><span class="italic font-bold text-yellow-500">Alice</span> asked him a bunch of questions in order to understand his mental model, when it comes to designing.</p><p>It quickly turned out that he associated &quot;mocking&quot; with &quot;implementation details&quot;, because that is what major of the software engineering community is saying so.</p><p>She tried to unfold another way of thinking that was more oriented toward <a href="cocoa-from-ports-and-adapters-to-concepts-capabilities-providers">business capabilities</a> - if there is <strong>a need for saving information about placed order</strong>, that is a hard requirement that cannot be omitted, rather than thinking in technical terms.</p><p>So ensuring that the e-mail was correctly sent and that the placed order was saved became a matter of fulfilling business needs, not just verifying technical interactions.</p><h3 id="sometimes-e-mail-sometimes-sms"><a href="#sometimes-e-mail-sometimes-sms" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Sometimes e-mail, sometimes SMS&quot;</h3><p>Change, change never changes.</p><p>It quickly turned out that this was a banger feature - finally customers were able to be informed right after their order was placed.</p><p>But not everyone wanted to use e-mails for achieving so.</p><p>Some customers wanted to receive notifications via SMS instead.</p><p>&quot;Notifications&quot;, <span class="italic font-bold text-yellow-500">Alice</span> said aloud, starting to realize their designing mistake.</p><p><span class="italic font-bold text-blue-500">Daniel</span> didn&#x27;t get it - &quot;what mistake was she talking about?&quot; - he wondered.</p><p>She went to the specs and understood that they did not discover true abstractions, but rather technical mechanisms for deliverying notifications.</p><p>&quot;We need to refactor&quot;, she said to her fellow pair-designer.</p><p>&quot;What? Oh come on, this feature is almost there, gimme the keyboard&quot;, <span class="italic font-bold text-blue-500">Daniel</span> protested.</p><p>Thankfully, he worked with <span class="italic font-bold text-yellow-500">Alice</span> so he had the habit so start with a specification (or rather adjusting it):</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span>
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">given_preference_set_to_email_and_an_order_when_placing_order_then_confirmation_email_is_sent</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> orderToPlace <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token punctuation">{</span> OrderId <span class="token operator">=</span> <span class="token string">&quot;order-123&quot;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> orders <span class="token operator">=</span> _factory<span class="token punctuation">.</span>Services<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">GetRequiredService</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>Orders<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> orderAwaitingPlacing <span class="token operator">=</span>
</span><span class="code-line">        Order
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">AnyAwaitingPlacing</span><span class="token punctuation">(</span><span class="token punctuation named-parameter">withId</span><span class="token punctuation">:</span> orderToPlace<span class="token punctuation">.</span>OrderId<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">WithCustomerEmail</span><span class="token punctuation">(</span><span class="token string">&quot;a@b.com&quot;</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">WithNotificationPreference</span><span class="token punctuation">(</span>NotificationPreference<span class="token punctuation">.</span>Email<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">Build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    orders
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span>orderToPlace<span class="token punctuation">.</span>OrderId<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">Returns</span><span class="token punctuation">(</span>orderAwaitingPlacing<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">await</span> _client<span class="token punctuation">.</span><span class="token function">PlaceOrder</span><span class="token punctuation">(</span><span class="token string">&quot;/orders&quot;</span><span class="token punctuation">,</span> orderToPlace<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> emailSender <span class="token operator">=</span> _factory<span class="token punctuation">.</span>Services<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">GetRequiredService</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>IEmailSender<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">await</span> emailSender<span class="token punctuation">.</span><span class="token function">Received</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Send</span><span class="token punctuation">(</span><span class="token string">&quot;a@b.com&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;Your order has been placed.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>This test failed when executed, so <span class="italic font-bold text-blue-500">Daniel</span> provided the implementation:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line">app<span class="token punctuation">.</span><span class="token function">MapPost</span><span class="token punctuation">(</span><span class="token string">&quot;/orders&quot;</span><span class="token punctuation">,</span> <span class="token keyword">async</span> <span class="token punctuation">(</span>
</span><span class="code-line">    <span class="token class-name">PlaceOrderRequest</span> request<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">Orders</span> orders<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">IEmailSender</span> emailSender
</span><span class="code-line"><span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> order <span class="token operator">=</span> orders<span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span>request<span class="token punctuation">.</span>OrderId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    order<span class="token punctuation">.</span><span class="token function">Place</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">await</span> orders<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>order<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">if</span> <span class="token punctuation">(</span>order<span class="token punctuation">.</span>NotificationPreference <span class="token operator">==</span> NotificationPreference<span class="token punctuation">.</span>Email<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token keyword">await</span> emailSender<span class="token punctuation">.</span><span class="token function">Send</span><span class="token punctuation">(</span>order<span class="token punctuation">.</span>CustomerEmail<span class="token punctuation">,</span> <span class="token string">&quot;Your order has been placed.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">return</span> Results<span class="token punctuation">.</span><span class="token function">Ok</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre></div></div><p>And poof, specs were green again.</p><p>&quot;Now, time for another channel!&quot;, shouted <span class="italic font-bold text-blue-500">Daniel</span>.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span>
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">given_preference_set_to_sms_and_an_order_when_placing_order_then_confirmation_sms_is_sent</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> orderToPlace <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token punctuation">{</span> OrderId <span class="token operator">=</span> <span class="token string">&quot;order-123&quot;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> orders <span class="token operator">=</span> _factory<span class="token punctuation">.</span>Services<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">GetRequiredService</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>Orders<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> orderAwaitingPlacing <span class="token operator">=</span>
</span><span class="code-line">        Order
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">AnyAwaitingPlacing</span><span class="token punctuation">(</span><span class="token punctuation named-parameter">withId</span><span class="token punctuation">:</span> orderToPlace<span class="token punctuation">.</span>OrderId<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">WithCustomerPhone</span><span class="token punctuation">(</span><span class="token string">&quot;+48123456789&quot;</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">WithNotificationPreference</span><span class="token punctuation">(</span>NotificationPreference<span class="token punctuation">.</span>Sms<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">Build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    orders
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span>orderToPlace<span class="token punctuation">.</span>OrderId<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">Returns</span><span class="token punctuation">(</span>orderAwaitingPlacing<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">await</span> _client<span class="token punctuation">.</span><span class="token function">PlaceOrder</span><span class="token punctuation">(</span><span class="token string">&quot;/orders&quot;</span><span class="token punctuation">,</span> orderToPlace<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> smsSender <span class="token operator">=</span> _factory<span class="token punctuation">.</span>Services<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">GetRequiredService</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>ISmsSender<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">await</span> smsSender<span class="token punctuation">.</span><span class="token function">Received</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Send</span><span class="token punctuation">(</span><span class="token string">&quot;+48123456789&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;Your order has been placed.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Satisfying new requirements happened just after that spec:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line">app<span class="token punctuation">.</span><span class="token function">MapPost</span><span class="token punctuation">(</span><span class="token string">&quot;/orders&quot;</span><span class="token punctuation">,</span> <span class="token keyword">async</span> <span class="token punctuation">(</span>
</span><span class="code-line">    <span class="token class-name">PlaceOrderRequest</span> request<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">Orders</span> orders<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">IEmailSender</span> emailSender<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">ISmsSender</span> smsSender
</span><span class="code-line"><span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> order <span class="token operator">=</span> orders<span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span>request<span class="token punctuation">.</span>OrderId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    order<span class="token punctuation">.</span><span class="token function">Place</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">await</span> orders<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>order<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">if</span> <span class="token punctuation">(</span>order<span class="token punctuation">.</span>NotificationPreference <span class="token operator">==</span> NotificationPreference<span class="token punctuation">.</span>Email<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token keyword">await</span> emailSender<span class="token punctuation">.</span><span class="token function">Send</span><span class="token punctuation">(</span>order<span class="token punctuation">.</span>CustomerEmail<span class="token punctuation">,</span> <span class="token string">&quot;Your order has been placed.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">if</span> <span class="token punctuation">(</span>order<span class="token punctuation">.</span>NotificationPreference <span class="token operator">==</span> NotificationPreference<span class="token punctuation">.</span>Sms<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token keyword">await</span> smsSender<span class="token punctuation">.</span><span class="token function">Send</span><span class="token punctuation">(</span>order<span class="token punctuation">.</span>CustomerPhone<span class="token punctuation">,</span> <span class="token string">&quot;Your order has been placed.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">return</span> Results<span class="token punctuation">.</span><span class="token function">Ok</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre></div></div><p>And tests were green again.</p><p>How good feeling is this, ain&#x27;t it dear Reader?</p><p>But <span class="italic font-bold text-yellow-500">Alice</span> remained silent throughout this entire <a href="https://talesfrom.dev/blog/tdd-specify-satisfy-simplify">3S</a> cycle.</p><p>&quot;We need to simplify it, it was very <a href="https://talesfrom.dev/blog/the-ambiguity-of-easy">easy</a> to add this implementation, but any time we do something with notifications, we would need to touch <a href="https://talesfrom.dev/blog/the-ambiguity-of-application">application logic</a>.&quot;, she concluded.</p><p>She also pointed out that number of dependencies increased, which is a strong signal that they are probably missing an abstraction.</p><p>Her pair-designing partner didn&#x27;t get all of these - tests were green, implementation was easy - why worry about abstractions?</p><p><span class="italic font-bold text-yellow-500">Alice</span> asked for a permission to add an alternative implementation, just to see the options they had.</p><p>She asked herself aloud what are the current needs and it turned out they were discussing notification preferences.</p><p>That was their <a href="cocoa-from-ports-and-adapters-to-concepts-capabilities-providers">WHAT</a>, and somehow they already <a href="https://talesfrom.dev/blog/the-ambiguity-of-naming">framed</a> themselves in using <code>Order</code> as the primary source of preferences.</p><p>But order placement capability never specified <a href="cocoa-from-ports-and-adapters-to-concepts-capabilities-providers">HOW</a> it needs to be provided.</p><p>So she started refactoring by introducing missing concepts and structures:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span>
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">given_preference_set_to_email_and_an_order_when_placing_order_then_confirmation_email_is_sent</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> orderToPlace <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token punctuation">{</span> OrderId <span class="token operator">=</span> <span class="token string">&quot;order-123&quot;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> orders <span class="token operator">=</span> _factory<span class="token punctuation">.</span>Services<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">GetRequiredService</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>Orders<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> orderAwaitingPlacing <span class="token operator">=</span>
</span><span class="code-line">        Order
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">AnyAwaitingPlacing</span><span class="token punctuation">(</span><span class="token punctuation named-parameter">withId</span><span class="token punctuation">:</span> orderToPlace<span class="token punctuation">.</span>OrderId<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">WithCustomerEmail</span><span class="token punctuation">(</span><span class="token string">&quot;a@b.com&quot;</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">Build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    orders
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span>orderToPlace<span class="token punctuation">.</span>OrderId<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">Returns</span><span class="token punctuation">(</span>orderAwaitingPlacing<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> notificationPreferenceProvider <span class="token operator">=</span> 
</span><span class="code-line">        _factory
</span><span class="code-line">        <span class="token punctuation">.</span>Services
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token generic-method"><span class="token function">GetRequiredService</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>IProvideNotificationPreference<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// ❌ bzzzzzt, no such interface!</span>
</span><span class="code-line">    
</span><span class="code-line">    notificationPreferenceProvider
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">For</span><span class="token punctuation">(</span>orderAwaitingPlacing<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">Returns</span><span class="token punctuation">(</span>NotificationPreference<span class="token punctuation">.</span>Email<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> emailSender <span class="token operator">=</span> _factory<span class="token punctuation">.</span>Services<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">GetRequiredService</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>IEmailSender<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">await</span> _client<span class="token punctuation">.</span><span class="token function">PlaceOrder</span><span class="token punctuation">(</span><span class="token string">&quot;/orders&quot;</span><span class="token punctuation">,</span> orderToPlace<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">await</span> emailSender<span class="token punctuation">.</span><span class="token function">Received</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Send</span><span class="token punctuation">(</span><span class="token string">&quot;a@b.com&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;Your order has been placed.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Then she created missing interface:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">IProvideNotificationPreference</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name return-type">NotificationPreference</span> <span class="token function">For</span><span class="token punctuation">(</span><span class="token class-name">Order</span> order<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Followed by adjusting the implementation:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line">app<span class="token punctuation">.</span><span class="token function">MapPost</span><span class="token punctuation">(</span><span class="token string">&quot;/orders&quot;</span><span class="token punctuation">,</span> <span class="token keyword">async</span> <span class="token punctuation">(</span>
</span><span class="code-line">    <span class="token class-name">PlaceOrderRequest</span> request<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">Orders</span> orders<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">IProvideNotificationPreference</span> notificationPreferenceProvider<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">IEmailSender</span> emailSender<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">ISmsSender</span> smsSender
</span><span class="code-line"><span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> order <span class="token operator">=</span> orders<span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span>request<span class="token punctuation">.</span>OrderId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    order<span class="token punctuation">.</span><span class="token function">Place</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">await</span> orders<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>order<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> preference <span class="token operator">=</span> notificationPreferenceProvider<span class="token punctuation">.</span><span class="token function">For</span><span class="token punctuation">(</span>order<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">if</span> <span class="token punctuation">(</span>preference <span class="token operator">==</span> NotificationPreference<span class="token punctuation">.</span>Email<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token keyword">await</span> emailSender<span class="token punctuation">.</span><span class="token function">Send</span><span class="token punctuation">(</span>order<span class="token punctuation">.</span>CustomerEmail<span class="token punctuation">,</span> <span class="token string">&quot;Your order has been placed.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">if</span> <span class="token punctuation">(</span>preference <span class="token operator">==</span> NotificationPreference<span class="token punctuation">.</span>Sms<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token keyword">await</span> smsSender<span class="token punctuation">.</span><span class="token function">Send</span><span class="token punctuation">(</span>order<span class="token punctuation">.</span>CustomerPhone<span class="token punctuation">,</span> <span class="token string">&quot;Your order has been placed.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">return</span> Results<span class="token punctuation">.</span><span class="token function">Ok</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre></div></div><p>She also refactored other specs, accommodating the change of introducing a new <a href="https://talesfrom.dev/blog/the-ambiguity-of-interfaces">interface</a>.</p><p>By specifying the interface and interaction in advance, by using <code>NSubstitute</code> (a tool for designing using mocking techniques), she designed the usage of that capability and the contract.</p><p><span class="italic font-bold text-blue-500">Daniel</span> was upset - jira ticket did not say anything about providing notification preferences.</p><p>It was so natural to associate preferences with orders - and it required so little changes.</p><p><span class="italic font-bold text-yellow-500">Alice</span> challenged that perspective by asking what if preferences coming from order is true for today, but tomorrow there will be a dedicated web service providing those - what then?</p><p>&quot;We will change implementation, simple.&quot;, <span class="italic font-bold text-blue-500">Daniel</span> replied.</p><p>But <span class="italic font-bold text-yellow-500">Alice</span> was not finished, she started pulling more capabilities out of the existing implementation:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span>
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">given_preference_set_to_email_and_an_order_when_placing_order_then_customer_is_notified</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> orderToPlace <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token punctuation">{</span> OrderId <span class="token operator">=</span> <span class="token string">&quot;order-123&quot;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> orders <span class="token operator">=</span> _factory<span class="token punctuation">.</span>Services<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">GetRequiredService</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>Orders<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> orderAwaitingPlacing <span class="token operator">=</span>
</span><span class="code-line">        Order
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">AnyAwaitingPlacing</span><span class="token punctuation">(</span><span class="token punctuation named-parameter">withId</span><span class="token punctuation">:</span> orderToPlace<span class="token punctuation">.</span>OrderId<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">Build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    orders
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span>orderToPlace<span class="token punctuation">.</span>OrderId<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">Returns</span><span class="token punctuation">(</span>orderAwaitingPlacing<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> notificationPreferenceProvider <span class="token operator">=</span> 
</span><span class="code-line">        _factory
</span><span class="code-line">        <span class="token punctuation">.</span>Services
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token generic-method"><span class="token function">GetRequiredService</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>IProvideNotificationPreference<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    notificationPreferenceProvider
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">For</span><span class="token punctuation">(</span>orderAwaitingPlacing<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">Returns</span><span class="token punctuation">(</span>NotificationPreference<span class="token punctuation">.</span>Email<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">await</span> _client<span class="token punctuation">.</span><span class="token function">PlaceOrder</span><span class="token punctuation">(</span><span class="token string">&quot;/orders&quot;</span><span class="token punctuation">,</span> orderToPlace<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> notification <span class="token operator">=</span> _factory<span class="token punctuation">.</span>Services<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">GetRequiredService</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>ISendNotification<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// ❌ bzzzzzt, no such concept expressed using code!</span>
</span><span class="code-line">    <span class="token keyword">await</span> notification<span class="token punctuation">.</span><span class="token function">Received</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Send</span><span class="token punctuation">(</span>NotificationPreference<span class="token punctuation">.</span>Email<span class="token punctuation">,</span> orderAwaitingPlacing<span class="token punctuation">,</span> <span class="token string">&quot;Your order has been placed.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p><span class="italic font-bold text-blue-500">Daniel</span> silently observed what the heck she is doing - &quot;new interfaces?!&quot; - he thought.</p><p><span class="italic font-bold text-yellow-500">Alice</span> added missing interface:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">ISendNotification</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name return-type">Task</span> <span class="token function">Send</span><span class="token punctuation">(</span><span class="token class-name">NotificationPreference</span> preference<span class="token punctuation">,</span> <span class="token class-name">Order</span> order<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">string</span></span> message<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>And adjusted other tests, so that they become green again.</p><p>But <span class="italic font-bold text-blue-500">Daniel</span> couldn&#x27;t understand - why so many new interfaces?</p><p>Now they are not 100% sure if the entire system is working, because they are testing against fake implementations!</p><p>In his opinion, it will be easier to use the real implementations and test the system end-to-end, rather then testing implementation details.</p><p><span class="italic font-bold text-yellow-500">Alice</span> to finalize her approach, she showed how real implementations might look like:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">OrderBasedNotificationPreference</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">IProvideNotificationPreference</span></span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">NotificationPreference</span> <span class="token function">For</span><span class="token punctuation">(</span><span class="token class-name">Order</span> order<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> order<span class="token punctuation">.</span>NotificationPreference<span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">InProcessNotificationGateway</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">ISendNotification</span></span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">private</span> <span class="token keyword">readonly</span> <span class="token class-name">IEmailSender</span> _emailSender<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">private</span> <span class="token keyword">readonly</span> <span class="token class-name">ISmsSender</span> _smsSender<span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token function">InProcessNotificationGateway</span><span class="token punctuation">(</span><span class="token class-name">IEmailSender</span> emailSender<span class="token punctuation">,</span> <span class="token class-name">ISmsSender</span> smsSender<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        _emailSender <span class="token operator">=</span> emailSender<span class="token punctuation">;</span>
</span><span class="code-line">        _smsSender <span class="token operator">=</span> smsSender<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">Send</span><span class="token punctuation">(</span><span class="token class-name">NotificationPreference</span> preference<span class="token punctuation">,</span> <span class="token class-name">Order</span> order<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">string</span></span> message<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">if</span> <span class="token punctuation">(</span>preference <span class="token operator">==</span> NotificationPreference<span class="token punctuation">.</span>Email<span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token keyword">await</span> _emailSender<span class="token punctuation">.</span><span class="token function">Send</span><span class="token punctuation">(</span>order<span class="token punctuation">.</span>CustomerEmail<span class="token punctuation">,</span> message<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token keyword">if</span> <span class="token punctuation">(</span>preference <span class="token operator">==</span> NotificationPreference<span class="token punctuation">.</span>Sms<span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token keyword">await</span> _smsSender<span class="token punctuation">.</span><span class="token function">Send</span><span class="token punctuation">(</span>order<span class="token punctuation">.</span>CustomerPhone<span class="token punctuation">,</span> message<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>&quot;Maybe you were correct, after all? Placing an order does not care about the implementation details of notification sending&quot;, she concluded again.</p><p><span class="italic font-bold text-blue-500">Daniel</span> nodded in agreement.</p><p>He knew that he was right all the time.</p><p>He awaited <span class="italic font-bold text-yellow-500">Alice</span>&#x27;s next refactoring, removing that artificially created interface.</p><p>So he observed in silence.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span>
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">given_an_order_when_placing_order_then_customer_is_notified</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> orderToPlace <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token punctuation">{</span> OrderId <span class="token operator">=</span> <span class="token string">&quot;order-123&quot;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> orders <span class="token operator">=</span> _factory<span class="token punctuation">.</span>Services<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">GetRequiredService</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>Orders<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> orderAwaitingPlacing <span class="token operator">=</span>
</span><span class="code-line">        Order
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">AnyAwaitingPlacing</span><span class="token punctuation">(</span><span class="token punctuation named-parameter">withId</span><span class="token punctuation">:</span> orderToPlace<span class="token punctuation">.</span>OrderId<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">Build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    orders
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span>orderToPlace<span class="token punctuation">.</span>OrderId<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">Returns</span><span class="token punctuation">(</span>orderAwaitingPlacing<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">await</span> _client<span class="token punctuation">.</span><span class="token function">PlaceOrder</span><span class="token punctuation">(</span><span class="token string">&quot;/orders&quot;</span><span class="token punctuation">,</span> orderToPlace<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> notification <span class="token operator">=</span> _factory<span class="token punctuation">.</span>Services<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">GetRequiredService</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>ISendNotification<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">await</span> notification<span class="token punctuation">.</span><span class="token function">Received</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Send</span><span class="token punctuation">(</span>orderAwaitingPlacing<span class="token punctuation">,</span> <span class="token string">&quot;Your order has been placed.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p><span class="italic font-bold text-yellow-500">Alice</span> smiled, because of the next specification:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span>
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">given_email_preference_when_sending_notification_then_email_is_sent</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> order <span class="token operator">=</span> 
</span><span class="code-line">        Order
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">AnyAwaitingPlacing</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">WithCustomerEmail</span><span class="token punctuation">(</span><span class="token string">&quot;a@b.com&quot;</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">Build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> preferenceProvider <span class="token operator">=</span> Substitute<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">For</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>IProvideNotificationPreference<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> emailSender <span class="token operator">=</span> Substitute<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">For</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>IEmailSender<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> gateway <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">InProcessNotificationGateway</span><span class="token punctuation">(</span>preferenceProvider<span class="token punctuation">,</span> emailSender<span class="token punctuation">,</span> Substitute<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">For</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>ISmsSender<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    preferenceProvider
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">For</span><span class="token punctuation">(</span>order<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">Returns</span><span class="token punctuation">(</span>NotificationPreference<span class="token punctuation">.</span>Email<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">await</span> gateway<span class="token punctuation">.</span><span class="token function">Send</span><span class="token punctuation">(</span>order<span class="token punctuation">,</span> <span class="token string">&quot;Your order has been placed.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">await</span> emailSender<span class="token punctuation">.</span><span class="token function">Received</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Send</span><span class="token punctuation">(</span><span class="token string">&quot;a@b.com&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;Your order has been placed.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>She ensured that all scenarios were covered, making all tests green too.</p><p>But there was one thing that was really off - &quot;why notification gateway does need to know anything about orders?&quot;, <span class="italic font-bold text-yellow-500">Alice</span> wondered.</p><p>She thought of introducing another concept - a <code>NotificationContent</code> - but decided to leave it, for now.</p><p>They had a very vivid discussion about the whole development process - <span class="italic font-bold text-yellow-500">Alice</span> tried to understand the standpoint of her pair-designer, highlighting the bright sides of using WireMock/testcontainers for the whole test suite.</p><p>Although, she disagreed with making specs much bigger, including many assertions.</p><p>Having the possibility to localize problems through well-defined expectations about interactions, using well-defined contracts, was a must-have in her world.</p><p>And then new requirements arrived.</p><h3 id="notify-about-fact"><a href="#notify-about-fact" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Notify about fact&quot;</h3><p>This time it was <span class="italic font-bold text-fuchsia-500">Jerry</span>, the architect, who came with a requirement: there are other parties interested in a fact of placing an order.</p><p>The idea was simple: emit an event, stating that order was placed, and let others deal with that information.</p><p>&quot;Of course, one of the consequences will be notifying customers about that fact using e-mail or SMS.&quot; <span class="italic font-bold text-blue-500">Daniel</span> assumed.</p><p>&quot;Finally, we won&#x27;t deal with e-mails&quot;, he assumed again.</p><p>&quot;Actually, it&#x27;s a bit opposite. I want to have two ways at the same time - I don&#x27;t know what is the customer experience if we notify them eventually&quot;, said the architect.</p><p><span class="italic font-bold text-blue-500">Daniel</span> couldn&#x27;t believe - how the hell it makes any difference? For the end user it&#x27;s a freaking notification, being delivered, but eventually, because there will be another service doing so.</p><p>&quot;But it will happen, for sure&quot;, he said aloud.</p><p><span class="italic font-bold text-blue-500">Alice</span> was more curious and asked about what is the decision point, when it comes to sending e-mail immediately rather than eventually.</p><p>&quot;Together with product owner, we believe that some customers treat notifications very seriously and they want to get that information as soon as possible&quot;, replied <span class="italic font-bold text-fuchsia-500">Jerry</span>.</p><p>&quot;So we need to send e-mails either immediately or eventually, and always emit events, right?&quot; <span class="italic font-bold text-yellow-500">Alice</span> asked.</p><p>&quot;Yes, but please remember that Notification service is serving multiple consumers and it <strong>can&#x27;t</strong> accept specific information, like <span class="italic font-bold text-blue-500">Daniel</span> suggested, by using events&quot;, <span class="italic font-bold text-fuchsia-500">Jerry</span> observed.</p><p>&quot;And please remember we&#x27;re experimenting to see what will be the customer response, when it comes those deferred notifications&quot;, he continued.</p><p>They know everything that was required to fullfil those requirements.</p><p><span class="italic font-bold text-blue-500">Daniel</span> was so eager earlier to go fully with Event-Driven Architecture, but now he needs to await.</p><p>So <span class="italic font-bold text-yellow-500">Alice</span> started thinking how to satisfy those requirements.</p><p>She wanted to express new concept - selecting Notification gateway - following that abstract idea in tests.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span>
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">given_an_order_when_placing_order_then_customer_is_notified</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> orderToPlace <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token punctuation">{</span> OrderId <span class="token operator">=</span> <span class="token string">&quot;order-123&quot;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> orders <span class="token operator">=</span> _factory<span class="token punctuation">.</span>Services<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">GetRequiredService</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>Orders<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> orderAwaitingPlacing <span class="token operator">=</span>
</span><span class="code-line">        Order
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">AnyAwaitingPlacing</span><span class="token punctuation">(</span><span class="token punctuation named-parameter">withId</span><span class="token punctuation">:</span> orderToPlace<span class="token punctuation">.</span>OrderId<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">WithCustomerId</span><span class="token punctuation">(</span><span class="token punctuation named-parameter">customerId</span><span class="token punctuation">:</span> <span class="token string">&quot;customer-ABC&quot;</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">Build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    orders
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span>orderToPlace<span class="token punctuation">.</span>OrderId<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">Returns</span><span class="token punctuation">(</span>orderAwaitingPlacing<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> notification <span class="token operator">=</span> Substitute<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">For</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>ISendNotification<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> gatewaySelector <span class="token operator">=</span> 
</span><span class="code-line">        _factory
</span><span class="code-line">        <span class="token punctuation">.</span>Services
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token generic-method"><span class="token function">GetRequiredService</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>ISelectNotificationGateway<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// ❌ bzzzzt, no abstract idea expressed in the code yet!</span>
</span><span class="code-line">
</span><span class="code-line">    gatewaySelector
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">SelectFor</span><span class="token punctuation">(</span><span class="token string">&quot;customer-ABC&quot;</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">Returns</span><span class="token punctuation">(</span>Task<span class="token punctuation">.</span><span class="token function">FromResult</span><span class="token punctuation">(</span>notification<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">await</span> _client<span class="token punctuation">.</span><span class="token function">PlaceOrder</span><span class="token punctuation">(</span><span class="token string">&quot;/orders&quot;</span><span class="token punctuation">,</span> orderToPlace<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">await</span> notification<span class="token punctuation">.</span><span class="token function">Received</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Send</span><span class="token punctuation">(</span>orderAwaitingPlacing<span class="token punctuation">,</span> <span class="token string">&quot;Your order has been placed.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>To calm down the compiler, new interface was immediately added:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">ISelectNotificationGateway</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>ISendNotification<span class="token punctuation">&gt;</span></span> <span class="token function">SelectFor</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> customerId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p><span class="italic font-bold text-blue-500">Daniel</span> was shocked - mock returning mock?</p><p>&quot;This is such an anti-pattern&quot;, he commented aloud.</p><p><span class="italic font-bold text-yellow-500">Alice</span> just mentioned that she used it to design interactions and contracts.</p><p>&quot;Internal ones, right?&quot;, he continued.</p><p>&quot;Well, yes, capabilities required by order placement, according to our new understanding&quot;, she replied.</p><p><span class="italic font-bold text-yellow-500">Alice</span> satisfied specification with the following implementation:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line">app<span class="token punctuation">.</span><span class="token function">MapPost</span><span class="token punctuation">(</span><span class="token string">&quot;/orders&quot;</span><span class="token punctuation">,</span> <span class="token keyword">async</span> <span class="token punctuation">(</span>
</span><span class="code-line">    <span class="token class-name">PlaceOrderRequest</span> request<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">Orders</span> orders<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">ISelectNotificationGateway</span> gatewaySelection<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">IPublishEvent</span> publisher
</span><span class="code-line"><span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> order <span class="token operator">=</span> orders<span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span>request<span class="token punctuation">.</span>OrderId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    order<span class="token punctuation">.</span><span class="token function">Place</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">await</span> orders<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>order<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">await</span> publisher<span class="token punctuation">.</span><span class="token function">Publish</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name constructor-invocation">OrderPlaced</span><span class="token punctuation">(</span>order<span class="token punctuation">.</span>Id<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> gateway <span class="token operator">=</span> <span class="token keyword">await</span> gatewaySelection<span class="token punctuation">.</span><span class="token function">SelectFor</span><span class="token punctuation">(</span>order<span class="token punctuation">.</span>CustomerId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">await</span> gateway<span class="token punctuation">.</span><span class="token function">Send</span><span class="token punctuation">(</span>order<span class="token punctuation">,</span> <span class="token string">&quot;Your order has been placed.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">return</span> Results<span class="token punctuation">.</span><span class="token function">Ok</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre></div></div><p>This sparked a new conversation, related to ratio of customers that should use deferred notifications. It turned out that it should be no more than 5% of customers.</p><p>According to the established understanding, the follwing implementation happened:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ExperimentalRandomizedNotificationGatewaySelection</span><span class="token punctuation">(</span>
</span><span class="code-line">    <span class="token class-name">InProcessNotificationGateway</span> immediateNotificationGateway<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">NotificationWebGatewayHttpClient</span> eventualNotificationGateway
</span><span class="code-line"><span class="token punctuation">)</span> <span class="token punctuation">:</span> ISelectNotificationGateway
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>ISendNotification<span class="token punctuation">&gt;</span></span> <span class="token function">SelectFor</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> customerId<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token class-name">ISendNotification</span> gateway <span class="token operator">=</span> Random<span class="token punctuation">.</span>Shared<span class="token punctuation">.</span><span class="token function">NextDouble</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&lt;</span> <span class="token number">0.05</span>
</span><span class="code-line">            <span class="token punctuation">?</span> eventualNotificationGateway
</span><span class="code-line">            <span class="token punctuation">:</span> immediateNotificationGateway<span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token keyword">return</span> Task<span class="token punctuation">.</span><span class="token function">FromResult</span><span class="token punctuation">(</span>gateway<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>They shipped it, awaited some time period and observed the results.</p><p>It turned out that some customers were happy to pay a little more in order to get notification in a guaranteed time.</p><p><span class="italic font-bold text-blue-500">Daniel</span> was surprised by the unexpected outcome.</p><p>He couldn&#x27;t believe that customers were willing to pay more for notifications.</p><p><span class="italic font-bold text-yellow-500">Alice</span> explained that it was not about notifications, but about purchasing priority.</p><p>It might have sounded as it was a mere detail, but that framing was crucial for understanding customer behavior.</p><p>And stop &quot;just coding&quot; and start thinking in terms of producing value, as customers would have never think of that themselves.</p><p>As this feature was proven to be valuable, they decided to provide it only for subscribed customers, which drove the implementation toward the following capability:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">SubscriptionBasedNotificationGatewaySelection</span><span class="token punctuation">(</span>
</span><span class="code-line">    <span class="token class-name">ICheckCustomerSubscription</span> subscriptions<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">InProcessNotificationGateway</span> immediateNotificationGateway<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">NotificationWebGatewayHttpClient</span> eventualNotificationGateway<span class="token punctuation">)</span> <span class="token punctuation">:</span> ISelectNotificationGateway
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>ISendNotification<span class="token punctuation">&gt;</span></span> <span class="token function">SelectFor</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> customerId<span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
</span><span class="code-line">        <span class="token keyword">await</span> subscriptions<span class="token punctuation">.</span><span class="token function">HasSubscribedToNotificationPriority</span><span class="token punctuation">(</span>customerId<span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token punctuation">?</span> immediateNotificationGateway
</span><span class="code-line">            <span class="token punctuation">:</span> eventualNotificationGateway<span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Fortunately, there was company-wide subscriptions web service that provided such capabilities, so it was very easy to integrate.</p><p>And thankfully, the structure, that emerged through gaining understanding, was ready for accommodating incoming changes.</p><h3 id="implementation-details"><a href="#implementation-details" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Implementation details?</h3><p>&quot;Come on, mocking in 2026 with AI?!&quot;, some might think right now.</p><p>Well, yes.</p><p>It is not mocking that is &quot;bad&quot; on its own, it&#x27;s the operator that truly makes the difference.</p><p>As we discussed some time ago - everything boils down to <a href="https://talesfrom.dev/blog/composing-a-pie">composing a PIE</a>.</p><p>Based on <strong>P</strong>urpose (driven by needs) we design <strong>I</strong>nteractions between <strong>E</strong>lements.</p><p>We saw two developers building understanding of what needs to be delivered and then they designed proper <strong>communication structure</strong> between <strong>elements</strong>.</p><p><span class="italic font-bold text-yellow-500">Alice</span> mindfully organized this communication letting certain <strong>abstractions</strong> to emerge.</p><p>Not <code>NotificationService</code> or <code>NotificationManager</code>, but symbols and ideas that were appearing in human language, as they spoke and listened to each other.</p><p><code>NotificationContent</code>, <code>NotificationPreference</code>, <code>NotificationGateway</code> and so on.</p><p>These abstractions allowed them to reason about the system at a higher level, focusing on the <strong>value</strong> delivered to the customer rather than the <strong>mechanics</strong> of implementation.</p><p>Considering they properly abstracted away details.</p><p>But really, what are implementation details?</p><p>Often time one might heard that mocks are &quot;bad&quot; because they make the tests brittle and tightly coupled to the <strong>implementation</strong>.</p><p>Same as the claim that mocks are breaking encapsulation - what is really <a href="https://talesfrom.dev/blog/the-ambiguity-of-encapsulation">encapsulation</a>? (you might be interested in a great <a href="https://feelings-erased.blogspot.com/2014/01/mocks-are-breaking-encapsulation-heres.html">article</a> by Grzegorz Gałęzowski about alleged encapsulation breaking and why we might incorrectly think about it)</p><p>As yet again we get trapped in thinking in static labels, names - &quot;mocks&quot;.</p><p>What if <strong>mocking</strong> is actually <a href="https://www.codurance.com/publications/2018/10/18/mocking-as-a-design-tool">a design tool</a>?</p><p>So it is a process of <strong>designing</strong>. Designing what?</p><p>Interactions.</p><p>How certain <a href="https://talesfrom.dev/blog/concepts-entities-data">concepts</a> interact with each other.</p><p>What are relationships between abstractions, but not in a static, &quot;data&quot; sense, but when those abstractions are in motion, when they &quot;act&quot;.</p><p>To understand how they <a href="https://talesfrom.dev/blog/context-segregation-principle">collaborate behaviorally</a>.</p><p>Or rather, how do we want them to collaborate with each other.</p><p>It might be that those &quot;implementation details&quot; are actually interaction requirements we specify (as <a href="https://talesfrom.dev/blog/the-invisible-role-switching-problem-and-need-driven-design">designers</a>) so that certain abstractions can provide them.</p><p>Abstractions we introduce so that we can raise the level of being specific.</p><p>Abstractions that aim at creating a specific <a href="https://talesfrom.dev/blog/boundaries-modularity-and-a-diaper-effect">boundary</a> that expresses certain language.</p><p>Often times those &quot;implementation details&quot; might create an effect that some call &quot;brittle tests from over-mocking&quot; - but if actually those &quot;brittle tests&quot; are diagnostic signal trying to highlight <strong>poor abstraction discipline</strong>?</p><p>Expressing <a href="https://talesfrom.dev/blog/the-ambiguity-of-interfaces">roles and their interactions</a> that might be actually quite stable, if we <a href="https://talesfrom.dev/blog/modeling-maturity-levels">model them at certain level</a>.</p><p>It might quickly turned out that interfaces do not represent the correct behavioral boundaries, but are rather a reflection of our current understanding.</p><p>Or rather - misunderstanding.</p><p>And shallow analysis of the problem area.</p><p>Poor abstraction discipline is frequently a symptom of implementation-first thinking, leaking <strong>details</strong> that should have been hidden inside a particular boundary.</p><p>And it is our job to understand the problem, language that lives inside of that area, decompose the purpose into a set of collaborating roles, named after what they do, not what they are or how they do it.</p><p>Translating that purpose into interactions of elements, provided that we build proper structure around our understanding, will bring stable abstractions, without the dreaded details.</p><p>Maybe those details are poorly designed abstractions, dear Reader?</p><h3 id="consumer-observable-behavior-you-fool"><a href="#consumer-observable-behavior-you-fool" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Consumer observable behavior&quot; you fool!</h3><p>What about notifying customers using some kind of preferred delivery mechanism?</p><p>Does it really matter <strong>how</strong> those notifications are delivered?</p><p>Isn&#x27;t it &quot;the implementation detail&quot;?</p><p>Well, some might say yes, some might say no.</p><p>Then, why &quot;no&quot;?</p><p>Behavior is exactly the same, isn&#x27;t it?</p><p>Well, what if an external Notification web service has a priority queue and some customers might be notified later than others?</p><p>Behavior might be exactly the same, but experience will significantly vary.</p><p>That is why quality attributes are truly important - they add more dimensions to the provided solution.</p><p>Those quality attributes emerge from the interactions between abstractions, that form boundaries, hiding certain details, from consumers&#x27; sight.</p><p>Features is the easy part.</p><p>Expressing important abstractions and how they interact - &quot;the structure&quot; - this is often the hard part.</p><p>It might turn out quickly that the notification delivery mechanism might actually matter - as it changes the reception of our provided capabilities.</p><p>One might conclude that there is a crucial nuance that the consumer is relative to the boundary you&#x27;re looking at - that&#x27;s why Outside-In Designing is so powerful, because one is traversing various boundaries and then designing accordingly.</p><p>&quot;Implementation detail&quot; is not an absolute property of a piece of code. It is a <strong>relational concept</strong> — defined by who is observing and from which boundary (or from what level).</p><p>And if mocking (a workflow/a process) is a designing technique that might teach us about interactions and boundaries - how does it contribute to thinking on other levels, outside of a single boundary?</p><h3 id="eda---eventing-dopamine-addiction"><a href="#eda---eventing-dopamine-addiction" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>EDA - Eventing Dopamine Addiction</h3><p>Let&#x27;s try to <a href="https://talesfrom.dev/blog/keep-it-visible-smartass">visualize</a> the simple workflow using Event Storming notation.</p><p><span class="text-orange-500">Orange stickies</span> are events, <span class="text-blue-400">blue stickies</span> are commands and <span class="text-yellow-400">yellow stickies</span> are rules.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-implementation-details-placing-order-workflow-start.svg" class="min-h-[10rem]"/></div><div class="italic">Exploring the problem</div></div><p>To better understand the needs, we could follow up with a question - &quot;what is a consequence of placing an order?&quot;</p><p>And some might of course come up with a notification - e-mail one.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-implementation-details-placing-order-workflow-notification.svg" class="min-h-[10rem]"/></div><div class="italic">Important information revealed</div></div><p>And as <span class="italic font-bold text-blue-500">Daniel</span> immediately saw - event here, event there, so placing order abstraction <strong>interacts</strong> with notifications in a very particular way - notifications consume events to trigger their behavior.</p><p>But is it the only way boundaries can interact?</p><p>It might be that designed interaction is not the correct one and might be quite costly if we continue down this path.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-implementation-details-placing-order-workflow-missing-interaction.svg" class="min-h-[26rem]"/></div><div class="italic">Another way of organizing interactions between boundaries - <span class="text-green-300">green stickies</span> are information, <span class="text-pink-500">pink stickies</span> are external systems</div></div><p>That is what <span class="italic font-bold text-fuchsia-500">Jerry</span> tried to communicate - some abstractions are much more stable than others and interactions should be designed accordingly.</p><p>If one organizes interactions incorrectly then details from one boundary might leak into another, causing unintended consequences and increasing complexity, operational costs and simply frustration.</p><p>Notifications are pretty stable concept (abstraction), whereas Orders might change more frequently - sometimes because of the business side, other times because of regulation.</p><p>Also, notice the language change - notifications are not using language of orders.</p><p>Inside their boundary there is nothing like &quot;order&quot; - there are recipients, notification contents, notification preferences, maybe notification priority?</p><p>As with &quot;brittle tests from over-mocking&quot; (which is a misnomer), coupling to details might be a wrong way of organizing interactions between elements - that are simply abstractions, but sometimes expressed on various levels.</p><p>Subsystems (Notifications) or small objects (Notifications).</p><p>Essentially, poorly designed abstractions (which means - <a href="cocoa-from-ports-and-adapters-to-concepts-capabilities-providers">behavioral models</a>) is what we typically might be dealing with, but &quot;coupling to implementation details&quot; is a consequence of that.</p><p>Focus on finding proper abstractions rather than fixating on implementation details.</p><p>They are truly a detail (pun intended) when it comes to a process of organizing interactions between boundaries.</p><h3 id="mocking-ddd-abstractions"><a href="#mocking-ddd-abstractions" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Mocking? DDD? Abstractions?</h3><p>In Domain-Driven Design we say and think a lot about models expressing <a href="context-segregation-principle">contextual behaviors</a> - which can be translated into abstractions interacting with each other.</p><p>Relating to each other, in certain moments of <a href="https://talesfrom.dev/blog/time-angle-and-depth-dimensions-in-software-design">time</a>, in specific way.</p><p>If one uses brittle tests and <a href="boundaries-modularity-and-a-diaper-effect">challenging integrations between bounded contexts</a> as diagnostic signals, we might eventually learn and improve ways how elements interact with each other.</p><p>Elements having different meaning, depending on the level we are currently reasoning at.</p><p>Which might lead to finding proper models or abstractions, or boundaries, or whatever.</p><p>It was always about the same thing, although the <a href="https://talesfrom.dev/blog/the-ambiguity-of-naming">names</a> might be changed.</p><p>Every brittle test is a friend in disguise - use it to guide you towards better abstractions and interactions.</p><p>Every challenging integration is an opportunity to refine boundaries, improve the language and communication structure.</p><p>Next time dear Reader when your tests are failing or you need to participate in yet another meeting about integration between services, ask yourself</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>What those signals are trying to tell me?</p>
<p>Is there a better way to organize interactions or abstractions?</p>
<p>Did I represent abstractions correctly?</p>
<p>What abstract concepts am I missing?</p></div></div></div>]]></content:encoded>
    <pubDate>Tue, 28 Apr 2026 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>domain-driven design</category><category>language patterns</category><category>design patterns</category><category>software architecture</category><category>mental models</category><category>communication</category><category>knowledge working</category><category>tools and capabilities</category><category>psychology</category><category>philosophy</category><category>visual thinking</category><category>perception</category><category>perspectives</category><category>test-driven development</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/the-ambiguity-of-easy</guid>
    <title>The ambiguity of easy: what does it mean?</title>
    <link>https://talesfrom.dev/blog/the-ambiguity-of-easy</link>
    <description>When discussing quality attributes - who&#39;s asking?</description>
    <content:encoded><![CDATA[<h3 id="i-want-it-to-be-easy"><a href="#i-want-it-to-be-easy" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;I want it to be easy&quot;</h3><p>Imagine that three people - <span class="italic font-bold text-red-500">Alice, the Architect</span>, <span class="italic font-bold text-blue-500">Peter, the Providing Developer</span>, and <span class="italic font-bold text-green-500">Chris, the Consuming Developer</span> - are discussing a new feature for their software application.</p><p><span class="italic font-bold text-green-500">Chris, the Consuming Developer</span> wants a new capability to be provided so that his team can complete their work.</p><p>Both the architect and the providing developer represent the another side of the relationship, trying to understand the needs.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div><span class="italic font-bold text-green-500">Chris, the Consuming Developer</span>: Hey! Finally, we have the new feature we&#x27;ve been waiting for.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-blue-500">Peter, the Providing Developer</span>: Hi! Yes, I hope we will be able to respond to your call quite efficiently.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-red-500">Alice, the Architect</span>: Let&#x27;s make sure we understand the requirements clearly before we proceed.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-green-500">Chris, the Consuming Developer</span>: So, I need an HTTP endpoint that enables ordering an equipment for each worker identifier or worker reference provided.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-blue-500">Peter, the Providing Developer</span>: Why do you need both identifiers and references?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-green-500">Chris, the Consuming Developer</span>: Well, sometimes we have the worker&#x27;s ID, and other times we only have a reference. We need the endpoint to handle both cases.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-red-500">Alice, the Architect</span>: If we are going to provide you such capability, we need to have a uniform contract so that others might use it too.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-green-500">Chris, the Consuming Developer</span>: I just want it to be easy to use. That&#x27;s it. I don&#x27;t see what is the problem.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-blue-500">Peter, the Providing Developer</span>: Hmm, I see your point, but the implementation wouldn&#x27;t be that easy for us - we don&#x27;t use references at all. I would need to introduce logic to handle that.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-red-500">Alice, the Architect</span>: It is not the first time when we&#x27;ve encountered such a situation - dual way of identifying resources can lead to inconsistencies which later on makes it harder to maintain the system.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-blue-500">Peter, the Providing Developer</span>: I think I could ask another service that contains the master data for workers - maybe it could exchange worker identifiers? Then would be super easy for me to provide the capability you need, honouring both identifiers - because I would delegate everything to the upstream service and we already use it in another place of the system.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-red-500">Alice, the Architect</span>: I don&#x27;t like it - it does not make it easy from the system perspective - I don&#x27;t want Peter&#x27;s service to be responsible for exchanging identifiers. I think we need to be always based on a worker identifier, and forget about references. This will make it easier for everyone.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-green-500">Chris, the Consuming Developer</span>: &quot;Easier for everyone&quot;? You must be kidding, right? I just told you I can&#x27;t guarantee that we will always have the worker&#x27;s ID.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-red-500">Alice, the Architect</span>: If you can&#x27;t, then you need to exchange identities. Peter&#x27;s service shouldn&#x27;t do it, in my opinion. From the system perspective, this service shouldn&#x27;t even know about &quot;worker reference&quot;.</div></span></div><p>As they were doing circles without any outcomes, someone got an idea to start <a href="https://talesfrom.dev/blog/keep-it-visible-smartass">visualizing</a> various options.</p><p>They went with Event Storming notation and conjured a quick process level diagram.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-quality-attributes-process.svg" class="min-h-[28rem]"/></div><div class="italic">Process level Event Storming for a tiny worker assignment process</div></div><p>Neither of them liked the solution of another, because it either put too much responsibilities on one side or made the system harder to maintain.</p><p>They tried to find consensus, but it was tough to be achieved, knowing the constraints they had.</p><p>Being caught in &quot;analysis paralysis&quot; isn&#x27;t the best state, <span class="italic font-bold text-red-500">Alice, the Architect</span> noticed that and decided to write <a href="https://talesfrom.dev/blog/the-ambiguity-of-architecture-decision-records">an ADR</a> in which they specify all options.</p><p>Then the architect decided to go with the option putting the responsibility for identifiers exchange on the <span class="italic font-bold text-green-500">Chris, the Consuming Developer</span> side.</p><p>Of course, it didn&#x27;t make him happy, but at least they moved on, remembering that &quot;Bad decision isn&#x27;t bad, if you know it&#x27;s bad&quot;.</p><h3 id="at-least-its-easy"><a href="#at-least-its-easy" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;At least it&#x27;s easy&quot;</h3><p>As it was decided, <span class="italic font-bold text-green-500">Chris, the Consuming Developer</span> is going to handle the exchange of identifiers.</p><p>In fact, he is providing yet another capability - assigning workers to jobs - which is consumed by the web application.</p><p>So <span class="italic font-bold text-green-500">Chris, the Consuming Developer</span> also plays the role of a provider.</p><p><span class="italic font-bold text-green-500">Chris, the Consuming Developer</span> wanted to have easy interface provided by <span class="italic font-bold text-blue-500">Peter&#x27;s</span> service, but it turned out that it wasn&#x27;t that easy (pun intended) to convince people.</p><p>So then he started specifying the capability that his service is going to provide, knowing that along with consuming equipment ordering capability, it also needs consume identifiers exchanging.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span>
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">given_existing_job_when_successfully_assigning_worker_by_id_then_confirms_successful_assignment</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> jobId <span class="token operator">=</span> <span class="token string">&quot;job-123&quot;</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> workerId <span class="token operator">=</span> <span class="token string">&quot;b692976a-b25c-450c-a5e1-c190cd5c09c4&quot;</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> response <span class="token operator">=</span> <span class="token keyword">await</span> _client<span class="token punctuation">.</span><span class="token function">PutAsync</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;/jobs/</span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">jobId</span><span class="token punctuation">}</span></span><span class="token string">/assign/</span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">workerId</span><span class="token punctuation">}</span></span><span class="token string">&quot;</span></span><span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    response<span class="token punctuation">.</span>StatusCode<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span>HttpStatusCode<span class="token punctuation">.</span>OK<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>The test failed ❌ because there was no implementation.</p><p>This is what a consumer of his service would do to assign a worker to a job, and what expects to get back as confirmation.</p><p>Implementation is also straightforward:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line">app<span class="token punctuation">.</span><span class="token function">MapPut</span><span class="token punctuation">(</span><span class="token string">&quot;/jobs/{jobId}/assign/{workerIdOrWorkerReference}&quot;</span><span class="token punctuation">,</span> <span class="token comment">// 👈 new!</span>
</span><span class="code-line">    <span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> jobId<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">string</span></span> workerIdOrWorkerReference<span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">return</span> Results<span class="token punctuation">.</span><span class="token function">Ok</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre></div></div><p>And this made the test passed ✅.</p><p><span class="italic font-bold text-green-500">Chris, the Consuming Developer</span> then specifies the next consequence of successful assignment - saving the assignment.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span>
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">given_existing_job_when_successfully_assigning_worker_by_id_then_assignment_is_saved</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> jobId <span class="token operator">=</span> <span class="token string">&quot;job-123&quot;</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> workerId <span class="token operator">=</span> <span class="token string">&quot;b692976a-b25c-450c-a5e1-c190cd5c09c4&quot;</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">await</span> _client<span class="token punctuation">.</span><span class="token function">PutAsync</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;/jobs/</span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">jobId</span><span class="token punctuation">}</span></span><span class="token string">/assign/</span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">workerId</span><span class="token punctuation">}</span></span><span class="token string">&quot;</span></span><span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> assignments <span class="token operator">=</span> 
</span><span class="code-line">        _factory<span class="token punctuation">.</span>Services<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">GetRequiredService</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>IGetAssignmentById<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 👈 in runtime this resolves to `PostgresAssignmentRepository`</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> assignment <span class="token operator">=</span> <span class="token keyword">await</span> assignments<span class="token punctuation">.</span><span class="token function">GetById</span><span class="token punctuation">(</span>jobId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    assignment<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">NotBeNull</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    assignment<span class="token operator">!</span><span class="token punctuation">.</span>WorkerId<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span>workerId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>The test failed ❌ because there was no saving yet.</p><p>Thankfully, the solution already uses testcontainers so it is super easy to run these tests in an isolated environment.</p><p>No mocking required, so less amount of code is needed to actually verify the real saving to database.</p><p>The downside is that this simple test requires additional time to start the Postgres container.</p><p>Then, <span class="italic font-bold text-green-500">Chris, the Consuming Developer</span> implements the remaining logic:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line">app<span class="token punctuation">.</span><span class="token function">MapPut</span><span class="token punctuation">(</span><span class="token string">&quot;/jobs/{jobId}/assign/{workerIdOrWorkerReference}&quot;</span><span class="token punctuation">,</span> 
</span><span class="code-line"><span class="token keyword">async</span> <span class="token punctuation">(</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">string</span></span> jobId<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">string</span></span> workerIdOrWorkerReference<span class="token punctuation">,</span>
</span><span class="code-line">    ISaveAssignment assignments <span class="token comment">// 👈 new!</span>
</span><span class="code-line"><span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">await</span> assignments<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name constructor-invocation">Assignment</span><span class="token punctuation">(</span>jobId<span class="token punctuation">,</span> workerIdOrWorkerReference<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 👈 new!</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">return</span> Results<span class="token punctuation">.</span><span class="token function">Ok</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre></div></div><p>And now, both tests passed ✅.</p><p><span class="italic font-bold text-green-500">Chris</span> isn&#x27;t an advocate for such <a href="https://talesfrom.dev/blog/the-ambiguity-of-interfaces">narrow interfaces</a>, they seem too fine-grained, too unit-esque.</p><p>It isn&#x27;t something that he decided on - if we could, he would name it as <code>IAssignmentsRepository</code>, at least the pattern is well-known in the industry.</p><p>But he asked himself - &quot;are there any benefits of using such narrow interfaces?&quot;, but a message on Teams broke this insightful moment.</p><p>The consumer of the capability provided by <span class="italic font-bold text-green-500">Chris&#x27;s</span> service can now confidently assign workers to jobs and have those assignments saved correctly, along with expected confirmation response.</p><p>But even those tests are small, working on real database interactions provides a delayed feedback, as tests startup takes longer.</p><p>&quot;At least it&#x27;s easy to write those tests, as I don&#x27;t need unnecessary mocking.&quot;, thought <span class="italic font-bold text-green-500">Chris, the Consuming Developer</span>.</p><h3 id="lets-not-complicate-it"><a href="#lets-not-complicate-it" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Let&#x27;s not complicate it&quot;</h3><p><span class="italic font-bold text-green-500">Chris, the Consuming Developer</span> to progress with provided capability, it&#x27;s time to order equipment using <span class="italic font-bold text-blue-500">Peter, the Providing Developer</span>.</p><p>&quot;The easiest would be to verify ordering on the HTTP level&quot;, told <span class="italic font-bold text-green-500">Chris, the Consuming Developer</span> himself.</p><p>So he did it:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span>
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">given_existing_job_when_successfully_assigning_worker_by_id_then_equipment_is_ordered</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> jobId <span class="token operator">=</span> <span class="token string">&quot;job-123&quot;</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> workerId <span class="token operator">=</span> <span class="token string">&quot;b692976a-b25c-450c-a5e1-c190cd5c09c4&quot;</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    _wiremock
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">Given</span><span class="token punctuation">(</span>Request<span class="token punctuation">.</span><span class="token function">Create</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token punctuation">.</span><span class="token function">WithPath</span><span class="token punctuation">(</span><span class="token string">&quot;/equipment-orders&quot;</span><span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token punctuation">.</span><span class="token function">UsingPost</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">RespondWith</span><span class="token punctuation">(</span>Response<span class="token punctuation">.</span><span class="token function">Create</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token punctuation">.</span><span class="token function">WithStatusCode</span><span class="token punctuation">(</span>HttpStatusCode<span class="token punctuation">.</span>OK<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">await</span> _client<span class="token punctuation">.</span><span class="token function">PutAsync</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;/jobs/</span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">jobId</span><span class="token punctuation">}</span></span><span class="token string">/assign/</span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">workerId</span><span class="token punctuation">}</span></span><span class="token string">&quot;</span></span><span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    _wiremock<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">HaveReceived</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Calls</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">WithPath</span><span class="token punctuation">(</span><span class="token string">&quot;/equipment-orders&quot;</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">UsingPost</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">WithBodyAsJson</span><span class="token punctuation">(</span>b <span class="token operator">=&gt;</span> b<span class="token punctuation">.</span>WorkerId <span class="token operator">==</span> workerId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>The test failed ❌ because there was no implementation of equipment ordering.</p><p>Observing unsatisfied behavior, the developer stated implementing it:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line">app<span class="token punctuation">.</span><span class="token function">MapPut</span><span class="token punctuation">(</span><span class="token string">&quot;/jobs/{jobId}/assign/{workerIdOrWorkerReference}&quot;</span><span class="token punctuation">,</span> <span class="token keyword">async</span> <span class="token punctuation">(</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">string</span></span> jobId<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">string</span></span> workerIdOrWorkerReference<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">ISaveAssignment</span> assignments<span class="token punctuation">,</span>
</span><span class="code-line">    HttpClient equipmentOrderingClient <span class="token comment">// 👈 new!</span>
</span><span class="code-line"><span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">await</span> assignments<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name constructor-invocation">Assignment</span><span class="token punctuation">(</span>jobId<span class="token punctuation">,</span> workerIdOrWorkerReference<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">await</span> equipmentOrderingClient<span class="token punctuation">.</span><span class="token function">PostAsJsonAsync</span><span class="token punctuation">(</span><span class="token string">&quot;/equipment-orders&quot;</span><span class="token punctuation">,</span> <span class="token keyword">new</span> <span class="token comment">// 👈 new!</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        WorkerId <span class="token operator">=</span> workerIdOrWorkerReference
</span><span class="code-line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">return</span> Results<span class="token punctuation">.</span><span class="token function">Ok</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre></div></div><p>And this made all tests pass ✅.</p><p>He observed even longer time needed to get feedback.</p><p>Here came the final boss - exchanging worker identifiers. Thankfully, <span class="italic font-bold text-red-500">Alice, the Architect</span> provided the necessary contract for doing the exchange.</p><p>It was a simple HTTP GET interaction to <a href="https://api.workers.bigcorp.io/workers/%7BworkerIdOrWorkerReference%7D">https://api.workers.bigcorp.io/workers/{workerIdOrWorkerReference}</a>, which gave entire worker object back.</p><p>Specifying this behavior for scenario with worker reference was easy, as WireMock.NET was already used:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span>
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">given_existing_job_when_assigning_worker_by_reference_then_worker_should_be_assigned_to_job</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> jobId <span class="token operator">=</span> <span class="token string">&quot;job-123&quot;</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> workerReference <span class="token operator">=</span> <span class="token string">&quot;EMP-ABC&quot;</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> resolvedWorkerId <span class="token operator">=</span> <span class="token string">&quot;b692976a-b25c-450c-a5e1-c190cd5c09c4&quot;</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    _wiremock
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">Given</span><span class="token punctuation">(</span>Request<span class="token punctuation">.</span><span class="token function">Create</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token punctuation">.</span><span class="token function">WithPath</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;/workers/</span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">workerReference</span><span class="token punctuation">}</span></span><span class="token string">&quot;</span></span><span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token punctuation">.</span><span class="token function">UsingGet</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">RespondWith</span><span class="token punctuation">(</span>Response<span class="token punctuation">.</span><span class="token function">Create</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token punctuation">.</span><span class="token function">WithStatusCode</span><span class="token punctuation">(</span>HttpStatusCode<span class="token punctuation">.</span>OK<span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token punctuation">.</span><span class="token function">WithBodyAsJson</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token punctuation">{</span> Id <span class="token operator">=</span> resolvedWorkerId<span class="token punctuation">,</span> Reference <span class="token operator">=</span> workerReference <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    _wiremock
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">Given</span><span class="token punctuation">(</span>Request<span class="token punctuation">.</span><span class="token function">Create</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token punctuation">.</span><span class="token function">WithPath</span><span class="token punctuation">(</span><span class="token string">&quot;/equipment-orders&quot;</span><span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token punctuation">.</span><span class="token function">UsingPost</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">RespondWith</span><span class="token punctuation">(</span>Response<span class="token punctuation">.</span><span class="token function">Create</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token punctuation">.</span><span class="token function">WithStatusCode</span><span class="token punctuation">(</span>HttpStatusCode<span class="token punctuation">.</span>OK<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> response <span class="token operator">=</span> <span class="token keyword">await</span> _client<span class="token punctuation">.</span><span class="token function">PutAsync</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;/jobs/</span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">jobId</span><span class="token punctuation">}</span></span><span class="token string">/assign/</span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">workerReference</span><span class="token punctuation">}</span></span><span class="token string">&quot;</span></span><span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    response<span class="token punctuation">.</span>StatusCode<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span>HttpStatusCode<span class="token punctuation">.</span>OK<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    _wiremock<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">HaveReceived</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Calls</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">WithPath</span><span class="token punctuation">(</span><span class="token string">&quot;/equipment-orders&quot;</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">UsingPost</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">WithBodyAsJson</span><span class="token punctuation">(</span>b <span class="token operator">=&gt;</span> b<span class="token punctuation">.</span>WorkerId <span class="token operator">==</span> resolvedWorkerId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>The test failed ❌ because there was no exchange logic provided.</p><p>So <span class="italic font-bold text-green-500">Chris, the Consuming Developer</span> started <a href="https://talesfrom.dev/blog/tdd-specify-satisfy-simplify">satisfying</a> it.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line">app<span class="token punctuation">.</span><span class="token function">MapPut</span><span class="token punctuation">(</span><span class="token string">&quot;/jobs/{jobId}/assign/{workerIdOrWorkerReference}&quot;</span><span class="token punctuation">,</span> <span class="token keyword">async</span> <span class="token punctuation">(</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">string</span></span> jobId<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">string</span></span> workerIdOrWorkerReference<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">ISaveAssignment</span> assignments<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">HttpClient</span> equipmentOrderingClient<span class="token punctuation">,</span>
</span><span class="code-line">    HttpClient workersClient <span class="token comment">// 👈 new!</span>
</span><span class="code-line"><span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> workerId <span class="token operator">=</span> workerIdOrWorkerReference<span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">// worker ids are GUIDs</span>
</span><span class="code-line">    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>Guid<span class="token punctuation">.</span><span class="token function">TryParse</span><span class="token punctuation">(</span>workerIdOrWorkerReference<span class="token punctuation">,</span> <span class="token keyword">out</span> _<span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> worker <span class="token operator">=</span> <span class="token keyword">await</span> workersClient
</span><span class="code-line">            <span class="token punctuation">.</span><span class="token generic-method"><span class="token function">GetFromJsonAsync</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>WorkerResponse<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;/workers/</span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">workerIdOrWorkerReference</span><span class="token punctuation">}</span></span><span class="token string">&quot;</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">        workerId <span class="token operator">=</span> worker<span class="token operator">!</span><span class="token punctuation">.</span>Id<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">await</span> assignments<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name constructor-invocation">Assignment</span><span class="token punctuation">(</span>jobId<span class="token punctuation">,</span> workerId<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">await</span> equipmentOrderingClient<span class="token punctuation">.</span><span class="token function">PostAsJsonAsync</span><span class="token punctuation">(</span><span class="token string">&quot;/equipment-orders&quot;</span><span class="token punctuation">,</span> <span class="token keyword">new</span> <span class="token comment">// 👈 new!</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        WorkerId <span class="token operator">=</span> workerId
</span><span class="code-line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">return</span> Results<span class="token punctuation">.</span><span class="token function">Ok</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre></div></div><p>And this made all tests pass ✅ again.</p><p><span class="italic font-bold text-green-500">Chris, the Consuming Developer</span> was pretty proud, as it didn&#x27;t take much time and was pretty easy to implement.</p><p>He didn&#x27;t even need to add too many new classes, and what is pretty important - he avoided mocking, and he heard that mocking leads to testing implementIt meant to be easyation details, which then leads to brittle tests.</p><p>For a while he thought of introducing mocks, at least for a small boundary between HTTP handler and HTTP clients, but then said to himself - &quot;let&#x27;s not complicate it&quot;.</p><p>Then, he started working on error scenarios.</p><h3 id="what-does-it-mean-easy"><a href="#what-does-it-mean-easy" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What does it mean &quot;easy&quot;?</h3><p>&quot;Isn&#x27;t a joke? TDD in the LLM world?&quot;, one might ask.</p><p>Bear with me, dear Reader.</p><p>We saw three roles collaborating to satisfy <strong>the needs</strong>.</p><p>The needs - of whom?</p><p>In the first part of the tale, we observed vivid discussion of three parties - each having their own understanding of &quot;easy&quot;.</p><p>The consumer wanted to have easy way of using the capability exposed through HTTP interface, by not needing to care about identifiers.</p><p>The architect wanted to have easy way of maintaining and evolving the system, by clear boundaries and responsibilities.</p><p>The provider wanted to have easy way of providing the capability, by delegating identifiers exchange to another service and just doing the HTTP interaction.</p><p>It is not difficult to see that in their eyes, the quality attribute &quot;easiness&quot; meant three different things, because the roles were physically separated.</p><p>But what about the second part of the tale?</p><p>Wasn&#x27;t it really different from the discussion between three people?</p><p>It might actually turn out to be a good example of <a href="https://talesfrom.dev/blog/the-invisible-role-switching-problem-and-need-driven-design">the invisible role-switching problem</a>.</p><p>A single person, Chris, unconsciously and dynamically swapped the perspective, multiple times.</p><p>One time he played the role of a consumer for &quot;his&quot; provided capability, next time he thought from the providers perspective.</p><p>When he started doubting whether more time needed to get feedback is worth it, provided that the system will grow in complexity - then we could say that Chris looked at &quot;things&quot; from a system&#x27;s designer perspective, taking into account quality attributes, like maintainability or testability.</p><p>As those role switching was done mostly in his head, it remained invisible to others.</p><p>Even to himself, especially when &quot;being in the process&quot;.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-quality-attributes-process-perspectives.svg" class="min-h-[32rem]"/></div><div class="italic">Each role having its own perspective</div></div><p>Roles (consumer, provider, designer) does not disappear, they are assigned or relocated differently.</p><p>A consumer looks from outside perspective.</p><p>A provider looks from inside perspective.</p><p>A designer looks from a system-level perspective - observing both outside and inside parts.</p><p>Sometimes to different people, sometimes to the same person at different moments.</p><p>Also, the tension between various needs remains similar, especially when one tries to take each and every perspective into account.</p><p>And we might arrive at the conclusion - &quot;there is no single <em>easy</em>&quot;.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-quality-attributes-process-easiness.svg" class="min-h-[32rem]"/></div><div class="italic">What does it mean &quot;easy&quot;?</div></div><h3 id="shocking-mocking"><a href="#shocking-mocking" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Shocking mocking?</h3><p>When dealing with implementation work, Chris used <a href="https://talesfrom.dev/blog/consumer-expected-need-driven-behavior-development">consumer-driven</a> approach for <a href="https://talesfrom.dev/blog/tdd-specify-satsify-simplify">driving</a> the implementation of capability that was expected to be provided by the service he owned.</p><p>He was able to specify the contracts (interfaces, along with required and provided information), from the HTTP interface consumer perspective.</p><p>Additionally to that, he went with &quot;the easiest implementation&quot; possible (at least in his mind) - designing against HTTP boundary and against real database.</p><p>I know, I know - it is a bit exaggerated to distinguish between a provider and a designer perspectives, mainly because while implementing, one is also designing, on some level.</p><p>But the designer might have more system-level approach for solving problems - was WireMock a right choice, from maintainability perspective?</p><p>What about test containers, and testing a typical state-changing process?</p><p>If you recall, Chris for a while switched to &quot;a designer&quot; perspective, asking about mocking.</p><p>How would mocking change the system&#x27;s behavior and maintainability?</p><p>Anti-mocking movement would tell you it&#x27;s straightforward - mocks break encapsulation.</p><p>Let&#x27;s stop for a while - what does &quot;mocking&quot; mean? Are we sure we have the same &quot;thing&quot; in our heads?</p><p>Ok, back to the main topic.</p><p>It might be arguable to even introduce &quot;designer&#x27;s perspective&quot;, but imagine a &quot;jira ticket jockey&quot; who just want to close the ticket, without caring about the system - even if they are implementing, are they really designing consciously?</p><p>And what about &quot;easy&quot; - what does it really mean in this context?</p><h3 id="effortless-now-effortful-later"><a href="#effortless-now-effortful-later" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Effortless now, effortful later?</h3><p>I hope you know dear Reader that I like definitions, because they contribute to building understanding and clarity, so here we go:</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">easy - a definition</div><div class="pb-2 px-3"><div class="break-words"><p>Requiring or exhibiting <strong>little effort</strong> or endeavor</p></div></div></div><p>In <a href="https://talesfrom.dev/blog/simple-aint-easy">Simple ain&#x27;t easy</a>, we tried to deepen our understanding when it comes those two terms.</p><p>Building something without adding more code might seem simple, but will it be after, let&#x27;s say, one year?</p><p>Or maybe it is just &quot;easy&quot;, meaning - requiring little effort? If it is, who&#x27;s stating that - a consumer? A provider? A designer?</p><p>The situational awareness might be really helpful when it comes to understanding the context and perspective from which &quot;easy&quot; is being evaluated.</p><p>As we saw in <a href="https://talesfrom.dev/blog/tdd-specify-satisfy-simplify">3S</a>, specifications through tests might be useful mental tool for &quot;putting on&quot; consumer&#x27;s glasses.</p><p>Which does not mean we magically will not get our hands (or heads?) dirty by looking inside, when it comes to designing internal quality.</p><p><a href="boundaries-modularity-and-a-diaper-effect">Boundaries</a> are not only valuable, but necessary to control complexity - technical, cognitive and organizational.</p><p>Establishing them doesn&#x27;t only happen at one level - boundaries are fractal in their nature, so pick a level and you will find them there too.</p><p>And without boundaries, we will lose (&quot;the game&quot;).</p><p>Sooner or later.</p><p>This leads us to the final conclusion - &quot;easy&quot; is relative, <a href="https://talesfrom.dev/blog/context-segregation-principle">context-dependent</a>.</p><p>In <a href="https://en.wikipedia.org/wiki/Domain-driven_design">DDD</a>, <a href="https://talesfrom.dev/blog/language-of-the-problem">the language</a> plays a crucial role when it comes to discovery and design - because in the hands (of head) of mindful practitioners, it enables noticing the subtle differences between meaning.</p><p>It&#x27;s all about semantics, one could say.</p><p>So even though &quot;easy&quot; means &quot;little effort&quot;, it varies when it comes to the subject of it.</p><p>&quot;Easy&quot; bounded by the consumer context means something different than &quot;easy&quot; bounded by the designer context.</p><p>It&#x27;s simple, but not easy to understand &quot;easy&quot;.</p><p>So next time, dear Reader, when someone (including yourself) drops &quot;I wanted it to be easy&quot;, be mindful and ask yourself:</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>Who is asking?</p>
<p>What does it mean &quot;easy&quot; in their perspective?</p></div></div></div>]]></content:encoded>
    <pubDate>Sat, 28 Mar 2026 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>domain-driven design</category><category>language patterns</category><category>design patterns</category><category>software architecture</category><category>mental models</category><category>communication</category><category>knowledge working</category><category>tools and capabilities</category><category>psychology</category><category>philosophy</category><category>visual thinking</category><category>perception</category><category>perspectives</category><category>test-driven development</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/keep-it-visible-smartass</guid>
    <title>Keep it visible, smartass</title>
    <link>https://talesfrom.dev/blog/keep-it-visible-smartass</link>
    <description>Why communication always fails, except by accident?</description>
    <content:encoded><![CDATA[<div class="bg-slate-600 rounded-xl "><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Attention!</span></div><div class="pb-2 px-3"><div class="break-words"><p>Big kudos for Xander, a fellow CRUD scientist, for sharing &quot;smartass&quot; term with me, while discussing this topic. I wanted to use &quot;stupid&quot; initially, but &quot;smartass&quot; sounds more polite.</p>
<p>Thanks Xander🙏</p></div></div></div><h3 id="cant-you-add-it-later"><a href="#cant-you-add-it-later" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Can&#x27;t you add it later?&quot;</h3><p>Imagine that there&#x27;s a discussion between two architects and a sponsor regarding technical debt that enormously slows down the delivery of new features.</p><p>The team is already behind the schedule, everyone is getting nervous, including management, as dates and potential benefits were communicated through PowerPoint presentation months ago.</p><p>Architects have an idea to gradually migrate two architectural elements into modern .NET, but most importantly to re-establish internal boundaries in each of them.</p><p>Re-align application architecture.</p><p>In their evaluation, this will enable faster incrementing of features across the entire system.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div><span class="italic font-bold text-green-500">Arthur, the Architect</span>: Hey Sam! Both me and Alex wanted to chat with you about the challenges we have in our architecture.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-blue-500">Alex, the Architect</span>: And address further steps of modernizing some part of it.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-red-500">Sam, the Sponsor</span>: Hey guys! Sure, I have 30 minutes for you, I am going to have a chat with the board and I don&#x27;t really want to keep them waiting.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-blue-500">Alex, the Architect</span>: Of course, fully understandable.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-green-500">Arthur, the Architect</span>: Ok, so let&#x27;s keep it tight. Two of our services are far from the industry standards - they are clunky, entangled and spaghetti-like - every time we need to touch them, we can&#x27;t deliver in a single sprint.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-red-500">Sam, the Sponsor</span>: So can&#x27;t you just not touch them at all?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-blue-500">Alex, the Architect</span>: It&#x27;s not that simple, unfortunately. They are related to BHG workflow.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-green-500">Arthur, the Architect</span>: So every time we touch BHG, we need to do changes in one or two of them.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-red-500">Sam, the Sponsor</span>: Is there anything I can help with? You seem to be in control, aren&#x27;t you?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-blue-500">Alex, the Architect</span>: We identified the need to stop delivery and focus on quality, at least for a while.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-red-500">Sam, the Sponsor</span>: What do you mean by saying &quot;stop delivery&quot;?! Do you know how do I look like every time I need to say that it&#x27;s being delayed?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-green-500">Arthur, the Architect</span>: No, no, Arthur just meant that we need to prioritize quality over speed for a short period, for those two services. That&#x27;s it.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-red-500">Sam, the Sponsor</span>: To be fair, can&#x27;t you just add quality later? We really need to deliver it, this time. Keep up the good work and things will resolve themselves, believe me.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-green-500">Arthur, the Architect</span>: ...</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-red-500">Sam, the Sponsor</span>: Ok, need to go. See you later guys!</div></span></div><p>Two architects were left in the virtual meeting room, discussing how hard it is for other people to understand typical problems of a technologists.</p><h3 id="arent-you-interested-in-the-code"><a href="#arent-you-interested-in-the-code" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Aren&#x27;t you interested in the code?&quot;</h3><p>The same organization, but different discussion - this time three developers collaborate on how to deliver a functionality, given the current structure of the module they both work on.</p><p>The change itself isn&#x27;t a big one, but it requires touching many submodules, each having a different responsibility.</p><p>Also, one of them is a newcomer, not knowing the system.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div><span class="italic font-bold text-purple-500">Dwight, the Developer</span>: Ok, so here we have the service fetching data from KLP data provider. I think we just need to tweak a bit the interface and then...</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-yellow-500">Debohard, the Developer</span>: Wait, wait. Are you sure that&#x27;s the best approach? Maybe we should take a step back and think what&#x27;s the real problem and what structures do we have in place to satisfy the needs?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-purple-500">Dwight, the Developer</span>: The task is simple - adjust KLP fetching, transform it to MTR schema, send notifications to publishers and reconcile pending publications. (<em>Shows all mentioned classes and interfaces</em>) </div></span><span class="text-white"><div><span class="italic font-bold text-yellow-500">Deborah, the Developer</span>: Yeah, I know the code, but was more curious about the overall design...</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-purple-500">Dwight, the Developer</span>: Aren&#x27;t you interested in the code? This is the only thing that matters, at the end of the day.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-emerald-500">David, the Developer</span>: What is KLP?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-purple-500">Dwight, the Developer</span>: This is a simple data provider we use in our system. We are mostly interested in the interface - <code>IKLPService</code>, which is implemented by <code>KLPService</code></div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-emerald-500">David, the Developer</span>: Why does it have eleven methods?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-purple-500">Dwight, the Developer</span>: Ok, the story goes like that. One time...</div></span></div><p>They continued the discussion for next hour, in which <span class="italic font-bold text-emerald-500">David, the Developer</span> asked many more questions, trying to wrap his head around the codebase.</p><p>Because all is about the code, right?</p><h3 id="it-will-take-time-to-put-everything-in-text"><a href="#it-will-take-time-to-put-everything-in-text" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;It will take time to put everything in text!&quot;</h3><p>Yet again the same company but different people setup - a product owner and two software engineers discussing potential new feature.</p><p>Product owner speaks about his requirements and customer needs.</p><p>Software engineers try to ask clarifying questions and explore potential invisible problems.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div><span class="italic font-bold text-indigo-500">Dave, the Developer</span>: So what do you need, Peter?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-lime-500">Peter, the Product Owner</span>: I want to display information related to failed transactions.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-orange-500">Dayanna, the Developer</span>: Why is it important?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-lime-500">Peter, the Product Owner</span>: There are various reasons why users struggle with filling up forms, we want to provide them with clear feedback and guidance.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-orange-500">Dayanna, the Developer</span>: What are those reasons?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-lime-500">Peter, the Product Owner</span>: Please don&#x27;t overcomplicate it, it&#x27;s just about displaying a nice label and a clear text saying the cause of the problem.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-indigo-500">Dave, the Developer</span>: We are asking those questions in order to understand your needs and not need to rework it later.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-orange-500">Dayanna, the Developer</span>: Would you mind if I start writing down our conversation?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-lime-500">Peter, the Product Owner</span>: What for?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-orange-500">Dayanna, the Developer</span>: It will help us remember the details and ensure we don&#x27;t miss anything important.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-lime-500">Peter, the Product Owner</span>: Remember? It will take time to put everything in text and we don&#x27;t have time for this. We need to deliver.</div></span></div><p>They didn&#x27;t note anything down.</p><p>When the next meeting happened, no one really remembered, nor understood, what they had agreed on.</p><p>The great confusion appeared as <span class="italic font-bold text-lime-500">Peter, the Product Owner</span> changed the words he used for concepts related to this feature.</p><p>It took time to restore understanding.</p><h3 id="understanding"><a href="#understanding" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Understanding?</h3><p>&quot;People struggle communicating with each other, what&#x27;s a big deal?&quot; - one might easily ask.</p><p>Turns out that software development is a social activity - as Kent Beck taught us with his wise words.</p><p>Social activity meaning a lot of communication, ideas transferring and building shared understanding.</p><p>Building trust and relationships because without them, collaboration and effective problem-solving become challenging.</p><p>Or even impossible.</p><p>What do those two tales have in common?</p><p>I hope you read the title, dear Reader, because they both strive to communicate missing something vastly relevant - visual communication.</p><p>How often did you participate in a meeting and no one was sharing anything?</p><p>Just a bunch of pixel avatars (because everyone is too shy to turn on their cameras) talking to each other, making bold statements and pretending to be very smart in another person&#x27;s eyes.</p><p>UFC-like match between egos, trying to play the dominance game, not asking &quot;What do you mean by that?&quot; so that they keep perpetuating the illusion that everyone is on the same page.</p><p>And then, customers suffer, as they didn&#x27;t get what they truly needed.</p><p>Recipients and consumers fail to get value delivered, because of poor, internal communication.</p><p>Things get delayed as someone &quot;just misunderstood the intentions&quot;.</p><p>Misunderstood... Or maybe they were communicated poorly?</p><h3 id="communication-always-fails-except-by-accident"><a href="#communication-always-fails-except-by-accident" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Communication always fails, except by accident&quot;</h3><p>I&#x27;ve heard this phrase from <a href="https://woodyzuill.com/">Woody Zuill</a>, which turned out to be one of <a href="https://en.wikipedia.org/wiki/Wiio&#x27;s_laws">Wiio&#x27;s laws</a>.</p><p>It brings harsh reality of being a human - we are inherently prone to miscommunication.</p><p>Recipient of the message may interpret it differently than intended.</p><p>The message itself might be convoluted enough to make it difficult to decode (which is a nice metaphor itself - like trying to read a book in a foreign language without a dictionary).</p><p>Interlocutors exchanging varying models of the reality, different perspectives, which easily lead to assumption-based communication.</p><p>When we converse with others, we not only publish and receive information, but also implicitly exchange mental models (models of thinking and processing information), which might be one big and invisible obstacle in communication.</p><p>Architects thinking in bigger pictures, developers thinking in details (btw. nice stereotype, isn&#x27;t it dear Reader?).</p><p>Sponsors thinking in money and market shares.</p><p>And so on.</p><p>How on earth those roles can effectively collaborate?</p><p>Even though language is hugely important in our lives, it is inherently limited and prone to misinterpretation.</p><p>Language means words, and when we &quot;peek inside a box&quot;, of &quot;a word&quot;, by checking one of many definitions:</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">a word - definition</div><div class="pb-2 px-3"><div class="break-words"><p><strong>A sound or a combination of sounds</strong>, or its representation in writing or printing, that symbolizes and communicates a meaning and may consist of a single morpheme or of a combination of morphemes.</p></div></div></div><p>We quickly might realize that words are sounds which have finite energy associated with them, which means that energy can quickly dissipate.</p><p>When spoken, words are impermanent, they are invisible and volatile.</p><p>Sounds translated to symbols, and their meaning can vary depending on the context and the interpreting party.</p><p>Or misinterpreting, if you wish, dear Reader.</p><h3 id="keep-it-visible-smartass"><a href="#keep-it-visible-smartass" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Keep it visible, smartass</h3><p>Let&#x27;s get back to the definition we conjured a while ago, but now focusing on another part of it:</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">a word - definition</div><div class="pb-2 px-3"><div class="break-words"><p>A sound or a combination of sounds, or <strong>its representation in writing or printing</strong>, that symbolizes and communicates a meaning and may consist of a single morpheme or of a combination of morphemes.</p></div></div></div><p>Just by making things visible, we can reduce the chances of miscommunication and ensure that everyone is on the same page.</p><p>Representing impermanent sound as a symbol is the way to go to fight against assumptions, lack of clarity and misinterpretation.</p><p>Paraphrasing <a href="https://medium.com/@ziobrando">Alberto Brandolini</a>&#x27;s words: &quot;don&#x27;t talk about invisible things&quot; (I believe he was the author of those words).</p><p>&quot;Woah, thank you captain obvious&quot; - someone can say in their head.</p><p>It might sound trivial, but it&#x27;s a crucial point.</p><p>Because it&#x27;s obvious, it&#x27;s easily overlooked.</p><p>Especially when it is not trained enough.</p><p>And yes, this is a skill.</p><p>It needs to be practiced consciously when we are collaborating with others.</p><p>And no, one does not need to be an architect to draw things on the board or be a scrum master to note things down.</p><p>One needs to be a human being.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Don&#x27;t talk about invisible things</p></div></div></div><p>The quality of visuals - well, that&#x27;s a different story.</p><h3 id="what-does-x-mean"><a href="#what-does-x-mean" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What does &quot;X&quot; mean?</h3><p>Let&#x27;s say you are discussing integration between two services and there&#x27;s a strange wording that is even difficult to pronounce.</p><p>It is not the first time you chat about it but somehow no diagram is readily available.</p><p>One could say - a perfect setup, free from sources of confusion.</p><p>There might be an implicit assumption that there will be no assumptions, because the topic is pretty well-known.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Communication always fails, except by accident</p></div></div></div><p>Write down this word.</p><p>Draw two boxes and a line.</p><p>Assign meaning to each by writing it down.</p><p>Will it make the conversation longer?</p><p>Well, maybe the first time.</p><p>&quot;Head is the worst place to keep problems and ideas&quot;, as my friend Przemek Wolnik taught me once.</p><p>Make things visible, explicit and represented.</p><p>Whenever a new concept arises in verbal conversation, put it into a visual form.</p><p>We often struggle if we can&#x27;t mention things by their name, as <a href="https://talesfrom.dev/blog/the-ambiguity-of-naming">naming is framing</a>.</p><p>It is actually useful and crucial process so that we can exchange information (and mental models) and collaborate.</p><p>Going back to integration between two services - imagine what happens if parties discussing the problem have never experienced this topic before.</p><p>They don&#x27;t have the shared context or mental models to understand each other fully.</p><p>And someone frames the meeting by saying &quot;we only have 30 minutes&quot;.</p><p>&quot;We need to be efficient&quot; - one might say aloud.</p><p>Everything will be successful, right dear Reader?</p><h3 id="miscommunication-visualized"><a href="#miscommunication-visualized" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Miscommunication visualized</h3><p>As Dijkstra said:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Program testing can be used to show the presence of bugs, but never to show their absence!</p></div></div></div><p>Drawing, writing - not in the secrecy - but in the public space, while chatting with others, is not to prove how smart one is.</p><p>It is to reveal the assumptions, gaps, and misunderstandings that might otherwise remain hidden.</p><p>We could use wise words from Dijkstra and create something similar but for visual collaboration:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Making things visible can be used to show the presence of assumptions, but (almost) never to show their absence</p></div></div></div><p>Of course, the trust and positive intentions are preliminary condition to move forward.</p><p>Whenever a conversation starts and no one shares anything in a couple of minutes - grab a screen or walk to a whiteboard and start sketching whatever you hear.</p><p>Yes, there is a high chance it will be a complete failure.</p><p>This time.</p><p>But do you, dear Reader, know what the <strong>FAIL</strong> acronym means?</p><div><strong>F</strong>irst</div> <div><strong>A</strong>ttempt</div> <div><strong>I</strong>n</div> <div><strong>L</strong>earning</div><p>It&#x27;s good to be wrong for a short period of time.</p><p>It&#x27;s not that good to be wrong for a loooooooong period of time.</p><p>Better to <strong>FAIL</strong> fast, gather feedback and reconfigure (avoiding being <a href="https://talesfrom.dev/blog/fragile">(fr)Agile</a>).</p><p>Ability to say &quot;<a href="https://talesfrom.dev/blog/i-dont-know">I don&#x27;t know</a>&quot; separates mature beings from the rest.</p><p>And yes, it might mean all will need to <a href="https://talesfrom.dev/blog/slow-down">slow down</a>, at least while starting.</p><p>But this is &quot;production capabilities&quot; investment.</p><p>Putting effort into advancing people&#x27;s capabilities in understanding a problem/a solution/a design/a whatever so that value production will come with less effort later.</p><p>It is a bet made for the future that there will be decreased rework, reducing waste.</p><p>Building shared understanding, considering that people are capable of following, is a key for software development.</p><p>Getting back to the drawing board - the next iteration might be more precise to what the mental models of the interlocutors are.</p><p>After couple of minutes there will be a shared platform for exchanging thoughts.</p><p>Even though people might internally think and talk to themselves that &quot;it&#x27;s a complete waste&quot;, they will suddenly start referring to the drawing or the text.</p><p>They will point at it and say &quot;in this thing called X, I think...&quot;.</p><p>A small, invisible win, which happened because of keeping things visual and not talking about invisible things.</p><h3 id="from-assumption-based-to-visual-based-communication"><a href="#from-assumption-based-to-visual-based-communication" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>From assumption-based to visual-based communication</h3><p>Visuals do not need to be advanced, perfect or detailed.</p><p>At least not when starting the session.</p><p>I really like, after hearing invisible words from my interlocutor, to say: &quot;let me rephrase it using my words to see if I understood you correctly&quot;.</p><p>I try to keep core concepts (here: words, terms), but use my own sentences, to ensure mutual understanding.</p><p>Instead of rephrasing, one could easily say: &quot;let me draw what you just said to see if I follow your thinking correctly&quot;.</p><p>Putting some boxes, lines and words in visual form creates a platform on which we can exchange mental models, information and doubts.</p><p>Suddenly, everyone can point with a finger, ask for clarification and contribute to the shared understanding.</p><p>Of course, there are various methods for collaborative modeling: Event Storming, Event Modeling, Domain Storytelling and more.</p><p>But the most important thing is to... do it.</p><p>Tiny steps, tiny wins.</p><p>For sure it will be great to organize a fully fledged session in which people can interact and collaborate, but starting small and iterating is key.</p><p>We are typically &quot;two boxes and an arrow&quot; away from changing the habits of our organization or our team.</p><p>No more meetings with invisible content - open <a href="https://excalidraw.com/">excalidraw</a> and start sketching.</p><p>Invite others.</p><p>If they feel insecure, be their guide - let them explain their thinking and you put it down.</p><p>Next time, dear Reader, when you collaborate with someone and nothing is visible, draw or write things down and say:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Let me rephrase it using my words and draw it to see if I follow your thinking correctly.</p></div></div></div><p>Magic happens when ideas and problems become visible.</p>]]></content:encoded>
    <pubDate>Sat, 14 Mar 2026 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>domain-driven design</category><category>language patterns</category><category>design patterns</category><category>software architecture</category><category>mental models</category><category>communication</category><category>knowledge working</category><category>tools and capabilities</category><category>psychology</category><category>philosophy</category><category>visual thinking</category><category>perception</category><category>perspectives</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/the-ambiguity-of-arrows</guid>
    <title>The ambiguity of arrows</title>
    <link>https://talesfrom.dev/blog/the-ambiguity-of-arrows</link>
    <description>To transform or to interact?</description>
    <content:encoded><![CDATA[<h3 id="1-what-do-you-mean-by-that"><a href="#1-what-do-you-mean-by-that" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>#1 What do you mean by that?</h3><p>Imagine that there are two software professionals - <span class="text-red-500 italic">Daniel, Developer</span> and <span class="text-blue-500 italic">Dylan, Developer</span> - discussing an engineering problem.</p><p>Fortunately, they are quite self-aware beings, knowing their cognitive limitations, so <span class="text-red-500 italic">Daniel, Developer</span> draws the following diagram on the virtual board:</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-arrows-arrow.png" class="max-h-[24rem]"/></div><div class="italic mx-24">A diagram.</div></div><p>And then it all started.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div><span class="italic font-bold text-blue-500">Dylan, Developer</span>: Ok, so then information flows from <code>A</code> to <code>B</code>.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-red-500">Daniel, Developer</span>: You mean <code>A</code> becomes <code>B</code>, right?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-blue-500">Dylan, Developer</span>: No, no, <code>A</code> calls <code>B</code> to perform an action.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-red-500">Daniel, Developer</span>: Sorry, but I don&#x27;t get it. It&#x27;s quite clearly visible - we are transforming value of type <code>A</code> to type <code>B</code>.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-blue-500">Dylan, Developer</span>: Transformation?</div></span></div><p>It was a polite conversation and fortunately it turned out that one was talking about more object-oriented design while another focused more on functional aspects of the solution.</p><p>They noticed a team mate walking by, <span class="italic font-bold text-green-500">Dwight, Developer</span>, and they asked him what he thought.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div><span class="italic font-bold text-green-500">Dwight, Developer</span>: Hey, what are you guys discussing?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-blue-500">Dylan, Developer</span>: We are trying to figure out if <code>A</code> transforms into <code>B</code> or if <code>A</code> calls <code>B</code> to perform an action.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-red-500">Daniel, Developer</span>: It&#x27;s quite clearly visible - we are transforming value of type <code>A</code> to type <code>B</code>.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-green-500">Dylan, Developer</span>: Well, I think it&#x27;s more about the interaction between <code>A</code> and <code>B</code> rather than a simple transformation.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-blue-500">Dwight, Developer</span>: Who transforms?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-green-500">Daniel, Developer</span>: An arrow, which represents a function.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-blue-500">Dwight, Developer</span>: Who interacts?</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-green-500">Dylan, Developer</span>: <code>A</code> interacts with <code>B</code>.</div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic font-bold text-blue-500">Dwight, Developer</span>: Neither a function transforms, nor an object interacts with another one.</div></span></div><p>And complete silence followed.</p><p>Both <span class="text-blue-500 italic">Dylan, Developer</span> and <span class="text-red-500 italic">Daniel, Developer</span> stared at Dwight, trying to comprehend his statement.</p><p>They tried to interpret the summary given by their team mate.</p><p>Eventually, <span class="italic font-bold text-green-500">Dwight, Developer</span> spoke again, telling them what he meant.</p><p>&quot;It&#x27;s the mind that either transforms or interacts.&quot; - he said. - &quot;Or rather it sees transformation or sees interaction.&quot;</p><p>And they both became enlightened.</p><h3 id="2-what-do-you-mean-by-that"><a href="#2-what-do-you-mean-by-that" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>#2 What do you mean by that?</h3><p>Another time, in the same company, two architects had a heated discussion about a piece of the system.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-arrows-more-arrows.png" class="max-h-[24rem]"/></div><div class="italic mx-24">Another diagram.</div></div><p>They both were looking at the diagram, trying to make sense of it.</p><p>Neither of them was the original author of it, so they needed to derive the understanding, together.</p><p>It turned out pretty quickly, that they couldn&#x27;t agree whether it is the information flow or HTTP requests between services.</p><p>&quot;Services?&quot;, commented one of them.</p><p>After they agreed that those architectural elements can be named &quot;services&quot;, they continued their discussion.</p><p>&quot;Ok, so information flows from service <code>A</code> to service <code>B</code> and service <code>C</code>, and then&quot;, highlighted another one, but got interrupted.</p><p>Heated debate went on and on until a manager came and summarized by saying &quot;this org chart looks a bit weird, because hierarchical diagrams are drawn from top to bottom.&quot;</p><p>They remained silent and waited for him to disappear in the rest part of the office.</p><h3 id="arrows"><a href="#arrows" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Arrows?</h3><p>&quot;These were imaginary conversations!&quot;, some might complain.</p><p>Yup, it&#x27;s all made up, right?</p><p>Literally every human conversation about diagrams reveals that we all interpret the information in the same way, ain&#x27;t it dear Reader?</p><p>What&#x27;s your preference, dear Reader, when you draw a diagram?</p><p>Do you start with information flow?</p><p>Maybe you rather draw an Entity-Relationship Diagram (ERD) to highlight information relationships (I know those are not arrows, but stay with me, dear Reader)?</p><p>Or maybe you focus on who initiates actions?</p><p>Drawing is of course important, as it&#x27;s a form of communication, but it&#x27;s a consequence of...Thinking.</p><p>And thinking involves using mental models, which effectively analyze, interpret and filter incoming information, leading to various actions.</p><p>So whatever is visible, might be a reflection of our mental models.</p><p>And possibly what&#x27;s even more important - whatever is invisible, might be shaping our mental models, as we saw in tiny tales.</p><p>What is an arrow?</p><p>Ask a developer and you get one answer.</p><p>Ask another one and you&#x27;ll get a different answer.</p><p>Who&#x27;s right?</p><p>We saw that it&#x27;s not about who&#x27;s right or wrong, but about seeing through the models, understanding the perspectives, and recognizing the underlying assumptions.</p><p>This can be done by training ourselves in self-awareness, in noticing that we might use a different model than our conversation partner.</p><p>Arrows might mean different things to different people.</p><p>And this meaning is <em>given</em> by the observer.</p><h3 id="processing-relationships"><a href="#processing-relationships" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Processing relationships?</h3><p>There are multitude of ways how one can interpret arrows in diagrams.</p><p>But I truly believe two of such interpretations are a little bit more important than the others, as they are fundamental and complementary to each other.</p><p>They can appear on &quot;higher levels&quot; (ekhm, &quot;architecture levels&quot;) or on more tactical ones.</p><p>Both of them are specific examples on how two or more elements <em>relate</em> to each other.</p><p>Relationships.</p><p>Why did I say they are &quot;a bit more important than the others&quot;?</p><p>They primarly focus on doing something, so they are related to acting.</p><p>As we explored in <a href="https://talesfrom.dev/blog/modeling-maturity-levels">Modeling Maturity Levels</a>, when modeling on the right levels, one is able to capture subtle <a href="https://talesfrom.dev/blog/context-segration-principle">contextual</a> nuances, just because the focus was placed on actions.</p><p><a href="https://talesfrom.dev/blog/i-interface">Verbs</a>.</p><p>Arrows can represent processing relationships: transformations and interactions.</p><p>In the first tale, one of the developers tried to emphasize the transformation aspect, while the other focused on the interaction aspect.</p><p><code>A -&gt; B</code> notation should be recognizable by functional folks, who often deal with function signatures that have such <em>expressions</em> built-in in their functional languages of choice.</p><p>I would guess that such notation isn&#x27;t well known to object-oriented people (unfortunately), who might think of objects as a data-bags (you might be interested in reading <a href="https://talesfrom.dev/blog/the-ambiguity-of-objects">The ambiguity of objects</a>).</p><p>Are functional programmers only transform things into other things?</p><p>What about calling an external service to get the information to be later transformed?</p><p>Oopsie, an interaction.</p><p>What do I mean by &quot;an interaction&quot;?</p><p>Communicating, exchanging information, collaborating, sending messages or signals - everything between two parties, across boundaries.</p><p>Transformations and interactions are dual aspects of processing relationships.</p><p>One does not exist without the other.</p><p>It&#x27;s the observers who assign meaning to these relationships.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Transformations and message passing are two sides of the same coin.</p></div></div></div><p>Such duo appear literally everywhere: from small objects transforming data, after responding to a method invocation, to business workflows that represent &quot;the flow of work&quot;, exercised by the interacting parties.</p><p>Processing relationships express <em>the structure of actions</em>, which allow for the observer to focus on movement, rather than static elements - which as we saw in <a href="https://talesfrom.dev/blog/boundaries-modularity-and-a-diaper-effect">Boundaries, modularity and a diaper effect</a>, is quite important aspect when looking at things.</p><p>Another name for such structure is a protocol.</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">a protocol</div><div class="pb-2 px-3"><div class="break-words"><p>A system of rules that explain the correct conduct and procedures to be followed in formal situations.</p></div></div></div><p>Well, it&#x27;s more close to an etiquette, but still it captures the essence of this abstraction - &quot;correct conduct and procedures&quot;.</p><p>Such &quot;the structure of actions&quot; is nothing more than a process, which involves steps that need to be executed in a specific order to achieve a desired outcome, which requires transforming information into some other type of information...</p><p>...And each transformational step requires a transforming party to provide capabilities for doing so...</p><p>...Without directly caring <em>how</em> the work is done (from the process perspective), but focusing on <a href="https://talesfrom.dev/blog/composing-a-pie"><em>what</em> needs to be achieved</a>.</p><p>...Ok, now we&#x27;re doing circles, but I hope you got the point, dear Reader?</p><h3 id="transforming-or-interacting"><a href="#transforming-or-interacting" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Transforming or interacting?</h3><p>When you deal with object-oriented code, do you think about objects interacting with each other, &quot;not caring about transformations&quot;? Why?</p><p>When looking at the diagram - do you focus on information flow and how the data is getting transformed? Why?</p><p>Interactions are quite different from transformations, as they involve communication between elements rather, without breaching certain established boundaries.</p><p>Transformations, on the other hand, might not pay attention at boundaries (and information hiding), as they mostly focus on immutable state evolution.</p><p>But at some stage, an <code>Order</code> might become an <code>Offer</code>, which eventually might become an <code>Invoice</code>, but each capability transforming one into another will be provided by a party, playing a certain role in the workflow.</p><p>What is really interesting is that typically providers are interested in details what are the steps (a workflow), whereas consumers are more focused on the <a href="https://talesfrom.dev/blog/cocoa-from-ports-and-adapters-to-concepts-capabilities-providers">provided capabilities and outcomes they can get</a>.</p><p>Which expresses an interesting dynamic: providers might care more about transformations, consumers might care more about interactions (of course it&#x27;s a huge simplification, as both processing relationships are dual and complementary).</p><p>Another fun fact, visible in mentioned tiny tales: trying to present <strong>both</strong> processing relationships at the same time might make participants confused, worried or overwhelmed.</p><p>That&#x27;s why I find particular ways of collaborative modeling (like Event Storming, BPMN, Event Modeling) powerful as they aim at capturing both perspectives: transforming and interacting.</p><p>So next time dear Reader, when you&#x27;ll be reviewing a diagram or drawing one, or maybe you&#x27;ll be <a href="https://talesfrom.dev/blog/the-ambiguity-of-application">applying business logic</a> in the code (with or without LLMs), ask yourself a question:</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>What processing relationship do I want to emphasize at this stage?</p></div></div></div><p>Bonus: here&#x27;s the original Zen Koan I got inspiration from:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Two monks were watching a flag flapping in the wind. One said to the other, “The flag is moving.”</p>
<p>The other replied, “The wind is moving.”</p>
<p>A Zen master overheard this. He said, “Not the flag, not the wind; mind is moving.”</p></div></div></div><p>What have changed since then?</p>]]></content:encoded>
    <pubDate>Fri, 27 Feb 2026 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>domain-driven design</category><category>language patterns</category><category>design patterns</category><category>software architecture</category><category>mental models</category><category>communication</category><category>knowledge working</category><category>tools and capabilities</category><category>psychology</category><category>philosophy</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/llms-3d-printers-amplifiers</guid>
    <title>LLMs, 3D printers and amplifiers</title>
    <link>https://talesfrom.dev/blog/llms-3d-printers-amplifiers</link>
    <description>What LLMs, 3D printers and amplifiers have in common?</description>
    <content:encoded><![CDATA[<h3 id="time-to-add-a-feature"><a href="#time-to-add-a-feature" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Time to add a feature&quot;</h3><p>Imagine that a senior software engineer named <span class="text-red-500 font-bold">Dave</span> is working on an application that enables his team to manage configurations for various services.</p><p>He made an analysis &quot;buy vs build&quot; and it turns out that building a custom solution is the best option for his company, as 20% of capabilities are quite unusual, whereas 80% are standard features that can be found in off-the-shelf products.</p><p><span class="text-red-500 font-bold">Dave</span> just wants to satisfy the needs of his team and deliver value as soon as possible.</p><p>The goal is not to build a generic, reusable product, that can be used across the entire company, but to deliver a solution that works for his team, so far.</p><p>He has a decade of experience where he built various systems, he worked with various technologies and paradigms.</p><p>He knows about the designing, various patterns and different practices.</p><p>He <a href="https://talesfrom.dev/blog/tdd-specify-satisfy-simplify#specify">specifies</a> the first feature, then asks an agent to <a href="https://talesfrom.dev/blog/tdd-specify-satisfy-simplify#satisfy">satisfy</a> the requirement using the first test.</p><p>An agent runs the tests, sees that they are failing, and produces the easiest possible code to make the tests pass, as <span class="text-red-500 font-bold">Dave</span> instructed it to do so.</p><p>The test becomes green.</p><p><span class="text-red-500 font-bold">Dave</span> stops and looks at the code that the agent produced.</p><p>&quot;Should I <a href="https://talesfrom.dev/blog/tdd-specify-satisfy-simplify#simplify">simplify</a> it now or proceed with specifications?&quot;, he wonders.</p><p>He decides to proceed with the next specification, and simplify later.</p><p>He increments the feature by using services of the agent, following the <a href="https://talesfrom.dev/blog/tdd-specify-satisfy-simplify">3S workflow</a>.</p><p>When all tests are green, he decides to review the code and <a href="https://talesfrom.dev/blog/tdd-specify-satisfy-simplify#simplify">simplify</a> it.</p><p>The agent didn&#x27;t get abstractions right, so <span class="text-red-500 font-bold">Dave</span> <a href="https://talesfrom.dev/blog/tdd-specify-satisfy-simplify#specify">specifies</a> an internal quality requirement to improve the design by restructuring the code, by introducing proper abstract ideas like <code>ConfigurationHistory</code>, etc.</p><p>The agent does refactorings, and the code looks much better now.</p><p><span class="text-red-500 font-bold">Dave</span> tells to verify if specs are satisfied, the agent does that and all are green.</p><p>He also sees that in some places a factory design pattern might be beneficial, so he <a href="https://talesfrom.dev/blog/tdd-specify-satisfy-simplify#specify">specifies</a> that as well.</p><p>He tells the agent to satisfy the new specification, and the agent introduces the factory pattern in the code.</p><p><span class="text-red-500 font-bold">Dave</span> asks the agent to run verification again, and all tests are green.</p><p>He is happy with the result.</p><p>Just to ensure the quality of the specifications as tests, <span class="text-red-500 font-bold">Dave</span> decides to run mutation testing cycle to see if the tests are strong enough.</p><p>The mutation testing shows that two tests are pretty weak against mutants, so he <a href="https://talesfrom.dev/blog/tdd-specify-satisfy-simplify#specify">specifies</a> new internal quality requirement to improve the tests.</p><p>The agent satisfies the new specification by improving the tests, and now the mutation testing shows that all tests are strong enough.</p><p><span class="text-red-500 font-bold">Dave</span> is happy.</p><p>He went to another feature, following the same <a href="https://talesfrom.dev/blog/tdd-specify-satisfy-simplify">3S workflow</a>, by using the services of the agent.</p><p>All took less than a couple of hours to have a walking skeleton so that his team can start using the application and provide feedback.</p><h3 id="we-need-to-analyze-the-log-files"><a href="#we-need-to-analyze-the-log-files" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;We need to analyze the log files&quot;</h3><p>Imagine that a senior software engineer named <span class="text-green-600 font-bold">Dayanna</span> got asked to help support team to analyze log files from various services to identify issues and patterns.</p><p>She opened the 10GB log file, and started to analyze it using her favorite text editor.</p><p>She quickly realized that it is going to take ages to analyze the file manually.</p><p>She remembered that she recently read about &quot;AI&quot; that can help to analyze text files, so she decided to give it a try.</p><p>She wrote a prompt that instructs the &quot;AI&quot; to analyze the log file, identify patterns, and summarize the findings.</p><p>It produced a summary, but it was not very accurate.</p><p>Actually, it missed very important patterns happening in the domain of the application.</p><p><span class="text-green-600 font-bold">Dayanna</span> realized that she needs to provide more context to the &quot;AI&quot;, so she decided to feed it with domain knowledge.</p><p>It got a little better, but still not accurate enough.</p><p>She decided to build a small tool that can preprocess the log file, extract relevant information, and provide it to the &quot;AI&quot; in a more structured way.</p><p>She knew how to work with .NET and C#, so she quickly built a console application that reads the log file, extracts relevant information, and formats it in a way that the &quot;AI&quot; can understand better.</p><p>Still it was pretty textual for her to get a glimpse of the patterns so she decided to visualize the data.</p><p><span class="text-green-600 font-bold">Dayanna</span> has heard about <a href="https://htmx.org/">HTMX</a> and decided to use it to build a simple web application that can visualize the log data.</p><p>She specified the requirements for the web application, and used the &quot;AI&quot; to generate the code for hypermedia-driven UI using HTMX.</p><p>She integrated the preprocessing tool with the web application, so that she can upload the log file, preprocess it, and visualize the data in a more interactive way.</p><p>She was able to identify patterns and issues in the log file much more easily now.</p><p><span class="text-green-600 font-bold">Dayanna</span> decided that she could deploy this tool to help the support team analyze log files more efficiently in the future.</p><p>She knew that the application was produced in a prototype spirit, so she definitely knew that internal quality might not be best possible, but it was good enough for the purpose.</p><p>If she gets a positive feedback from the support team, she might consider improving the design and architecture of the application as the next step.</p><p>Also, she decided that it might be useful to employ a simple machine learning model to help with the log analysis by suggesting important features/patterns in the given logs.</p><p>So <span class="text-green-600 font-bold">Dayanna</span> specified that problem to the &quot;AI&quot;, got four recommendations, and decided to implement a simple solution using one of the suggested models - pytorch one.</p><p>She didn&#x27;t get the analysis done, but she easily produced a tool that can help with enhancing the log analysis capability of the team.</p><h3 id="we-are-so-cooked-or-we-are-cooking"><a href="#we-are-so-cooked-or-we-are-cooking" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>We are so cooked or we are cooking?</h3><p>Metaphors.</p><p>Who does not love a good metaphor?</p><p>We need metaphors to understand, to communicate with other beings so that we are capable of helping each other, work toward a common goal (and more, of course).</p><p>A metaphor is like a bridge that connects two different ends, enabling to convey the caravans full of ideas from one side to another.</p><p>That was a metaphor about metaphors.</p><p>As you probably know, dear Reader, I love metaphors.</p><p>Some might say they are dangerous, as they can lead to misunderstandings if the metaphor is not well chosen or if the audience interprets it differently than intended.</p><p>But can we really be human without producing and consuming metaphors?</p><p>&quot;Ok, but what does it have to do with those two tales about <span class="text-red-500 font-bold">Dave</span> and <span class="text-green-600 font-bold">Dayanna</span>?&quot;, one might ask.</p><p>I am so happy that you asked that question! (or at least, I believe you did, dear Reader).</p><p>Recently, we constantly hear that AGI is &quot;just around the corner&quot;, and that &quot;we&#x27;re cooked&quot;, and so on.</p><p>Instead of throwing more fuel to the fire (next metaphor, huh?) of such discussions, why don&#x27;t we think what &quot;AI&quot; can give us back, when used properly?</p><p>&quot;Used properly&quot; is the key phrase here.</p><h3 id="amplifiers-not-replacements"><a href="#amplifiers-not-replacements" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Amplifiers, not replacements</h3><p>So far, we&#x27;ve followed two tales of imaginary senior software engineers, who used &quot;AI&quot; in different ways to achieve their goals.</p><p>What is really important is that both of the imaginary engineers were experienced, reflective, conscious professionals, who knew what they wanted to achieve.</p><p>They probably had a good mentals models, sourced from past experiences, saw both &quot;bad&quot; code and &quot;good&quot; code, and were able to judge the quality of the produced artifacts.</p><p>By observing <span class="text-red-500 font-bold">Dave</span> in action, one might say that he already internalized <a href="https://talesfrom.dev/blog/tdd-specify-satisfy-simplify">TDD</a> workflow (which I like to call 3S) and he used it pretty confidently in the past.</p><p>He used &quot;AI&quot; as a tool to amplify his capabilities, to deliver value sooner, knowing that the tool he produces might be actually put into production quite quickly.</p><p>It might be that <span class="text-red-500 font-bold">Dave</span> already worked with Outside-In development (as we saw how we focused on walking skeleton first), Domain-Driven Design (as we saw how he spotted missing domain concepts like <code>ConfigurationHistory</code>), and various design patterns (as we saw how he introduced Factory pattern).</p><p>For <span class="text-red-500 font-bold">Dave</span>, &quot;AI&quot; worked as an amplifier of his capabilities, to deliver value sooner, while keeping the quality of the produced artifacts at a satisfactory level.</p><p>As sound amplifier ehances the sound signal, it does not replace the instrument producing the sound, but it makes it louder, more powerful, so that more people can hear it.</p><h3 id="3d-printers-not-manufacturing-plants"><a href="#3d-printers-not-manufacturing-plants" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>3D printers, not manufacturing plants</h3><p>By observing <span class="text-green-600 font-bold">Dayanna</span> in action, one might say that she was able to identify a problem that needed to be solved.</p><p>She didn&#x27;t just jump into the solution by going through the logs, but she first analyzed the problem, identified the pain points, and then decided to build a tool that can help her achieve her goal.</p><p>She used &quot;AI&quot; as a tool to amplify her capabilities, to build a prototype quickly, maybe a little bit dirty, not really knowing if it will be useful later or not.</p><p>Years ago, doing this kind of prototyping and building a specialized tool would take days, if not weeks, sometimes involving a small team.</p><p>Requirements analysis, refinements, and so on.</p><p>But this time, it took couple of hours to have a working prototype that can be used to analyze the log files.</p><p><span class="text-green-600 font-bold">Dayanna</span> consciously stated it is a prototype which might have internal structure that might not last long.</p><p>To judge the quality of the produced code, she probably had a good mental model of what &quot;good enough&quot; means in this context.</p><p>She probably could tell what pain points the prototype might have, but she was ok with them, as long as the tool helps her achieve her primary goal - to help the support team analyze log files more efficiently.</p><p><span class="text-green-600 font-bold">Dayanna</span> used &quot;AI&quot; almost as a 3D printer - to quickly produce a tool that can help her and others, knowing that it might not be used across the whole organization for years.</p><p>Personal 3D printers are not manufacturing plants - meaning to achieve the economies of scale, producing large quantities, providing <strong>high quality</strong> outcomes.</p><p>Repeatedly.</p><h3 id="tools-amplify-capabilities"><a href="#tools-amplify-capabilities" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Tools amplify capabilities</h3><p>&quot;The form follows the function&quot;, as the golden saying goes.</p><p>The usage determines the mental form &quot;a thing&quot; takes.</p><p>People are using LLMs for a variety of purposes, from generating summaries up to producing videos of cats singing songs.</p><p>Haven&#x27;t we (human beings) always engaged with models?</p><p>Probably because of the LLM current context, one might conclude that by saying &quot;models&quot; I mean exactly LLMs - which is not true.</p><p>I am thinking about all the <em>mental models</em> we wield in our models repository (wherever it is, does not matter for now) so that we can use (consciously or unconsciously).</p><p>Internalized mental models frame how we think of the tools, hence impacting how we use them, including LLMs.</p><p>Imagine a scenario: whenever a problem appears (let&#x27;s assume it&#x27;s the right problem) and we built some initial understanding of its essence, we could ask ourselves, before jumping to finding a solution: &quot;what options do we have?&quot;.</p><p>&quot;what options do we have?&quot; - this innocently looking question implies the mental model itself - &quot;the operator&quot; needs to <em>know</em> about the concept of &quot;options&quot; so that it can be used (consciously or unconsciously) for working with the challenge in front of them.</p><p>And models are like metaphors - they help us to understand, to communicate, to work together.</p><p>Going back to our tales, both of the engineers <strong>were capable</strong> of either following <a href="https://talesfrom.dev/blog/tdd-specify-satisfy-simplify">TDD</a> workflow or building a prototype tool, because they had the mental models in place to do so.</p><p>They already <strong>internalized</strong> those models, so they could use them consciously to achieve their goals.</p><p>LLMs enhanced those capabilities, amplified them.</p><p>One can use LLMs to amplify skills, or as 3D printer to produce tools to amplify other capabilities.</p><p>Humans are doing that for ages.</p><p>If <em>the way we think</em> (meaning, what mental models use <em>have</em>) shapes the frame of <em>how we use tools</em>, then wouldn&#x27;t it make sense to work on (better) mental models?</p><p>Turns out that <a href="https://talesfrom.dev/blog/inverse-bruce-lee-maneuver">Inverse Bruce Lee maneuver</a> might be one strategy (a mental model?) to follow that path.</p><p>There might be more.</p><p>I invite you dear Reader, to reflect on your own mental models, observe the patterns of your thinking, and see how they impact your usage of LLMs (or life in general).</p><p>If something is not working in your measures, maybe it&#x27;s time to revisit your mental models, and see if they are serving you well.</p><p>This means we need to learn how to discard or deactivate models, remembering about them, but not blindly following them, because &quot;everything is a nail, right?&quot; instrumentation problem.</p><p>But the real foundation is to be aware - nothing really happens if you don&#x27;t see it.</p><p>&quot;The problem is that I don&#x27;t see the problem&quot;, as the saying goes.</p><p>Gigantic repository of mental models would be quite useless if one is not aware of the thinking patterns, behaviors and mental habits, isn&#x27;t it?</p><p>Then, work on your awareness, dear Reader.</p><p>There are plenty of easy tools like one-minute mindful sitting on the chair, just observing your breath, or mindful body scanning to put all attention on a little finger of your left foot (funny thing, you just realized that you have a left foot, didn&#x27;t you?).</p><p>The observation (the process) is the foundation of everything.</p><p>Happy exploring and modeling, dear Reader!</p>]]></content:encoded>
    <pubDate>Sat, 31 Jan 2026 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>domain-driven design</category><category>language patterns</category><category>design patterns</category><category>software architecture</category><category>mental models</category><category>communication</category><category>knowledge working</category><category>tools and capabilities</category><category>psychology</category><category>philosophy</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/cocoa-from-ports-and-adapters-to-concepts-capabilities-providers</guid>
    <title>COCOA: from Ports &amp; Adapters to concepts, capabilities and providers</title>
    <link>https://talesfrom.dev/blog/cocoa-from-ports-and-adapters-to-concepts-capabilities-providers</link>
    <description>Why changing the metaphor behind application architecture might be beneficial?</description>
    <content:encoded><![CDATA[<h3 id="time-for-a-little-detour"><a href="#time-for-a-little-detour" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Time for a little (de)tour?</h3><p>Imagine that we observe a discussion between a senior software engineer <span class="italic font-bold text-green-300">Dan</span>, an architect <span class="italic font-bold text-yellow-300">Alex</span> and a business stakeholder <span class="italic font-bold text-blue-300">Pete</span>.</p><p><span class="italic font-bold text-blue-300">Pete</span> is working in local, guided tourism business and he tries to explain to <span class="italic font-bold text-green-300">Dan</span> and <span class="italic font-bold text-yellow-300">Alex</span> how a particular workflow is working, so that they can modernize the technical side of it (because technical people should bother only by technical matters, right dear Reader?).</p><p>He explains the moment when a tour was published and what happens next.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-blue-300">Pete, a business stakeholder:</span><span>Ok, the tour got published.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>Why is it important?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-blue-300">Pete, a business stakeholder:</span><span>Only published tours can be activated.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>What does it mean that a published tour is activated?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-blue-300">Pete, a business stakeholder:</span><span>Well, it becomes visible in the web page as a search result, if that&#x27;s what counts as important. Customers can view the details of such a tour, then book it.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>Anything else? Why actually is it named as &quot;activated&quot; and not &quot;searchable&quot;?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-blue-300">Pete, a business stakeholder:</span><span>Hmm, good question. Some of the tours can be navigated by guides having specific skills or licenses. Whenever a tour has such a requirement, then we need to book this guide for this tour.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>Ok, it makes sense. I wonder, can we draw it?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-blue-300">Pete, a business stakeholder:</span><span>Yes, of course! Whatever helps you understand better.</span></div></span></div><p>So they pulled couple of stickies and following Event Storming notation, they created following visualization of the workflow:</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/concepts-capabilities-providers-tour-activation.png" class="max-h-[24rem]"/></div><div class="italic mx-24">A published tour becoming activated.</div></div><p>Technical folks continued asking.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>You said that customers can book it, what are consequences of that?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-blue-300">Pete, a business stakeholder:</span><span>Well, for each declared participant we need to reserve a seat, isn&#x27;t it obvious?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>Why is it important?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-blue-300">Pete, a business stakeholder:</span><span>Depending on the tour activities, sometimes we need to book buses to commute between locations. But let&#x27;s not complicate, for now at least.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>So reserving seats means that there needs to be a pool of seats available, while the tour is activated?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-blue-300">Pete, a business stakeholder:</span><span>Yes, that&#x27;s right. A tour must have a total number of available seats associated with it, otherwise we can&#x27;t track if the tour is full!</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>Could I put it on the board and you confirm if it matches how you understand it?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-blue-300">Pete, a business stakeholder:</span><span>Yup, let&#x27;s try.</span></div></span></div> <div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/concepts-capabilities-providers-tour-activation-search-and-seats-pool.png" class="max-h-[24rem]"/></div><div class="italic mx-24">Two consequences of activating a published tour.</div></div><p><span class="italic font-bold mr-2 text-blue-300">Pete</span> visibly started thinking, while staring at the board, and then he continued explaining.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-blue-300">Pete, a business stakeholder:</span><span>&quot;Tour becomes searchable&quot;, does it represent that a tour can appear in the search results?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>Yes, exactly.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-blue-300">Pete, a business stakeholder:</span><span>Ok, if that&#x27;s what you mean, then fine.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>In our previous collaborative session, when we looked through potential opportunities and risks, you highlighted something related to participants getting lost, could you say something about it?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-blue-300">Pete, a business stakeholder:</span><span>Yes, what we explored during this &quot;Big Picture&quot; session, is really big deal. Our guides often report that some participants do not follow the guide and walk to the next activity location using different routes than the group. That&#x27;s what I meant they &quot;are getting lost&quot; - so a consequence of that is a guide who needs to &quot;chase&quot; them.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>How does a guide &quot;chase&quot; such participants?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-blue-300">Pete, a business stakeholder:</span><span>Well, a guide prepares a list of all adult participants with phone numbers - whenever an adult participant is lost, a guide can call them. It&#x27;s pretty easy job, but it drags attention from other participants, which make them irritated and so on.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>While calling them using the mobile phone, what does a guide ask for?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-blue-300">Pete, a business stakeholder:</span><span>The most important thing is to locate them - so a guide asks where they are, and after that a guide either goes to get them back or asks them to return to the group.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>What if they did not return?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-blue-300">Pete, a business stakeholder:</span><span>A guide calls again and checks where they are.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>Ok, if I correctly follow you, a guide needs to be capable of locating participants, right? How this is achieved today is that guides prepare participant-to-phone-number lists, which then is used for calling?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-blue-300">Pete, a business stakeholder:</span><span>Yes, you stated it very precisely. Can we go back to the board - I see we didn&#x27;t put booking guides when a tour requires specific skills.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>Sure, let me add it.</span></div></span></div> <div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/concepts-capabilities-providers-tour-activation-search-and-seats-pool-and-guides.png" class="max-h-[24rem]"/></div><div class="italic mx-24">An additional consequence of activating a published tour.</div></div><p><span class="italic font-bold text-yellow-300">Alex</span> was not happy that suddenly they jumped out of the topic of losing the location of participants, his architectural spider senses told him that something important is hidden there.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>And regarding locating lost participants - in a way, a guide needs to track location of each participant, right?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-blue-300">Pete, a business stakeholder:</span><span>Hmmmm, a guide needs to know where a participant is, yes - we can say so.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>But is this knowledge required while the tour is activated?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-blue-300">Pete, a business stakeholder:</span><span>No, definitely not. Such information is important while a guide navigates the tour.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>So such guide needs to actively track location at that moment, otherwise such tracking is not necessary.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-blue-300">Pete, a business stakeholder:</span><span>Yes, participants tracking is necessary during tour navigation.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>I&#x27;ll put something on the board right now.</span></div></span></div><p><span class="italic font-bold mr-2 text-green-300">Dan</span> walked to the board and placed another orange sticky, representing another consequence of activating a published tour.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/concepts-capabilities-providers-tour-activation-all-four-consequences.png" class="max-h-[24rem]"/></div><div class="italic mx-24">All four consequences of activating a published tour, including establishing inactive geotracking session.</div></div><p><span class="italic font-bold text-blue-300">Pete</span> did not understand it in the first place, but both <span class="italic font-bold text-green-300">Dan</span> and <span class="italic font-bold text-yellow-300">Alex</span> explained the idea behind geotracking session and why it starts as inactive.</p><p>After couple of minutes of discussion, <span class="italic font-bold text-blue-300">Pete</span> nodded and confirmed that it matches his understanding.</p><p>They told him that as soon as the tour navigation starts, such geotracking session becomes activated, and guides will be able to track participants&#x27; locations.</p><p>Technical folks thanked the business stakeholder for his time and insights, and they went back to their office to started collaborating on the solution, using the insights and findings.</p><h3 id="what-is-possible"><a href="#what-is-possible" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What is possible?</h3><p><span class="italic font-bold text-yellow-300">Alex</span> looked at the board again, and he started thinking and mumbling to himself, at the same time.</p><p><span class="italic font-bold text-green-300">Dan</span> was typing something on the keyboard, and suddenly he stopped and looked at <span class="italic font-bold text-yellow-300">Alex</span>.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>Hey Alex, what are you thinking about?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>Well, I was thinking about business capabilities we need while the tour is activated.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>Business capabilities? What do you mean?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>Each orange sticky tells us that there was an important state change, right? And they are consequences of requesting jobs to be done, based on the needs of the consumer - in this context, something orchestrating published tour activation.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>Yeah, orange stickies are events, so I think we need to publish an event - <code>Published Tour Activated</code>. Then four services need to listen on it, translate it to a respective command, and handle those.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>Pardon me, commands?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>You know, CQRS - Command Query Responsibility Segregation. Events represent something that happened, and commands represent an intention to do something.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>Hmm, if we take an architectural element, a component providing <code>Searching</code> business capability, why do you want it to listen to a very specific event? It would creating coupling.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>Are you nuts? Events decouple things. Come on, I know you are an architect, but please do follow recent trends. Everyone talks about that - events bring <strong>decoupling</strong>.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>I&#x27;ve heard about CQRS, but I don&#x27;t feel how can it help. I see that in order to provide published tour activation capability, we need four capabilities: one for establishing seats pool, one for creating search entry, one for booking guide and another one for creating inactive geotracking session.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>I still don&#x27;t get what do you mean about those capabilities, but in my world they will be simple ports.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>Ports?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>Oh come one, ports - Ports &amp; Adapters - didn&#x27;t you hear about that one too?!</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>There are two other capabilities that were not mentioned, but they are required too: one for loading a published tour for activation and another one for saving activated published tour.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>Are you listening to me, Alex?! You know what, let&#x27;s go to the code, I&#x27;ll show you how I would implement that use case.</span></div></span></div><p>And <span class="italic font-bold text-green-300">Dan</span> started typing, representing his understanding of how to implement the published tour activation workflow.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="code-highlight language-csharp"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ActivatePublishedTourCommandHandler</span><span class="token punctuation">(</span>
</span><span class="code-line">    <span class="token class-name">IPublishedTourRepository</span> publishedTourRepository<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">ISearchService</span> searchService<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">ISeatsPoolService</span> seatsPoolService<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">IGuideBookingService</span> guideBookingService<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">IGeotrackingService</span> geotrackingService<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">IEventsPublisher</span> eventsPublisher
</span><span class="code-line"><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">Task</span> <span class="token function">Handle</span><span class="token punctuation">(</span><span class="token class-name">ActivatePublishedTourCommand</span> command<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> publishedTour <span class="token operator">=</span> <span class="token keyword">await</span> publishedTourRepository<span class="token punctuation">.</span><span class="token function">Load</span><span class="token punctuation">(</span>command<span class="token punctuation">.</span>PublishedTourId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">if</span> <span class="token punctuation">(</span>publishedTour <span class="token keyword">is</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">PublishedTourNotFoundException</span><span class="token punctuation">(</span>command<span class="token punctuation">.</span>PublishedTourId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">        publishedTour<span class="token punctuation">.</span><span class="token function">Activate</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">await</span> publishedTourRepository<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>publishedTour<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">await</span> eventsPublisher<span class="token punctuation">.</span><span class="token function">Publish</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name constructor-invocation">PublishedTourActivatedEvent</span><span class="token punctuation">(</span>publishedTour<span class="token punctuation">.</span>Id<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token keyword">await</span> searchService<span class="token punctuation">.</span><span class="token function">CreateSearchEntry</span><span class="token punctuation">(</span>@<span class="token keyword">for</span><span class="token punctuation">:</span> publishedTour<span class="token punctuation">.</span><span class="token function">ToSearchEntry</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">await</span> seatsPoolService<span class="token punctuation">.</span><span class="token function">EstablishSeatsPool</span><span class="token punctuation">(</span>publishedTour<span class="token punctuation">.</span>Id<span class="token punctuation">,</span> publishedTour<span class="token punctuation">.</span>SeatsCount<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">if</span><span class="token punctuation">(</span>publishedTour<span class="token punctuation">.</span>RequiresGuideBooking<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">await</span> guideBookingService<span class="token punctuation">.</span><span class="token function">BookGuide</span><span class="token punctuation">(</span>publishedTour<span class="token punctuation">.</span>Id<span class="token punctuation">,</span> publishedTour<span class="token punctuation">.</span>RequiredGuideSkills<span class="token punctuation">,</span> publishedTour<span class="token punctuation">.</span>NavigationDate<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">        <span class="token keyword">await</span> geotrackingService<span class="token punctuation">.</span><span class="token function">CreateInactiveGeotrackingSession</span><span class="token punctuation">(</span>publishedTour<span class="token punctuation">.</span>Id<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Even though <span class="italic font-bold text-green-300">Dan</span> was very keen on going fully with Event-Driven Architecture, because he believed in its benefits, he decided to implement the entire workflow in a single command handler.</p><p>It reflected exactly what was visualized on the board, and it was easy to understand.</p><p>And because it was easy to understand, it was easy to debug, test, and maintain.</p><p><span class="italic font-bold text-yellow-300">Alex</span> looked at the code, and asked about what happens if one of the services fails - whether the entire operation is expected to be rolled back, or not.</p><p>But the discussion quickly stopped and both of them started doing circles between business capabilities and ports and adapters.</p><h3 id="clean-adaptive-hexagonal-ports-or-something-else"><a href="#clean-adaptive-hexagonal-ports-or-something-else" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Clean, adaptive hexagonal ports, or something else?</h3><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>I see that you expressed exactly what I was saying aloud - six required capabilities.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>You mean the ports? Yeah, that&#x27;s exactly what I was thinking after looking at the board.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>I think our board does not match the code right now, because it shows only important state changes. Should we add those capabilities?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>When you say capabilities - you think of commands? If yes, then I agree - let&#x27;s add them.</span></div></span></div> <div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/concepts-capabilities-providers-tour-activation-commands-capabilities.png" class="max-h-[24rem]"/></div><div class="italic mx-24">A complete workflow of published tour activation.</div></div><p>They included blue stickies for commands and green stickies representing state that is used in a particular step of a workflow.</p><p>Now the board reflected the code better, and both <span class="italic font-bold text-green-300">Dan</span> and <span class="italic font-bold text-yellow-300">Alex</span> were happy.</p><p><span class="italic font-bold text-yellow-300">Alex</span> was curious about the mismatch between the language that he used and what <span class="italic font-bold text-green-300">Dan</span> used.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>Dan, I noticed that both me and you disagree on terms, but we mostly speak about the same thing.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>Hmm, you might be right. I still don&#x27;t get what did you mean by saying &quot;business capabilities&quot;. There are various patterns people use - CQRS, Vertical Slices, Hexagonal Architecture, Clean Architecture, Ports &amp; Adapters (that&#x27;s my favorite, by the way), but never business capabilities.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>&quot;Business capabilities&quot; is not a new concept, just so you know. As far as I recall, it originated in enterprise architecture reasoning.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>Enterprise architecture - now you scared me.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>Sorry for that. A business capability is pretty pragmatic, in its role. It expresses &quot;<strong>WHAT</strong>, not <strong>HOW</strong> and not <strong>WHO</strong>&quot;. Can you show me ports that you used in the code?</span></div></span></div><p><span class="italic font-bold text-green-300">Dan</span> pointed to the command handler constructor parameters, and <span class="italic font-bold text-yellow-300">Alex</span> nodded.</p><p>Then, he showed all the interfaces representing those ports:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="code-highlight language-csharp"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">IPublishedTourRepository</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>PulishedTour<span class="token punctuation">?</span><span class="token punctuation">&gt;</span></span> <span class="token function">Load</span><span class="token punctuation">(</span><span class="token class-name">PublishedTourId</span> id<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token class-name return-type">Task</span> <span class="token function">Save</span><span class="token punctuation">(</span><span class="token class-name">PublishedTour</span> publishedTour<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">ISearchService</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name return-type">Task</span> <span class="token function">CreateSearchEntry</span><span class="token punctuation">(</span><span class="token class-name">SearchEntry</span> entry<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">ISeatsPoolService</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name return-type">Task</span> <span class="token function">EstablishSeatsPool</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token class-name">PublishedTourId</span> publishedTourId<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">int</span></span> seatsCount
</span><span class="code-line">    <span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">IGuideBookingService</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name return-type">Task</span> <span class="token function">BookGuide</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token class-name">PublishedTourId</span> publishedTourId<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">IEnumerable<span class="token punctuation">&lt;</span>Skill<span class="token punctuation">&gt;</span></span> requiredSkills<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">DateTime</span> navigationDate
</span><span class="code-line">    <span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">IGeotrackingService</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name return-type">Task</span> <span class="token function">CreateInactiveGeotrackingSession</span><span class="token punctuation">(</span><span class="token class-name">PublishedTourId</span> publishedTourId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">IEventsPublisher</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name return-type">Task</span> <span class="token function">Publish</span><span class="token punctuation">(</span><span class="token class-name">DomainEvent</span> domainEvent<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>By looking at the interfaces and how they are used, can you tell me who is providing those capabilities?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>No, just by looking at the interfaces and the command, I can&#x27;t.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>Can you say how <code>EstablishSeatsPool</code> is implemented?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>No, I can&#x27;t say - I just use that method, trusting that a responsible object knows how to provide it.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>Exactly - so they express what I call a business capability.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>Ok, but how does loading and saving published tour relate to a business needs?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>Well, storing and restoring information is pretty fundamental to many businesses, isn&#x27;t it? When you get money from a client, wouldn&#x27;t you like to keep that information?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>Hmmm, I see you point now - because it&#x27;s one of the fundamental capabilities that supports business operations.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>Restoring information is also important - we do it either to make a decision or present it for others to make a decision. How can you decide to buy something if you know how much money do you have?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>So each interface represents a business capability?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>Sometimes there are capabilities that are not directly expressed by business people, and they can be regarded as pure fabrications, a technical necessity to support other capabilities.</span></div></span></div><p><span class="italic font-bold text-green-300">Dan</span> felt that something important just clicked in his mind.</p><p>Ports were not just technical abstractions, they could be expressions of business capabilities, that are required by a particular use case!</p><p>He was wondering about the implications of that realization, so he immediately asked about adapters.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>Alex, if those port interfaces play a role of business capabilities, expressing what, not how and not who - what about adapters? What is the role they play?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>Good question - if we take a delivery company - what capabilities do they provide for consumers like you?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>They provide package delivery - I can send packages to my friends. So you mean that they are a delivery capability providers?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>Yup, they are providers. If you need to send a package, could you provide such capability for yourself? Probably yes, but you decide to use another providers, by exchanging various things for money.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>So adapters are capability providers?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>Yes, adapters are required capability providers.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>&quot;Required&quot;? What do you mean?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>If you look at command handler, it uses interfaces, because it <strong>requires</strong> them to satisfy its consumer needs. We could say that satisfying consumer needs can be regarded as a <strong>providing</strong> a capability to them.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>A command handler requires capabilities to provide a capability?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>Exactly, and the best part is that our command handler is a provider itself too.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>Yyyyy?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>Look from the perspective of a consumer, who invokes the command handler via HTTP API, does it matter how &quot;published tour activation&quot; capability is provided?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>Mhm, no. From that perspective, it does not matter.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>So instead of those nice interfaces, we could use transaction script, write everything in a database, and still capability will be provided?</span></div></span></div><p><span class="italic font-bold text-green-300">Dan</span> was enlightened.</p><p>This means that ports and adapters can express something more profound than just another way of structuring software.</p><p>Then can be used to express business capabilities and their providers.</p><p>And what truly matters is <strong>a perspective</strong> - a command handler can be either a capability provider or a consumer, requiring other capabilities.</p><p>But never both at the same time, as holding <a href="https://talesfrom.dev/blog/the-invisible-role-switching-problem-and-need-driven-design/">two perspectives is really difficult, if not impossible</a>.</p><p><span class="italic font-bold text-yellow-300">Alex</span> asked <span class="italic font-bold text-green-300">Dan</span> to show him a directory structure of the project, so that they can see how those concepts are expressed there.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-text code-highlight"><span class="code-line">src/
</span><span class="code-line">└── ActivatePublishedTour/
</span><span class="code-line">    ├── Adapters/
</span><span class="code-line">    ├── Api/
</span><span class="code-line">    ├── Domain/
</span><span class="code-line">    ├── Ports/
</span><span class="code-line">    └── ActivatePublishedTourCommandHandler.cs
</span></code></pre></div></div><p>Just to reinforce the idea of business capabilities, <span class="italic font-bold text-yellow-300">Alex</span> asked if it matters, from a consumer, outside-in perspective, whether there is no folder structure inside <code>ActivatePublishedTour/</code> folder, and <span class="italic font-bold text-green-300">Dan</span> agreed that it does not matter.</p><p>&quot;I think that&#x27;s what is advocated through Vertical Slices&quot;, he thought to himself.</p><p>After expanding all the directories, they saw following structure:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-text code-highlight"><span class="code-line">src/
</span><span class="code-line">└── ActivatePublishedTour/
</span><span class="code-line">    ├── Adapters/
</span><span class="code-line">    │   ├── PostgresPublishedTourRepository.cs
</span><span class="code-line">    │   ├── RabbitMqGuideBookingService.cs
</span><span class="code-line">    │   ├── RabbitMqGeotrackingService.cs
</span><span class="code-line">    │   ├── RabbitMqSearchService.cs
</span><span class="code-line">    │   └── RabbitMqSeatsPoolService.cs
</span><span class="code-line">    ├── Api/
</span><span class="code-line">    │   └── Http/
</span><span class="code-line">    │       └── ActivatePublishedTourEndpoint.cs
</span><span class="code-line">    ├── Domain/
</span><span class="code-line">    │   ├── Events/
</span><span class="code-line">    │   │   └── PublishedTourActivated.cs
</span><span class="code-line">    │   └── Models/
</span><span class="code-line">    │       ├── PublishedTour.cs
</span><span class="code-line">    │       ├── SearchEntry.cs
</span><span class="code-line">    │       └── Skill.cs
</span><span class="code-line">    ├── Ports/
</span><span class="code-line">    │   ├── IEventsPublisher.cs
</span><span class="code-line">    │   ├── IGeotrackingService.cs
</span><span class="code-line">    │   ├── IGuideBookingService.cs
</span><span class="code-line">    │   ├── IPublishedTourRepository.cs
</span><span class="code-line">    │   ├── ISearchService.cs
</span><span class="code-line">    │   └── ISeatsPoolService.cs
</span><span class="code-line">    └── ActivatePublishedTourCommandHandler.cs
</span></code></pre></div></div><p><span class="italic font-bold text-yellow-300">Alex</span> smiled and asked, knowing what they both learned, if they could do a little renaming.</p><p>The idea was to rename <code>Ports/</code> directory to <code>RequiredCapabilities/</code>, <code>Adapters/</code> directory to <code>Providers/</code>.</p><p>Additionally, rename <code>Domain/</code> to <code>Concepts/</code>, which made <span class="italic font-bold text-green-300">Dan</span> a little bit confused, as they were not discussing that before, but <span class="italic font-bold text-yellow-300">Alex</span> asked to firstly do so and then they could discuss it.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-text code-highlight"><span class="code-line">src/
</span><span class="code-line">└── ActivatePublishedTour/
</span><span class="code-line">    ├── Api/
</span><span class="code-line">    │   └── Http/
</span><span class="code-line">    │       └── ActivatePublishedTourEndpoint.cs
</span><span class="code-line">    ├── Concepts/
</span><span class="code-line">    │   ├── Events/
</span><span class="code-line">    │   │   └── PublishedTourActivated.cs
</span><span class="code-line">    │   └── Models/
</span><span class="code-line">    │       ├── PublishedTour.cs
</span><span class="code-line">    │       ├── SearchEntry.cs
</span><span class="code-line">    │       └── Skill.cs
</span><span class="code-line">    ├── Providers/
</span><span class="code-line">    │   ├── PostgresPublishedTourRepository.cs
</span><span class="code-line">    │   ├── RabbitMqGuideBookingService.cs
</span><span class="code-line">    │   ├── RabbitMqGeotrackingService.cs
</span><span class="code-line">    │   ├── RabbitMqSearchService.cs
</span><span class="code-line">    │   └── RabbitMqSeatsPoolService.cs
</span><span class="code-line">    ├── RequiredCapabilities/
</span><span class="code-line">    │   ├── IEventsPublisher.cs
</span><span class="code-line">    │   ├── IGeotrackingService.cs
</span><span class="code-line">    │   ├── IGuideBookingService.cs
</span><span class="code-line">    │   ├── IPublishedTourRepository.cs
</span><span class="code-line">    │   ├── ISearchService.cs
</span><span class="code-line">    │   └── ISeatsPoolService.cs
</span><span class="code-line">    └── ActivatePublishedTourCommandHandler.cs
</span></code></pre></div></div><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>I use &quot;concepts&quot; very intentionally - they express abstract ideas that are important in a particular capability that we provide.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>Abstract idea?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>For me an abstraction is a very specific perspective one holds to think about something. People often tend to think in absolute terms, mixing many perspectives, and putting that knowledge in a single entity - a User, a Tour, a Product.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>Hmmm, so &quot;concept&quot; means some kind of a decomposition?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>You are really close - a context-based decomposition, contextual segregation. For example, we don&#x27;t want to think about base price while activating a published tour, that&#x27;s why we don&#x27;t bring that information in.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>Same with past reviews, they are not needed while activating a published tour.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>Exactly. Concepts are about focusing on what matters in a specific context, in a way they <strong>outline</strong> a boundary...</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-green-300">Dan, a software engineer:</span><span>...In which they have sense and mean something!</span></div></span></div><p><span class="italic font-bold text-green-300">Dan</span> was excited about the new terminology. It seemed to him that while talking to business stakeholders, it was easier to talk about &quot;capabilities&quot; rather than &quot;ports&quot; or &quot;commands&quot;.</p><p>Also, &quot;providers&quot; sounded slighlty more humane than &quot;adapters&quot;.</p><p>It almost felt as super powers - was that the secret technique used by enterprise architects to communicate with business stakeholders?</p><p>Finally, &quot;concepts&quot; made perfect sense - it expressed the idea of focusing on what matters in a specific context.</p><p>He was eager to try those new terms in his next conversations with business stakeholders.</p><h2 id="hexagonal-clean-onion-hardware"><a href="#hexagonal-clean-onion-hardware" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Hexagonal? Clean? Onion? Hardware?</h2><p>Ok, time to stop this lovely tale.</p><p>&quot;You must be kidding me&quot;, some Readers could think right now.</p><p>&quot;It&#x27;s soo foolish to rename well-known terms like ports and adapters to capabilities and providers, and domain to concepts!&quot;, others might comment in their heads.</p><p>&quot;You did so just to sound fancy and different!&quot;, one could accuse.</p><p>&quot;Isn&#x27;t it a SOA reincarnation?&quot;, yat another could blame.</p><p>How dare I propose a new terminology, in the world where so many architectural patterns already exist, describing similar ideas?</p><p>Whatever we mentally do, as human beings, we build mental models.</p><p>A model is like a metaphor - it&#x27;s not created to be perfect, accurate, and complete.</p><p>It is brought to life to help us understand something, to reason about it, to communicate our understanding to others.</p><p>It might have its flaws, but if it emphasizes the essentials, it does its job.</p><p>Isn&#x27;t <a href="https://talesfrom.dev/blog/the-ambiguity-of-abstraction">abstractions</a> just that - imperfect mental models that help us reason about complex things?</p><p>Nevermind, let&#x27;s get back to the point.</p><p>We use a variety of models to describe application architecture: hexagonal architecture, onion architecture, clean architecture, ports and adapters architecture.</p><p>Some of them were named after the shape, some were named after &quot;clean code&quot; to sound similar, others were named after hardware and the idea separating ports from adapters.</p><p>Each of them convey profound ideas that shape the way we reason about our applications, and aim at bringing certain qualities.</p><p>The big idea behind each of them is to isolate the application logic from the outside, external concerns, to make everything testable and maintainable.</p><p>But nothing really stops us from using <a href="https://talesfrom.dev/blog/the-ambiguity-the-curse-and-the-fallacy-of-domain-model"><strong>THE</strong> domain model</a>, a single entity for everything.</p><p>It will attract more and more the knowledge, growing into enormous size, becoming unmaintanable, untestable, and inflexible.</p><p>To counteract that, CQRS-thinking comes into play, helping us with model segregation: some for writing (or making a decisions), others for reading (or presenting information to make a decision).</p><p>Commands typically need little information, just to make a decision with transactional integrity, whereas queries might require tons of information, aggregated from various sources, to present a complete picture.</p><p>And nothing really stops us from coupling decision models across various use cases, making them interdependent and inflexible.</p><p>To counteract that, Vertical Slices-thinking comes into play, helping us with reasoning about independent use cases, where isolation and possible duplication are acceptable for independent evolution.</p><p>Of course, we&#x27;re touching only the surface of these topics.</p><p>All of those models are imperfect, but useful - they help us reasoning and communicating about complex things.</p><p>When one developer says &quot;port&quot;, another one immediately understands what is meant.</p><p>In a way, those are the language patterns technical people use to communicate.</p><p>What about communicating across boundaries?</p><p>When we communicate with business stakeholders, would they understand what is meant by &quot;port&quot; or &quot;adapter&quot;?</p><p>&quot;Of course not, you dummy&quot; - one might easily answer.</p><p>No one uses such words in business conversations, right?</p><p>How naive one would be to use entity, aggregate, repository or even domain in conversations with business stakeholders - those terms are pretty tactical, &quot;low-level&quot;, and technical.</p><p>Others can use &quot;use cases&quot;, &quot;features&quot;, &quot;services&quot; - but those terms are so overloaded that they hardly help in communication.</p><p>Somehow architects are able to reason about business, enterprises, without stepping too much into technical details (which many times is a problem on its own, but let&#x27;s leave it for another blogpost).</p><p>Through our tiny tale, we saw how an architect and a software engineer struggled to find a common ground to effectively communicate.</p><p>How often do we see that happening in real life - two technical folks discussing a solution, but failing to understand each other?</p><p>The idea behind this tale is not to resolve all the misunderstandings, and conflicts that arise in such conversations - oh no.</p><p>It is yet again an attempt to show that <a href="https://talesfrom.dev/blog/the-ambiguity-of-naming">naming is framing</a> - how we name things shapes the way we think about the world.</p><h2 id="what-not-who-and-not-how"><a href="#what-not-who-and-not-how" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>WHAT, not WHO and not HOW</h2><p>Living next to Ports&amp;Adapters and other types of application architecture might make us blind to strategic aspects of the business area we might build software solutions for.</p><p>And please do not get me wrong, dear Reader - I am not saying that Ports&amp;Adapters and others are bad, incorrect, or that we should abandon it.</p><p>&quot;All models are wrong (=imperfect, an interpretation of mine), but some are useful&quot;, as George Box said.</p><p>Let&#x27;s start - what is a business capability?</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">a business capability - short version</div><div class="pb-2 px-3"><div class="break-words"><p><strong>What</strong> a business does or needs to be able to do to achieve its objectives.</p></div></div></div><p>A longer version:</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">a business capability - long version</div><div class="pb-2 px-3"><div class="break-words"><p>An ability of an organization to perform a particular business activity, supporting its business operations and goals. It&#x27;s a stable, abstract description of business functions that doesn&#x27;t change much over time, regardless of how the organization is structured or which technologies are used.</p></div></div></div><p>Both are inspired by enterprise architecture thinking.</p><p>The most important is that we focus on <strong>WHAT</strong> needs to be done, not <strong>HOW</strong> and not <strong>WHO</strong>.</p><p>So we frame our thinking around <strong>capabilities</strong> - what needs to be provided to satisfy <a href="https://talesfrom.dev/blog/consumer-expected-need-driven-behavior-development">consumer needs</a>.</p><p><strong>Needs</strong> are very important as they enable the way of reasoning, Outside-In one, that drives everything.</p><p>Ideally, there should be one technical authority for a business capability.</p><p>In other words, one <strong>(capability) provider</strong>.</p><p>One could say that as long as the capability is provided with success, it does not matter <strong>who</strong> provides it, or <strong>how</strong>.</p><p>But when we step into a details of a given provider, suddenly <strong>how</strong> matters a lot.</p><p>Such <strong>provider</strong> becomes <strong>a consumer</strong>, <strong>requiring</strong> other <strong>capabilities</strong> in order to provide the capability it was contracted with.</p><p>A <strong>(capability) provider</strong> uses <strong>concepts</strong> that depict important ideas that matter for that capability.</p><p>Those <strong>abstract terms</strong> mean something <strong>inside that boundary</strong>, as if there were <strong>invisible contours outlining</strong> the context in which those concepts make sense.</p><p>Additionally, conceptual outlining helps counteracting absolute, universal and reality-chasing <a href="https://talesfrom.dev/blog/the-ambiguity-the-curse-and-the-fallacy-of-domain-model">models</a> that suffer from <a href="https://talesfrom.dev/blog/the-knowledge-gravity-problem">the knowledge gravity problem</a>.</p><p>Yes, dear Reader, if you are familiar with Domain-Driven Design, you might see some similarities with Bounded Contexts and Ubiquitous Language.</p><p>And I think it might be quite important to express it explicitly, when we discuss application architecture.</p><p>Here comes the idea of <strong>COCOA</strong> - <strong>Capabilities</strong>-Oriented, <strong>Concepts</strong>-Outlined Architecture.</p><h2 id="cocoa-capabilities-oriented-concepts-outlined-architecture"><a href="#cocoa-capabilities-oriented-concepts-outlined-architecture" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>COCOA: Capabilities-Oriented, Concepts-Outlined Architecture</h2><p>In <strong>COCOA</strong>, we would like to reason about application architecture through the lens of <strong>business capabilities</strong>, their <strong>providers</strong>, and <strong>concepts</strong> that outline the context in which make sense.</p><p>One shouldn&#x27;t forget the big picture, the high-level persperctive, thinking only about low-level tactical details.</p><p>Sometimes a required capability would be provided by team-owned service, whereas other times it would be provided by a third-party system.</p><p>The capability does not change, but the provider does.</p><p>While testing, one might mock a required capability by using a mock provider so that we are able to verify if a specific step happened.</p><p>But when we register dependencies in the composition root, we would use a real provider that communicates with another system over HTTP, or a database.</p><p>Summing it all up:</p><ul><li>When we think about <strong>concepts</strong>, we think about <strong>WHAT</strong> abstract ideas and terms matter in a specific context.</li><li>When we think about <strong>capabilities</strong>, we think about <strong>WHAT</strong> needs to be provided, not <strong>HOW</strong> and not <strong>WHO</strong>, from the persperctive of a consumer.</li><li>When we think about <strong>providers</strong>, we think about <strong>WHO</strong> provides the capability, and <strong>HOW</strong> it is provided, but only from the perspective of that provider.</li></ul><p><strong>Capabilities</strong> are pretty important here, emphasizing the behavioral aspects of the system.</p><p>Reasoning behind that is similar to <a href="https://www.sandimetz.com">Sandi Metz&#x27;s</a> words about objects and messages:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>You don&#x27;t send messages because you have objects, you have objects because you send messages.</p></div></div></div><p>Which can be rephrased in the context of capabilities and providers as:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>You don&#x27;t have capabilities because you need providers, you have providers because you need capabilities.</p></div></div></div><p>And of course, now you might be thinking now, dear Reader, if we discussed &quot;business capabilities&quot;, what about &quot;business processes&quot;?</p><p>Let&#x27;s get a brief definition.</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">a business process - short version</div><div class="pb-2 px-3"><div class="break-words"><p>A business process is <strong>how</strong> the business does something.</p></div></div></div><p>And a longer version:</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">a business process - long version</div><div class="pb-2 px-3"><div class="break-words"><p>It&#x27;s a specific sequence of activities, steps, and tasks that transform inputs into outputs. Processes are more concrete and can change frequently as the business optimizes operations or adopts new technologies.</p></div></div></div><p>Doesn&#x27;t it sound similar to a workflow we saw our three amigos visualizing on the board?</p><p>It was a logical sequence of steps that needed to be performed to achieve a specific goal.</p><p>A description of <strong>HOW</strong> something is done.</p><p>In that context, the goal was activating a published tour.</p><p>Let&#x27;s shift our focus to the problem of locating &quot;lost participants&quot;, that <span class="italic font-bold text-yellow-300">Pete</span> mentioned.</p><p>He described <strong>HOW</strong> a guide (<strong>WHO</strong>) tried to locate lost participants by calling them over the phone, asking repeatedly until they reached the group.</p><p>So the guide was a capability provider in that context.</p><p>The architect and the software engineer suggested an abstraction - &quot;geotracking&quot; capability.</p><p>They tried to depict <strong>WHAT</strong> needed to be provided.</p><p>Of course, when this &quot;geotracking&quot; capability is provided by a software system, there will be a sequence of logical steps to provide it.</p><p>But yet again, it is a matter of <strong>the perspective</strong>.</p><p>When we look from outside, as consumers, we care about <strong>WHAT</strong>.</p><p>When we look from inside, as capability providers, we care about <strong>HOW</strong>.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/concepts-capabilities-providers-tour-activation-persperctives.png" class="max-h-[24rem]"/></div><div class="italic mx-24">A consumer and a provider perspectives</div></div><p>For a consumer - it does not matter <strong>HOW</strong> geotracking is provided, as long as it is provided.</p><p>For a provider - it matters <strong>HOW</strong> geotracking is provided, as long as it satisfies consumer needs.</p><p>If we are <strong>outside</strong> the boundary, reasoning will be framed around capabilities.</p><p>If we are <strong>inside</strong> the boundary, reasoning will be framed around processes.</p><h2 id="why-cocoa"><a href="#why-cocoa" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Why COCOA?</h2><p>You might be wondering, dear Reader, why and how on earth I came up with COCOA.</p><p>It&#x27;s because I love chocolate?</p><p>Am I a cocoa farmer on the side?</p><p>I needed a catchy phrase, that&#x27;s all.</p><p>The big thing is not the name, not the symbol, not the abstraction.</p><p>The real deal is the mental model behind it.</p><p>I tried to reflect on my experiences and observations, and synthesize them into something useful.</p><p>A mental model that mainly helps me with reasoning and helps me with communication.</p><p>It enables me changing the levels (using Gregor Hohpe&#x27;s <a href="https://architectelevator.com/">The Software Architect Elevator</a> metaphor), connecting higher-level, strategic thinking with tactical, technical implementations.</p><p>As mentioned before, I am not saying that Ports &amp; Adapters (and others), CQRS and Vertical Slices are anyhow &quot;bad&quot; or &quot;incorrect&quot;.</p><p>I learned from them, used them, drew from them, and they shaped the way I think about application architecture.</p><p>COCOA is another model one can use to think about application architecture.</p><p>It still uses isolation, separation of concerns, and other qualities, but it also tries to capture and emphasize strategic aspects of the business area we are building software solutions for.</p><p>Organizing code is very important topic to many, so how potentially COCOA would look like in practice?</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-text code-highlight"><span class="code-line">src/
</span><span class="code-line">└── ActivatePublishedTour/
</span><span class="code-line">    ├── Api/
</span><span class="code-line">    ├── Concepts/
</span><span class="code-line">    ├── Providers/
</span><span class="code-line">    ├── RequiredCapabilities/
</span><span class="code-line">    └── ActivatePublishedTourCommandHandler.cs
</span></code></pre></div></div><p>And when expanding all the directories:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-text code-highlight"><span class="code-line">src/
</span><span class="code-line">└── ActivatePublishedTour/
</span><span class="code-line">    ├── Api/
</span><span class="code-line">    │   └── Http/
</span><span class="code-line">    │       └── ActivatePublishedTourEndpoint.cs
</span><span class="code-line">    ├── Concepts/
</span><span class="code-line">    │   ├── Events/
</span><span class="code-line">    │   │   └── PublishedTourActivated.cs
</span><span class="code-line">    │   └── Models/
</span><span class="code-line">    │       ├── PublishedTour.cs
</span><span class="code-line">    │       ├── SearchEntry.cs
</span><span class="code-line">    │       └── Skill.cs
</span><span class="code-line">    ├── Providers/
</span><span class="code-line">    │   ├── PostgresPublishedTourRepository.cs
</span><span class="code-line">    │   ├── RabbitMqGuideBookingService.cs
</span><span class="code-line">    │   ├── RabbitMqGeotrackingService.cs
</span><span class="code-line">    │   ├── RabbitMqSearchService.cs
</span><span class="code-line">    │   └── RabbitMqSeatsPoolService.cs
</span><span class="code-line">    ├── RequiredCapabilities/
</span><span class="code-line">    │   ├── IEventsPublisher.cs
</span><span class="code-line">    │   ├── IGeotrackingService.cs
</span><span class="code-line">    │   ├── IGuideBookingService.cs
</span><span class="code-line">    │   ├── IPublishedTourRepository.cs
</span><span class="code-line">    │   ├── ISearchService.cs
</span><span class="code-line">    │   └── ISeatsPoolService.cs
</span><span class="code-line">    └── ActivatePublishedTourCommandHandler.cs
</span></code></pre></div></div><p>So nothing really changed, one could comment.</p><p>&quot;It&#x27;s just a naming, fool&quot;, some might say.</p><p>But <a href="https://talesfrom.dev/blog/the-ambiguity-of-naming">naming is framing</a>, when we see &quot;geotracking&quot; required capability, might it be that another team requires it also?</p><p>Might it be that we can reuse that capability in other contexts?</p><p>If not, what can we do to make it reusable?</p><p>If yes, why aren&#x27;t we doing it?</p><p>I am not saying about reusing that <a href="https://talesfrom.dev/blog/the-ambiguity-of-interfaces"><em>interface</em></a>, but reusing the <strong>capability</strong>.</p><p>Aligning the language used, possible web services providing that capability, and so on.</p><p>&quot;You say providers - how does it differ from services?&quot;, one might ask.</p><p>Well, as many concepts in our industry, &quot;service&quot; is an overloaded term.</p><p>Appearing on different levels of abstractions - an application level, an architecture level, a business level.</p><p>Many might hold an image of services having dozens of methods, exposing too big API surface, making them impossible to change.</p><p>I hope you know, dear Reader, I am more interested in <a href="https://talesfrom.dev/blog/the-ambiguity-of-interfaces">roles things play</a>.</p><p>And I am not the first one who tries to express an important role something plays by renaming it.</p><p>In COCOA, capabilities strive to emphasize the <a href="https://talesfrom.dev/blog/context-segregation-principles">contextual</a> behaviors.</p><p>Concepts aim at expressing <a href="https://talesfrom.dev/blog/context-segregation-principles">contextual</a> models.</p><p>Finally, providers embody &quot;the doers&quot;, but they shall come last in the whole process.</p><p>I only give it a name so that I can refer to it later.</p><p>It is a useful abstraction, a mental model, still being imperfect.</p><p>I don&#x27;t aim at building a school or a church around it - it&#x27;s goal is to help different reasoning.</p><h2 id="should-you-use-cocoa"><a href="#should-you-use-cocoa" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Should you use COCOA?</h2><p>When you get back to work, refactor all codebases, align with COCOA.</p><p>And give me fifty.</p><p>Ok, jokes aside.</p><p>I don&#x27;t know, dear Reader.</p><p>You might find it useful, or not.</p><p>COCOA doesn&#x27;t throw away isolating application logic from outside concerns, used to achieve testability, which is advocated by Ports &amp; Adapters and others.</p><p>COCOA doesn&#x27;t throw away locality of behavior, used to achieve high cohesion and evolvability, which is advocated by Vertical Slices.</p><p>COCOA doesn&#x27;t throw away segregation of models, used to achieve maintainability and flexibility, which is advocated by CQRS.</p><p>COCOA doesn&#x27;t throw away domain modeling, used to achieve alignment with business areas, which is advocated by Domain-Driven Design.</p><p>All of those abstract ideas need to live in the designer&#x27;s mind.</p><p>COCOA is a way of reasoning, nothing more, nothing less.</p><p>Expressing COCOA through code organization is just a way to express those ideas.</p><p>You can have a single file, having all of mentioned ideas, and COCOA will be there.</p><p>You can have a complex directory structure, and COCOA will appear again.</p><p>COCOA is in the eye of the beholder, same as a tree that falls in the forest, and no one is around to hear it.</p><p>Remember: <a href="https://talesfrom.dev/blog/systems-by-with-for-people">systems are built by, with and for people</a>.</p><p>Talk to your experts, collaborate with people - that&#x27;s what truly matters.</p><p>Happy building!</p>]]></content:encoded>
    <pubDate>Mon, 19 Jan 2026 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>application architecture</category><category>domain-driven design</category><category>language patterns</category><category>design patterns</category><category>object-oriented design</category><category>functional programming</category><category>software architecture</category><category>mental models</category><category>communication</category><category>knowledge working</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/consumer-expected-need-driven-behavior-development</guid>
    <title>Consumer-expected, need-driven behavior development</title>
    <link>https://talesfrom.dev/blog/consumer-expected-need-driven-behavior-development</link>
    <description>What can we learn from Toyota Production System?</description>
    <content:encoded><![CDATA[<div class="bg-slate-600 rounded-xl mb-8"><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>#1</span></div><div class="pb-2 px-3"><div class="break-words"><p>This article is based on <a href="https://talesfrom.dev/blog/the-invisible-role-switching-problem-and-need-driven-design">previous one</a> about the invisible role-switching problem and Need-Driven Design.</p>
<p>It is highly recommended to read it first, as it provides important context and background information.</p></div></div></div> <div class="bg-slate-600 rounded-xl "><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>#2</span></div><div class="pb-2 px-3"><div class="break-words"><p>This article tries to illustrate <a href="https://talesfrom.dev/blog/the-ambiguity-of-tdd">TDD</a>/<a href="https://talesfrom.dev/blog/tdd-specify-satisfy-simplify">3S</a> worfklow.</p>
<p>Please bear in mind that we&#x27;re simulating a worfklow that usually be pretty slick and smooth, considering the experience of the engineer.</p>
<p>Even though it might seem a bit verbose, heavy &quot;on the screen&quot;, all those small steps are usually done in seconds, sometimes even less.</p></div></div></div><h3 id="clean-slate"><a href="#clean-slate" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Clean slate</h3><p>Imagine that this time <span class="italic font-bold text-rose-400">Hank</span> is aware of the invisible role-switching problem and Need-Driven Design.</p><p>He also understands the important role of <a href="https://talesfrom.dev/blog/the-ambiguity-of-interfaces">interfaces</a>.</p><p>In this alternative round, he will undergo the same sequence of events: implementing a feature, an interruption, and then coming back to finish the feature.</p><p>This time, however, he will approach the task differently.</p><p>Nothing lives in the vacuum, so <span class="italic font-bold text-rose-400">Hank</span> asked his colleague <span class="italic font-bold text-lime-400">Tom</span> about the requirements, from the consumer perspective.</p><p><span class="italic font-bold text-lime-400">Tom</span> works on the web UI, so he will need to interact over HTTP with the web service to activate the tour.</p><p><span class="italic font-bold text-rose-400">Hank</span>, as a capability provider, asked about the front-end perspective, expected behavior and needs.</p><p>They agreed upon the following behavior:</p><ul><li>given a published tour does not exist, when activating it, then returns <code>404 Not Found</code></li><li>given a published tour exists, when activating it, then returns <code>200 OK</code> and activates the tour</li><li>given a published tour is already active, when activating it, then returns <code>409 Conflict</code></li></ul><p>Because they both are technical folks, they used <a href="https://talesfrom.dev/blog/language-of-the-problem">language of the problem</a> domain.</p><p>As this feature is not existing, they also agreed that a new endpoint will be created: <code>POST /tours/{tourId}/activate</code>.</p><p>Initially, to establish something working, both <span class="italic font-bold text-rose-400">Hank</span> and <span class="italic font-bold text-lime-400">Tom</span> decided to work on fake published tours - just to have something working end-to-end.</p><p>They mapped three identifiers to three different scenarios:</p><ul><li><code>tour-404</code> - non-existing published tour</li><li><code>tour-409</code> - already active published tour</li><li>any other identifier - inactive published tour</li></ul><h3 id="http-interaction---consumer-perspective"><a href="#http-interaction---consumer-perspective" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>HTTP interaction - consumer perspective</h3><p><span class="italic font-bold text-rose-400">Hank</span> started by specifying the expected behavior: <code>given a published tour does not exist, when activating it, then returns 404 Not Found</code>, from the consumer perspective, using tests.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span>
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">given_non_existing_published_tour_when_activating_it_then_returns_404</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// given</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> NON_EXISTING_TOUR_ID <span class="token operator">=</span> <span class="token string">&quot;tour-404&quot;</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> client <span class="token operator">=</span> PublishedToursWebService<span class="token punctuation">.</span><span class="token function">CreateHttpClient</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">// when</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> response <span class="token operator">=</span> <span class="token keyword">await</span> client<span class="token punctuation">.</span><span class="token function">PostAsync</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;/tours/</span><span class="token interpolation"><span class="token punctuation">{</span><span class="token language-csharp expression">NON_EXISTING_TOUR_ID</span><span class="token punctuation">}</span></span><span class="token string">/activate&quot;</span></span><span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token comment">// then</span>
</span><span class="code-line">    Assert<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span>HttpStatusCode<span class="token punctuation">.</span>NotFound<span class="token punctuation">,</span> response<span class="token punctuation">.</span>StatusCode<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>He ran it, which then failed, as expected.</p><p>&quot;Time to satisfy the specification&quot;, thought <span class="italic font-bold text-rose-400">Hank</span>.</p><p>&quot;But probably I should create an interface for repository to load published tours first?&quot;, he pondered.</p><p>&quot;Also, I know that there must be a geotracking session created when a tour is activated, so I should create an interface for that as well&quot;, he continued.</p><p>Fortunately, <span class="italic font-bold text-rose-400">Hank</span> read <a href="https://talesfrom.dev/blog/tdd-specify-satisfy-simplify">3S</a> article recently, so he decided to follow that workflow.</p><p>Simplify comes after satisfying the specification, so he focused on satisfying the specification first.</p><p>&quot;Maybe I could put the implementation next to the test, focusing on deliverying working behavior first?&quot;, he wondered.</p><p>By doing so, he enabled pretty fast feedback loop, as everything was in one place.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">PublishedToursWebService</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name return-type">WebApplicationFactory<span class="token punctuation">&lt;</span>Program<span class="token punctuation">&gt;</span></span> <span class="token function">WithPublishedToursActivation</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">WebApplicationFactory<span class="token punctuation">&lt;</span>Program<span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token punctuation">.</span><span class="token function">WithWebHostBuilder</span><span class="token punctuation">(</span>builder <span class="token operator">=&gt;</span>
</span><span class="code-line">            <span class="token punctuation">{</span>
</span><span class="code-line">                builder<span class="token punctuation">.</span><span class="token function">Configure</span><span class="token punctuation">(</span>app <span class="token operator">=&gt;</span>
</span><span class="code-line">                <span class="token punctuation">{</span>
</span><span class="code-line">                    app<span class="token punctuation">.</span><span class="token function">MapPost</span><span class="token punctuation">(</span><span class="token string">&quot;/tours/{tourId}/activate&quot;</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> tourId<span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
</span><span class="code-line">                    <span class="token punctuation">{</span>
</span><span class="code-line">                        <span class="token keyword">if</span> <span class="token punctuation">(</span>tourId <span class="token operator">==</span> <span class="token string">&quot;tour-404&quot;</span><span class="token punctuation">)</span>
</span><span class="code-line">                        <span class="token punctuation">{</span>
</span><span class="code-line">                            <span class="token keyword">return</span> Results<span class="token punctuation">.</span><span class="token function">NotFound</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">                        <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">                        <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">NotImplementedException</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">                    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">                <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>The specification through test was still failing, but now <span class="italic font-bold text-rose-400">Hank</span> had a working implementation to build upon, so he adjusted the test to use this handly, local <code>WebApplicationFactory</code>.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span>
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">given_non_existing_published_tour_when_activating_it_then_returns_404</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// given</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> NON_EXISTING_TOUR_ID <span class="token operator">=</span> <span class="token string">&quot;tour-404&quot;</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> client <span class="token operator">=</span> PublishedToursWebService
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">WithPublishedToursActivation</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">CreateHttpClient</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    
</span><span class="code-line">    <span class="token comment">// when</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> response <span class="token operator">=</span> <span class="token keyword">await</span> client<span class="token punctuation">.</span><span class="token function">PostAsync</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;/tours/</span><span class="token interpolation"><span class="token punctuation">{</span><span class="token language-csharp expression">NON_EXISTING_TOUR_ID</span><span class="token punctuation">}</span></span><span class="token string">/activate&quot;</span></span><span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token comment">// then</span>
</span><span class="code-line">    Assert<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span>HttpStatusCode<span class="token punctuation">.</span>NotFound<span class="token punctuation">,</span> response<span class="token punctuation">.</span>StatusCode<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>After running the test, it passed successfully.</p><h3 id="http-interaction---next-specifications"><a href="#http-interaction---next-specifications" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>HTTP interaction - next specifications</h3><p>So now it is the time to decide: specify further or simplify?</p><p>Remember dear Reader, that <a href="https://talesfrom.dev/blog/tdd-specify-satisfy-simplify--simplify">simplification</a> also means cleaning up, refactoring, improving the design.</p><p><span class="italic font-bold text-rose-400">Hank</span> decided to move on with progressing on provided capability of activating published tours.</p><p>He proceeded to the next specification: <code>given a published tour is already active, when activating it, then returns 409 Conflict</code>.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span>
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">given_already_active_published_tour_when_activating_it_then_returns_409</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// given</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> ALREADY_ACTIVE_TOUR_ID <span class="token operator">=</span> <span class="token string">&quot;tour-409&quot;</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> client <span class="token operator">=</span> PublishedToursWebService
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">WithPublishedToursActivation</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">CreateHttpClient</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">// when</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> response <span class="token operator">=</span> <span class="token keyword">await</span> client<span class="token punctuation">.</span><span class="token function">PostAsync</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;/tours/</span><span class="token interpolation"><span class="token punctuation">{</span><span class="token language-csharp expression">ALREADY_ACTIVE_TOUR_ID</span><span class="token punctuation">}</span></span><span class="token string">/activate&quot;</span></span><span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token comment">// then</span>
</span><span class="code-line">    Assert<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span>HttpStatusCode<span class="token punctuation">.</span>Conflict<span class="token punctuation">,</span> response<span class="token punctuation">.</span>StatusCode<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>He ran it, which then failed, as expected.</p><p>&quot;Time to satisfy the specification&quot;, thought <span class="italic font-bold text-rose-400">Hank</span> again.</p><p>He went to newly added local implementation and added the necessary logic to satisfy the specification.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line">app<span class="token punctuation">.</span><span class="token function">MapPost</span><span class="token punctuation">(</span><span class="token string">&quot;/tours/{tourId}/activate&quot;</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> tourId<span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">if</span> <span class="token punctuation">(</span>tourId <span class="token operator">==</span> <span class="token string">&quot;tour-404&quot;</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">return</span> Results<span class="token punctuation">.</span><span class="token function">NotFound</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">if</span> <span class="token punctuation">(</span>tourId <span class="token operator">==</span> <span class="token string">&quot;tour-409&quot;</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">return</span> Results<span class="token punctuation">.</span><span class="token function">Conflict</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">NotImplementedException</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre></div></div><p>After executing the specification through test, it passed successfully.</p><p>Satisfy or simplify?</p><p><span class="italic font-bold text-rose-400">Hank</span> decided to proceed with the last specification: <code>given a published tour exists, when activating it, then returns 200 OK and activates the tour</code>.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Theory</span></span><span class="token punctuation">]</span>
</span><span class="code-line"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">InlineData</span><span class="token attribute-arguments"><span class="token punctuation">(</span><span class="token string">&quot;tour-123&quot;</span><span class="token punctuation">)</span></span></span><span class="token punctuation">]</span>
</span><span class="code-line"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">InlineData</span><span class="token attribute-arguments"><span class="token punctuation">(</span><span class="token string">&quot;tour-xyz&quot;</span><span class="token punctuation">)</span></span></span><span class="token punctuation">]</span>
</span><span class="code-line"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">InlineData</span><span class="token attribute-arguments"><span class="token punctuation">(</span><span class="token string">&quot;tour-abc&quot;</span><span class="token punctuation">)</span></span></span><span class="token punctuation">]</span>
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">given_existing_published_tour_when_activating_it_then_returns_200_and_activates_tour</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> EXISTING_TOUR_ID<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// given</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> client <span class="token operator">=</span> PublishedToursWebService
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">WithPublishedToursActivation</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">CreateHttpClient</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    
</span><span class="code-line">    <span class="token comment">// when</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> response <span class="token operator">=</span> <span class="token keyword">await</span> client<span class="token punctuation">.</span><span class="token function">PostAsync</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;/tours/</span><span class="token interpolation"><span class="token punctuation">{</span><span class="token language-csharp expression">EXISTING_TOUR_ID</span><span class="token punctuation">}</span></span><span class="token string">/activate&quot;</span></span><span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token comment">// then</span>
</span><span class="code-line">    Assert<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span>HttpStatusCode<span class="token punctuation">.</span>OK<span class="token punctuation">,</span> response<span class="token punctuation">.</span>StatusCode<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>He ran it, which then failed, as expected.</p><p>&quot;Time to satisfy the specification&quot;, thought <span class="italic font-bold text-rose-400">Hank</span> once more.</p><p>Yet again, he jumped to HTTP handler developed locally, close to the specification, and added the necessary logic to satisfy the specification.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line">app<span class="token punctuation">.</span><span class="token function">MapPost</span><span class="token punctuation">(</span><span class="token string">&quot;/tours/{tourId}/activate&quot;</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> tourId<span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">if</span> <span class="token punctuation">(</span>tourId <span class="token operator">==</span> <span class="token string">&quot;tour-404&quot;</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">return</span> Results<span class="token punctuation">.</span><span class="token function">NotFound</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">if</span> <span class="token punctuation">(</span>tourId <span class="token operator">==</span> <span class="token string">&quot;tour-409&quot;</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">return</span> Results<span class="token punctuation">.</span><span class="token function">Conflict</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">return</span> Results<span class="token punctuation">.</span><span class="token function">Ok</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre></div></div><p>All specifications were green!</p><h3 id="simplify"><a href="#simplify" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Simplify!</h3><p>Ok, now it order to expose the capability properly, <span class="italic font-bold text-rose-400">Hank</span> needed to move the implementation from local, test project to the actual web service project.</p><p>So he took the implementation from local HTTP handler and moved it to <code>Program.cs</code>, which is kind of copy-and-paste operation (or if you prefer, dear Reader, IDE shortcut acrobatics).</p><p>He ran all specs, which were still green.</p><p><span class="italic font-bold text-rose-400">Hank</span> also removed unused <code>WithPublishedToursActivation</code> which stopped being used.</p><p>Specs executed again, still green.</p><p>&quot;Any further simplifying possible?&quot;, wondered <span class="italic font-bold text-rose-400">Hank</span>.</p><p>He decied that this capability, even though not completely ready, is good enough for <span class="italic font-bold text-rose-400">Tom</span> to start using it and getting feedback.</p><p>Changes were intergrated with the main branch which then got deployed to dev environment.</p><p>His UI development comrade, <span class="italic font-bold text-lime-400">Tom</span>, was able to start using the new endpoint right away, simulating different scenarios using the agreed-upon identifiers.</p><p>&quot;Pushing unfinished work?&quot;, others were not so sure about it.</p><p>&quot;It literally makes no sense to ship some mocked behavior to dev environment, doesn&#x27;t it?&quot;, some were wondering.</p><h3 id="interrupting-interrupting-never-changes"><a href="#interrupting-interrupting-never-changes" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Interrupting, interrupting never changes?</h3><p>As we know from <a href="https://talesfrom.dev/blog/the-invisible-role-switching-problem-and-need-driven-design">previous article</a>, interruptions are part of software development life (is it normal? you might be interested in <a href="https://talesfrom.dev/blog/the-ambiguity-of-team-work">The ambiguity of team work</a> article).</p><p><span class="italic font-bold text-rose-400">Hank</span> was asked to write a documentation related to migrations.</p><p>He postponed the published tours activation feature and focused on writing the documentation.</p><p>During his documentation writing, <span class="italic font-bold text-lime-400">Tom</span> was able to progress with the UI part of the feature.</p><p>Let&#x27;s imagine that <span class="italic font-bold text-rose-400">Hank</span> finished the documentation and got back to his work on published tours activation feature.</p><p>Three specifications were already in place, driven by the capability-exposed-over-HTTP consumer perspective.</p><p>Current implementation is quite, faked, if we could say so.</p><p><span class="italic font-bold text-rose-400">Hank</span> faked it up to the point where he could share results of his work with <span class="italic font-bold text-lime-400">Tom</span> as soon as possible.</p><p>Now it&#x27;s time to put a designer&#x27;s hat and think about the system needs - deciding whether published tour exists, whether it is active - won&#x27;t be purely based on input identifier.</p><p>This information will come from some durable place, possibly.</p><p>Currently, the system uses Postgres database, so probably that would be a good place to start.</p><p>But wait a sec - is this knowledge easily available for HTTP handler? Hm, no. It is not.</p><p><span class="italic font-bold text-rose-400">Hank</span> played a role of the system designer for a while, now it&#x27;s capability provider turn - HTTP handler...</p><p>...Which actually becomes a consumer, requiring a capability for loading published tours.</p><p>As <span class="italic font-bold text-rose-400">Hank</span> framed his reasoning by &quot;becoming&quot; a HTTP handler, he can specify the needs in the form of a required capability.</p><p>This specification happens in the test, of course.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span>
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">given_non_existing_published_tour_when_activating_it_then_returns_404</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// given</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> NON_EXISTING_TOUR_ID <span class="token operator">=</span> <span class="token string">&quot;tour-404&quot;</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> publishedTourRepository <span class="token operator">=</span> Substitute<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">For</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>IGetPublishedTour<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// ❌ bzzzzzt, does not compile!</span>
</span><span class="code-line">    publishedTourRepository
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">GetPublishedTourById</span><span class="token punctuation">(</span>NON_EXISTING_TOUR_ID<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">Returns</span><span class="token punctuation">(</span>Task<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">FromResult</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>PublishedTourToActivate<span class="token punctuation">?</span><span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// ❌ bzzzzzt, does not compile!</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> client <span class="token operator">=</span> PublishedToursWebService
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">WithFake</span><span class="token punctuation">(</span>publishedTourRepository<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">CreateHttpClient</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">// when</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> response <span class="token operator">=</span> <span class="token keyword">await</span> client<span class="token punctuation">.</span><span class="token function">PostAsync</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;/tours/</span><span class="token interpolation"><span class="token punctuation">{</span><span class="token language-csharp expression">NON_EXISTING_TOUR_ID</span><span class="token punctuation">}</span></span><span class="token string">/activate&quot;</span></span><span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    
</span><span class="code-line">    <span class="token comment">// then</span>
</span><span class="code-line">    Assert<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span>HttpStatusCode<span class="token punctuation">.</span>NotFound<span class="token punctuation">,</span> response<span class="token punctuation">.</span>StatusCode<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>He tried running it, but it did not even compile!</p><p>Now, <span class="italic font-bold text-rose-400">Hank</span>-the-HTTP-handler definitely has a proper demand to require this interface (a capability) to be produced.</p><p>In a way, it gets pulled into existence by the HTTP handler&#x27;s need.</p><p>To tighten the feedback loop, it gets added in the same test project, close to the specification.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">IGetPublishedTour</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>PublishedTourToActivate<span class="token punctuation">?</span><span class="token punctuation">&gt;</span></span> <span class="token function">GetPublishedTourById</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> tourId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">record</span> <span class="token class-name">PublishedTourToActivate</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> Id<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">bool</span></span> IsActive<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre></div></div><p>Now, at least it compiles.</p><p>But there&#x27;s one important detail to consider - from the HTTP handler perspective, coordinating the workflow, whenever a published tour cannot be activated, nothing should be saved.</p><p>Shouldn&#x27;t this be specified as well?</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span>
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">given_non_existing_published_tour_when_activating_it_then_returns_404</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// given</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> NON_EXISTING_TOUR_ID <span class="token operator">=</span> <span class="token string">&quot;tour-404&quot;</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> publishedTourRepository <span class="token operator">=</span> Substitute<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">For</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>PublishedToursRepository<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 👈 new interface!</span>
</span><span class="code-line">    publishedTourRepository
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">GetPublishedTourById</span><span class="token punctuation">(</span>NON_EXISTING_TOUR_ID<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">Returns</span><span class="token punctuation">(</span>Task<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">FromResult</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>PublishedTourToActivate<span class="token punctuation">?</span><span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> client <span class="token operator">=</span> PublishedToursWebService
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">WithFake</span><span class="token punctuation">(</span>publishedTourRepository<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">CreateHttpClient</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">// when</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> response <span class="token operator">=</span> <span class="token keyword">await</span> client<span class="token punctuation">.</span><span class="token function">PostAsync</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;/tours/</span><span class="token interpolation"><span class="token punctuation">{</span><span class="token language-csharp expression">NON_EXISTING_TOUR_ID</span><span class="token punctuation">}</span></span><span class="token string">/activate&quot;</span></span><span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">// then</span>
</span><span class="code-line">    Assert<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span>HttpStatusCode<span class="token punctuation">.</span>NotFound<span class="token punctuation">,</span> response<span class="token punctuation">.</span>StatusCode<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">await</span> publishedTourRepository
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">DidNotReceive</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>Arg<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Is</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>PublishedTourToActivate<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span>x <span class="token operator">=&gt;</span> x<span class="token punctuation">.</span>Id <span class="token operator">==</span> NON_EXISTING_TOUR_ID <span class="token operator">&amp;&amp;</span> x<span class="token punctuation">.</span>IsActive <span class="token operator">==</span> <span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 👈 new expectation which does not compile ❌!</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>There is a new demand, time to pull, again.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">ISavePublishedTour</span> <span class="token comment">// 👈 new capability added!</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name return-type">Task</span> <span class="token function">Save</span><span class="token punctuation">(</span><span class="token class-name">PublishedTourToActivate</span> publishedTour<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">PublishedToursRepository</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">IGetPublishedTour</span><span class="token punctuation">,</span> <span class="token class-name">ISavePublishedTour</span></span><span class="token punctuation">;</span>
</span></code></pre></div></div><p>Now everything compiles again.</p><p>He runs the specification, which fails, as expected.</p><p>&quot;Time to satisfy the specification&quot;, thought <span class="italic font-bold text-rose-400">Hank</span> yet again.</p><h3 id="specify-satisfy-simplify---round-two"><a href="#specify-satisfy-simplify---round-two" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Specify, satisfy, simplify - round two</h3><p>He jumped to the HTTP handler implementation and added the necessary logic to satisfy the specification.</p><p>Before doing so, this <code>PublishedToursRepository</code> needed to be moved into <code>Program.cs</code> file to make it compile.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line">app<span class="token punctuation">.</span><span class="token function">MapPost</span><span class="token punctuation">(</span><span class="token string">&quot;/tours/{tourId}/activate&quot;</span><span class="token punctuation">,</span> <span class="token keyword">async</span> <span class="token punctuation">(</span>
</span><span class="code-line">    <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">FromRoute</span></span><span class="token punctuation">]</span> <span class="token class-name"><span class="token keyword">string</span></span> tourId<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">FromServices</span></span><span class="token punctuation">]</span> <span class="token class-name">PublishedToursRepository</span> publishedTourRepository
</span><span class="code-line"><span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> publishedTour <span class="token operator">=</span> <span class="token keyword">await</span> publishedTourRepository<span class="token punctuation">.</span><span class="token function">GetPublishedTourById</span><span class="token punctuation">(</span>tourId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">if</span> <span class="token punctuation">(</span>publishedTour <span class="token keyword">is</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">return</span> Results<span class="token punctuation">.</span><span class="token function">NotFound</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">if</span> <span class="token punctuation">(</span>tourId <span class="token operator">==</span> <span class="token string">&quot;tour-409&quot;</span><span class="token punctuation">)</span> <span class="token comment">// 👈 this remained untouched</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">return</span> Results<span class="token punctuation">.</span><span class="token function">Conflict</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">await</span> publishedTourRepository<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>publishedTour <span class="token keyword">with</span> <span class="token punctuation">{</span> IsActive <span class="token operator">=</span> <span class="token boolean">true</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">return</span> Results<span class="token punctuation">.</span><span class="token function">Ok</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 👈 this remained untouched</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre></div></div><p>After executing the specification through test, it passed successfully.</p><p><span class="italic font-bold text-rose-400">Hank</span> decided to use &quot;manual mutation testing&quot; to verify the usefulness of the newly added specifications.</p><p>He manually changed <code>publishedTour is null</code> check to <code>publishedTour is not null</code> in the HTTP handler implementation.</p><p>Executed specification fails, as expected.</p><p>He reverts the change, runs specifications again, which pass successfully.</p><p><span class="italic font-bold text-rose-400">Hank</span> asks himself: &quot;Any simplifying possible?&quot;</p><p>He decided that for now, the design is good enough.</p><p>He specifies, satisfies the remaining two specifications - the good part is that no more things needs to be pulled into existence, as the necessary capabilities are already in place.</p><p><span class="italic font-bold text-rose-400">Hank</span>-the-HTTP-handler is satisfied.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line">app<span class="token punctuation">.</span><span class="token function">MapPost</span><span class="token punctuation">(</span><span class="token string">&quot;/tours/{tourId}/activate&quot;</span><span class="token punctuation">,</span> <span class="token keyword">async</span> <span class="token punctuation">(</span>
</span><span class="code-line">    <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">FromRoute</span></span><span class="token punctuation">]</span> <span class="token class-name"><span class="token keyword">string</span></span> tourId<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">FromServices</span></span><span class="token punctuation">]</span> <span class="token class-name">PublishedToursRepository</span> publishedTourRepository
</span><span class="code-line"><span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> publishedTour <span class="token operator">=</span> <span class="token keyword">await</span> publishedTourRepository<span class="token punctuation">.</span><span class="token function">GetPublishedTourById</span><span class="token punctuation">(</span>tourId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">if</span> <span class="token punctuation">(</span>publishedTour <span class="token keyword">is</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">return</span> Results<span class="token punctuation">.</span><span class="token function">NotFound</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">if</span> <span class="token punctuation">(</span>tourId<span class="token punctuation">.</span>IsActive<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">return</span> Results<span class="token punctuation">.</span><span class="token function">Conflict</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">await</span> publishedTourRepository<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>publishedTour <span class="token keyword">with</span> <span class="token punctuation">{</span> IsActive <span class="token operator">=</span> <span class="token boolean">true</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">return</span> Results<span class="token punctuation">.</span><span class="token function">Ok</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre></div></div><p>The capability is not yet complete, as the actual implementation of <code>PublishedToursRepository</code> is still missing.</p><p>The good part is that the contract between a potential provider was already specified using consumer-expected, need-driven approach.</p><p>Let&#x27;s make a pause and ask ourselves, dear Reader: why are we saving anything to durable storage at all?</p><p>Probably to read it later, right?</p><p><span class="italic font-bold text-rose-400">Hank</span>-the-designer ponders about it and decided to specify another case: <code>given an existing published tour that was just activated, when getting it, then returns published tour with active status</code>.</p><p>He wants to use testcontainers to have a real Postgres database for this specification, as he (in the designer&#x27;s role) wants to pull a new capability provider into existence: <code>PostgresPublishedToursRepository</code>.</p><p>Let&#x27;s imagine he did so and tests use real database now, and he&#x27;s ready to specify the behavior.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span>
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">given_existing_published_tour_that_was_just_activated_when_getting_it_then_returns_published_tour_with_active_status</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// given</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> EXISTING_TOUR_ID <span class="token operator">=</span> <span class="token string">&quot;tour-123&quot;</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> client <span class="token operator">=</span> PublishedToursWebService<span class="token punctuation">.</span><span class="token function">CreateHttpClient</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> tourToPublish <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">StringContent</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$@&quot;{{
</span></span></span><span class="code-line"><span class="token interpolation-string"><span class="token string">        &quot;&quot;Id&quot;&quot;: &quot;&quot;</span><span class="token interpolation"><span class="token punctuation">{</span><span class="token language-csharp expression">EXISTING_TOUR_ID</span><span class="token punctuation">}</span></span><span class="token string">&quot;&quot;,
</span></span></span><span class="code-line"><span class="token interpolation-string"><span class="token string">        &quot;&quot;IsActive&quot;&quot;: false,
</span></span></span><span class="code-line"><span class="token interpolation-string"><span class="token string">        &quot;&quot;PublishedAt&quot;&quot;: &quot;&quot;2023-01-01T00:00:00Z&quot;&quot;,
</span></span></span><span class="code-line"><span class="token interpolation-string"><span class="token string">        &quot;&quot;Title&quot;&quot;: &quot;&quot;Sample Tour&quot;&quot;,
</span></span></span><span class="code-line"><span class="token interpolation-string"><span class="token string">        &quot;&quot;Description&quot;&quot;: &quot;&quot;This is a sample tour.&quot;&quot;,
</span></span></span><span class="code-line"><span class="token interpolation-string"><span class="token string">        &quot;&quot;TourPlannerId&quot;&quot;: &quot;&quot;planner-001&quot;&quot;
</span></span></span><span class="code-line"><span class="token interpolation-string"><span class="token string">    }}&quot;</span></span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    _ <span class="token operator">=</span> <span class="token keyword">await</span> client<span class="token punctuation">.</span><span class="token function">PostAsync</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;/tours/&quot;</span></span><span class="token punctuation">,</span> tourToPublish<span class="token punctuation">,</span> Encoding<span class="token punctuation">.</span>UTF8<span class="token punctuation">,</span> <span class="token string">&quot;application/json&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    _ <span class="token operator">=</span> <span class="token keyword">await</span> client<span class="token punctuation">.</span><span class="token function">PostAsync</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;/tours/</span><span class="token interpolation"><span class="token punctuation">{</span><span class="token language-csharp expression">EXISTING_TOUR_ID</span><span class="token punctuation">}</span></span><span class="token string">/activate&quot;</span></span><span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">// when</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> response <span class="token operator">=</span> <span class="token keyword">await</span> client<span class="token punctuation">.</span><span class="token function">GetAsync</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;/tours/</span><span class="token interpolation"><span class="token punctuation">{</span><span class="token language-csharp expression">EXISTING_TOUR_ID</span><span class="token punctuation">}</span></span><span class="token string">&quot;</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> responseBody <span class="token operator">=</span> <span class="token keyword">await</span> response<span class="token punctuation">.</span>Content<span class="token punctuation">.</span><span class="token function">ReadAsStringAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">// then</span>
</span><span class="code-line">    Assert<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span>HttpStatusCode<span class="token punctuation">.</span>OK<span class="token punctuation">,</span> response<span class="token punctuation">.</span>StatusCode<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    Assert<span class="token punctuation">.</span><span class="token function">Contains</span><span class="token punctuation">(</span><span class="token string">@&quot;&quot;&quot;IsActive&quot;&quot;:true&quot;</span><span class="token punctuation">,</span> responseBody<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>A capability for publishing tour was already in place, so <span class="italic font-bold text-rose-400">Hank</span> used it to set up the scenario.</p><p>The entire spec, after running, failed, as expected.</p><p>The real demand is there - time to pull into the existence a Postgres provider for the capability for loading published tours awaiting activation and saving them after activation.</p><p>This means that now it&#x27;s specification satisfaction time again.</p><p>For a while, <span class="italic font-bold text-rose-400">Hank</span> started playing a role of a capability provider - <code>PublishedToursRepository</code> - using Postgres and having the necessary knowledge to only satisfy the current needs, specified by the contract which got designed with consumer feedback.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">PostgresPublishedToursRepository</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">PublishedToursRepository</span></span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">private</span> <span class="token keyword">readonly</span> <span class="token class-name"><span class="token keyword">string</span></span> _connectionString<span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token function">PostgresPublishedToursRepository</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> connectionString<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        _connectionString <span class="token operator">=</span> connectionString<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>PublishedTourToActivate<span class="token punctuation">?</span><span class="token punctuation">&gt;</span></span> <span class="token function">GetPublishedTourById</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> tourId<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">await</span> <span class="token keyword">using</span> <span class="token class-name"><span class="token keyword">var</span></span> connection <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">NpgsqlConnection</span><span class="token punctuation">(</span>_connectionString<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">await</span> connection<span class="token punctuation">.</span><span class="token function">OpenAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> command <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">NpgsqlCommand</span><span class="token punctuation">(</span><span class="token string">&quot;SELECT Id, IsActive FROM PublishedTours WHERE Id = @Id&quot;</span><span class="token punctuation">,</span> connection<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        command<span class="token punctuation">.</span>Parameters<span class="token punctuation">.</span><span class="token function">AddWithValue</span><span class="token punctuation">(</span><span class="token string">&quot;Id&quot;</span><span class="token punctuation">,</span> tourId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token keyword">await</span> <span class="token keyword">using</span> <span class="token class-name"><span class="token keyword">var</span></span> reader <span class="token operator">=</span> <span class="token keyword">await</span> command<span class="token punctuation">.</span><span class="token function">ExecuteReaderAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">await</span> reader<span class="token punctuation">.</span><span class="token function">ReadAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">PublishedTourToActivate</span><span class="token punctuation">(</span>
</span><span class="code-line">                reader<span class="token punctuation">.</span><span class="token function">GetString</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
</span><span class="code-line">                reader<span class="token punctuation">.</span><span class="token function">GetBoolean</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token keyword">return</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">Save</span><span class="token punctuation">(</span><span class="token class-name">PublishedTourToActivate</span> publishedTour<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">await</span> <span class="token keyword">using</span> <span class="token class-name"><span class="token keyword">var</span></span> connection <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">NpgsqlConnection</span><span class="token punctuation">(</span>_connectionString<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">await</span> connection<span class="token punctuation">.</span><span class="token function">OpenAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> command <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">NpgsqlCommand</span><span class="token punctuation">(</span><span class="token string">&quot;UPDATE PublishedTours SET IsActive = @IsActive WHERE Id = @Id&quot;</span><span class="token punctuation">,</span> connection<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        command<span class="token punctuation">.</span>Parameters<span class="token punctuation">.</span><span class="token function">AddWithValue</span><span class="token punctuation">(</span><span class="token string">&quot;Id&quot;</span><span class="token punctuation">,</span> publishedTour<span class="token punctuation">.</span>Id<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        command<span class="token punctuation">.</span>Parameters<span class="token punctuation">.</span><span class="token function">AddWithValue</span><span class="token punctuation">(</span><span class="token string">&quot;IsActive&quot;</span><span class="token punctuation">,</span> publishedTour<span class="token punctuation">.</span>IsActive<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token keyword">await</span> command<span class="token punctuation">.</span><span class="token function">ExecuteNonQueryAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p><span class="italic font-bold text-rose-400">Hank</span>-the-postgres-capability-provider did only the required work to adhere to the contract - nothing more, nothing less.</p><p>&quot;There is no waste here&quot;, he thought.</p><p><span class="italic font-bold text-rose-400">Hank</span>-the-designer added this newly pulled capability provider to a dependency register in <code>Program.cs</code>.</p><p>All specs were executed, which passed successfully.</p><p>He started simplifying the design and structure, organizing types, files here and there, running specs after each change to ensure everything is still green.</p><h3 id="specify-satisfydeploy"><a href="#specify-satisfydeploy" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Specify, satisfy...Deploy!</h3><p><span class="italic font-bold text-rose-400">Hank</span>-the-designer decided that the design is good enough for now.</p><p>There is no need to pull more concepts into existence at this point, like application services or other contructs.</p><p>It will be unnecessary work at this moment - &quot;waste&quot;.</p><p>He decided to push the changes to main branch, which then got deployed to staging environment.</p><p><span class="italic font-bold text-lime-400">Tom</span> was able to use the real implementation of published tours activation right away, testing it end-to-end with the UI.</p><p>Almost no changes were required, as the contract remained unchanged.</p><p>Of course, <span class="italic font-bold text-rose-400">Hank</span> recalled that there&#x27;s a need for geotracking session creation when a tour is activated.</p><p>He decided to specify it next, following the same workflow of consumer-expected, need-driven behavior development.</p><p>Satisfy, satisfy, maybe simplify, and then deploy!</p><h3 id="consumers-needs-capabilities-providers"><a href="#consumers-needs-capabilities-providers" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Consumers, needs, capabilities, providers</h3><p>&quot;What the heck just happened?&quot;, you might be wondering, dear Reader.</p><p>One might say that the entire tale was very boilerplate-y, especially the parts about specifying, satisfying, simplifying.</p><p>During that tale and various checkpoints, we were able to see how <span class="italic font-bold text-rose-400">Hank</span> switched roles multiple times:</p><ul><li>from a capability consumer (HTTP handler) specifying needs for loading and saving published tours</li><li>to a capability provider (PublishedToursRepository) satisfying those needs using Postgres</li><li>to a system designer, pulling into existence the necessary capabilities to satisfy the system needs</li><li>back to a capability consumer (HTTP handler) using those capabilities to provide the expected behavior over HTTP</li><li>and so on...</li></ul><p>Typically, those role switches are invisible, happening in the mind of the engineer.</p><p>Which actually, might be pretty dangerous as we might bake wrong assumptions about the needs, expected behavior, capabilities, and so on.</p><p>That&#x27;s what we explored in the <a href="https://talesfrom.dev/blog/the-invisible-role-switching-problem-and-need-driven-design">previous article</a>, dear Reader.</p><p>It might not be explicitly visible, but along the way, we were able to see Lean principles in action.</p><p>In the <a href="http://jmock.org/oopsla2004.pdf">&quot;Mock Roles, Not Objects&quot;</a> paper, the authors mention:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>A core principle of Lean Development is that value should be
<strong>pulled into existence from demand</strong>, rather than pushed from
implementation: “The effect of &#x27;pull&#x27; is that production is not
based on forecast; <strong>commitment is delayed until demand is present
to indicate what the customer really wants.</strong>” [16].</p></div></div></div><p>Waste-reduction at its essence, isn&#x27;t it, dear Reader?</p><p>They continue by stating:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p><strong>TDD with Mock Objects guides
interface design by the services that an object requires, not just
those it provides</strong>. This process results in a system of narrow
interfaces each of which defines a role in an interaction between
objects, rather than wide interfaces that describe all the features
provided by a class. We call this approach <strong>Need-Driven
Development</strong>.</p></div></div></div><p>Which is exactly what we were able to observe in action - focusing on the required capabilities, driven by the consumer-expected needs.</p><p>It does not matter if the consumer was HTTP handler, <span class="italic font-bold text-lime-400">Tom</span> or an executable specification (test).</p><p>Providers treated those needs seriously, satisfying them with minimal effort, avoiding waste.</p><p>Everything was driven by the rapid feedback loop - either through tests or end-to-end usage.</p><p>By shipping &quot;a walking skeleton&quot;, <span class="italic font-bold text-rose-400">Hank</span> enabled early learning, reducing the risk of building something nobody needs, as <span class="italic font-bold text-lime-400">Tom</span> was able to start using the feature right away, providing that valuable feedback.</p><p>Tests were the first consumers of the contracts, behaviors and results - they were the foundation of fast feedback loop.</p><p>They were used as a design tool.</p><p>Tests are multipurpose, hence they might feel a bit <a href="https://talesfrom.dev/blog/the-ambiguity-of-tdd">ambiguous</a>.</p><p>As authors of <a href="http://jmock.org/oopsla2004.pdf">&quot;Mock Roles, Not Objects&quot;</a> paper put it:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Using TDD has many benefits but the most relevant is that it
directs the programmer to think about the design of code from its
intended use, rather than from its implementation.</p></div></div></div><p>&quot;But Hank did not follow any modern application architecture like Clean Architecture!&quot;, some might say.</p><p>Where is the problem? <span class="italic font-bold text-rose-400">Hank</span> focused on delivering value and he mindfully decided not to pull unnecessary concepts into existence while going through simplifying stage.</p><p>It&#x27;s not the implementation that is the real treasure, but specifications, especially in the AI times.</p><p>What would be the required effort for creating <code>TourActivationService</code> or <code>ActivatePublishedTourCommandHandler</code>?</p><p>Executable specifications are there, it will be pretty safe to pull them into existence, if there will be a need - for instance when a reader (another consumer) will find it difficult to understand, because there will be HTTP-related noise.</p><p>What is truly important and huge is that through entire tale a miracle of &quot;interface discovery&quot; happened - <span class="italic font-bold text-rose-400">Hank</span>-the-designer used mocking (a process) to purposefully establish boundaries and specify contracts that were required from consumer perspectives.</p><p>One might aim at ending up with a Ports &amp; Adapters architecture or Clean Architecture, but those are the final state.</p><p>We saw in the <a href="https://talesfrom.dev/blog/the-invisible-role-switching-problem-and-need-driven-design">previous article</a> the Inside-Out approach for development - quite speculative - which does not leave space for discovery, learning and adaptation.</p><p><a href="http://jmock.org/oopsla2004.pdf">&quot;Mock Roles, Not Objects&quot;</a> also captures the difference between provider-driven and consumer-driven approaches:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>This changes design from a process of <em>invention</em>, where the
developer thinks hard about what a unit of code should do and
then implements it, to a process of <em>discovery</em>, where the developer
adds small increments of functionality and then extracts structure
from the working code.</p></div></div></div><p>Throughtout the entire tale, we experienced Outside-In approach for development, driven by consumer-expected needs.</p><p>It was a designer&#x27;s decision <strong>when</strong> it is a right moment to pull new concepts into existence.</p><p><strong>When</strong> and <strong>where</strong> the boundaries should be established.</p><h3 id="why-so-slow"><a href="#why-so-slow" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Why so slow?</h3><p>You might be wondering, dear Reader, why the entire process seemed so slow and verbose.</p><p>&quot;All those microsteps, small refactoring activities, tiny ifs - do I really need to do that?&quot;, you might be asking, dear Reader.</p><p>The answer is: it depends.</p><p>It depends on how confident you feel about making larger steps.</p><p>If one struggles with making tests green - take smaller steps.</p><p>Edit a variable name, run tests.</p><p>Extract method, run tests.</p><p>Change place of an if, run tests.</p><p>Feeling more confident?</p><p>Add more logic - order interactions in a new sequence, add conditionals - run tests.</p><p>Distribute responsibilities, move things around - run tests.</p><p>Suddenly you feel you lost control? Make smaller steps again.</p><p>Watch for absolutisms - the beauty of being a human is that we can adapt, learn and change our minds.</p><p>Slowly roll out requirements, based on the needs and provide those capabilities, simplifying along the way.</p><p>And it does not really matter whether we are providing capabilities for human beings, other systems or tiny objects - outside-in perspective remains the same.</p><p>Who is the consumer?</p><p>What are the needs?</p><p>What capabilities are required to satisfy those needs?</p><p>And so on.</p><p>Happy designing, dear Reader!</p>]]></content:encoded>
    <pubDate>Wed, 07 Jan 2026 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>software engineering</category><category>software design</category><category>object-oriented design</category><category>modularity</category><category>design patterns</category><category>language patterns</category><category>software quality</category><category>knowledge working</category><category>modularity</category><category>modular monolith</category><category>boundaries</category><category>behavior specification</category><category>collaboration</category><category>concurrency</category><category>optimistic concurrency</category><category>composability</category><category>collaborative modelling</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/the-invisible-role-switching-problem-and-need-driven-design</guid>
    <title>The invisible role-switching problem and Need-Driven Design</title>
    <link>https://talesfrom.dev/blog/the-invisible-role-switching-problem-and-need-driven-design</link>
    <description>What is really challenging in software design?</description>
    <content:encoded><![CDATA[<h3 id="application-logic---implementers-perspective"><a href="#application-logic---implementers-perspective" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Application logic - implementer&#x27;s perspective</h3><p>Imagine that there&#x27;s a developer named <span class="italic font-bold text-rose-400">Hank</span>, working in a local, guided tourism business area and his current assignment is to implement a simple workflow for activating published tour.</p><p>What&#x27;s worth knowing is that whenever a published tour is it becomes available for customers to reserve seats.</p><p>One important step in that workflow is that whenever a tour is successfully activated, a new geotracking session needs to be created.</p><p>This is quite important because during the tour navigation, the geotracking session will be used to track the location of the tour guide and the participants.</p><p>Tracking provides useful information when it comes to managing a group of people spatially, and helps learning from each tour, afterwards.</p><p><span class="italic font-bold text-rose-400">Hank</span> learned that such new geotracking session will be created in inactive state, but in the future it might change, meaning that we might create a new session that should be immediately active.</p><p>So <span class="italic font-bold text-rose-400">Hank</span> starts his implementation by adding a simple repository for creating new geotracking sessions:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">GeotrackingSessionRepository</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>GeotrackingSession<span class="token punctuation">&gt;</span></span> <span class="token function">CreateNewSession</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> id<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">bool</span></span> isActive<span class="token punctuation">)</span> <span class="token comment">// 👈 Hank prepared this method to work with future, immediately active sessions</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> session <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">GeotrackingSession</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            Id <span class="token operator">=</span> id<span class="token punctuation">,</span>
</span><span class="code-line">            IsActive <span class="token operator">=</span> isActive<span class="token punctuation">,</span>
</span><span class="code-line">            CreatedAt <span class="token operator">=</span> DateTime<span class="token punctuation">.</span>UtcNow
</span><span class="code-line">        <span class="token punctuation">}</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">        _geotrackingSessionsDbContext<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span>session<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">await</span> _geotrackingSessionsDbContext<span class="token punctuation">.</span><span class="token function">SaveChangesAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token keyword">return</span> session<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Then <span class="italic font-bold text-rose-400">Hank</span> used his IDE to pull an interface out of that repository:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">IGeotrackingSessionRepository</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>GeotrackingSession<span class="token punctuation">&gt;</span></span> <span class="token function">CreateNewSession</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> id<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">bool</span></span> isActive<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Almost there!</p><p>Now <span class="italic font-bold text-rose-400">Hank</span> can implement the tour activation workflow, using that repository:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">TourActivationService</span><span class="token punctuation">(</span>
</span><span class="code-line">    <span class="token class-name">IGeotrackingSessionRepository</span> geotrackingSessionRepository<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">ITourRepository</span> tourRepository
</span><span class="code-line"><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">ActivateTour</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> tourId<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> publishedTour <span class="token operator">=</span> <span class="token keyword">await</span> tourRepository<span class="token punctuation">.</span><span class="token function">GetPublishedTourById</span><span class="token punctuation">(</span>tourId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token keyword">if</span><span class="token punctuation">(</span>publishedTour <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">InvalidOperationException</span><span class="token punctuation">(</span><span class="token string">&quot;Tour not found.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token keyword">if</span><span class="token punctuation">(</span>publishedTour<span class="token punctuation">?.</span>IsActive<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">InvalidOperationException</span><span class="token punctuation">(</span><span class="token string">&quot;Tour is already active.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">        publishedTour<span class="token punctuation">.</span>IsActive <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span> <span class="token comment">// 👈 Hank implemented this step accordingly to business logic</span>
</span><span class="code-line">        publishedTour<span class="token punctuation">.</span>ActivatedAt <span class="token operator">=</span> DateTime<span class="token punctuation">.</span>UtcNow<span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">await</span> tourRepository<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>publishedTour<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> _ <span class="token operator">=</span> <span class="token keyword">await</span> geotrackingSessionRepository<span class="token punctuation">.</span><span class="token function">CreateNewSession</span><span class="token punctuation">(</span>Guid<span class="token punctuation">.</span><span class="token function">NewGuid</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation named-parameter">isActive</span><span class="token punctuation">:</span> <span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 👈 Hank uses the repository to create a new, inactive geotracking session</span>
</span><span class="code-line">        <span class="token comment">// we discard the created session, as it is not needed in this context</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>So far, so good.</p><p>Tours repository was omitted, but it&#x27;s easy to imagine that it has methods for retrieving published tours and saving them back to the database.</p><p>Nice that <span class="italic font-bold text-rose-400">Hank</span> thought about future requirements and prepared the repository method to handle both active and inactive sessions.</p><p>Yes, it was a bit speculative, but hey, better be prepared, right?</p><p><span class="italic font-bold text-rose-400">Hank</span> is happy with his implementation, and he even wrote tests, verifying that the application logic works correctly!</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span>
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">should_throw_an_exception_when_no_tour_found</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// Arrange</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> NON_EXISTING_TOUR_ID <span class="token operator">=</span> Guid<span class="token punctuation">.</span><span class="token function">NewGuid</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> tourActivationService <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">TourActivationService</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token punctuation named-parameter">geotrackingSessionRepository</span><span class="token punctuation">:</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">InMemoryGeotrackingSessionRepository</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token punctuation named-parameter">tourRepository</span><span class="token punctuation">:</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">InMemoryTourRepository</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">// Act &amp; Assert</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> exception <span class="token operator">=</span>
</span><span class="code-line">        <span class="token keyword">await</span> Assert<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">ThrowsAsync</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>InvalidOperationException<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> tourActivationService<span class="token punctuation">.</span><span class="token function">ActivateTour</span><span class="token punctuation">(</span>NON_EXISTING_TOUR_ID<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    
</span><span class="code-line">    Assert<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span><span class="token string">&quot;Tour not found.&quot;</span><span class="token punctuation">,</span> exception<span class="token punctuation">.</span>Message<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span>
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">should_throw_an_exception_when_activating_already_active_published_tour</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// Arrange</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> EXISTING_ACTIVE_TOUR_ID <span class="token operator">=</span> Guid<span class="token punctuation">.</span><span class="token function">NewGuid</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> inMemoryTourRepository <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">InMemoryTourRepository</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    inMemoryTourRepository<span class="token punctuation">.</span><span class="token function">AddPublishedTour</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name constructor-invocation">PublishedTour</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        Id <span class="token operator">=</span> EXISTING_ACTIVE_TOUR_ID<span class="token punctuation">,</span>
</span><span class="code-line">        IsActive <span class="token operator">=</span> <span class="token boolean">true</span>
</span><span class="code-line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> tourActivationService <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">TourActivationService</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token punctuation named-parameter">geotrackingSessionRepository</span><span class="token punctuation">:</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">InMemoryGeotrackingSessionRepository</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token punctuation named-parameter">tourRepository</span><span class="token punctuation">:</span> inMemoryTourRepository
</span><span class="code-line">    <span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">// Act &amp; Assert</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> exception <span class="token operator">=</span>
</span><span class="code-line">        <span class="token keyword">await</span> Assert<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">ThrowsAsync</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>InvalidOperationException<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> tourActivationService<span class="token punctuation">.</span><span class="token function">ActivateTour</span><span class="token punctuation">(</span>EXISTING_ACTIVE_TOUR_ID<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    
</span><span class="code-line">    Assert<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span><span class="token string">&quot;Tour is already active.&quot;</span><span class="token punctuation">,</span> exception<span class="token punctuation">.</span>Message<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Application service looks quite straightforward, I believe that you, dear Reader, might have seen similar code before.</p><h3 id="documentation---writers-perspective"><a href="#documentation---writers-perspective" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Documentation - writer&#x27;s perspective</h3><p>An interruption came and <span class="italic font-bold text-rose-400">Hank</span> was asked to write documentation for running database migrations and seeding initial data for the application.</p><p>Now, let&#x27;s imagine we see <span class="italic font-bold text-rose-400">Hank</span> in action, when he puts a writer&#x27;s hat on.</p><p>He used that workflow many, many times so he&#x27;s a right person to put that knowledge down.</p><p>He opens a new file and starts writing:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="code-highlight language-md"><span class="code-line">Run <span class="token keyword code code-snippet">`dbmig -a -s`</span> in the root. Don&#x27;t forget to check the LSN if you&#x27;re on PG13+.
</span><span class="code-line">
</span><span class="code-line">The migration script uses a custom SQL generator that leverages our internal DbMigrationHelper class.
</span><span class="code-line">
</span><span class="code-line">It constructs the schema using a fluent API and applies transactional boundaries for each operation.
</span><span class="code-line">
</span><span class="code-line">After setup, everything should work as expected. If you encounter any issues, ask a team member.
</span></code></pre></div></div><p>Easy peasy, lemon squeezy.</p><p>15 min and the documentation is ready.</p><p>It looks quite straightforward, at the time of writing. I believe that you, dear Reader, might have seen similar documentation before.</p><h3 id="web-service-http-interaction---providers-perspective"><a href="#web-service-http-interaction---providers-perspective" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Web service HTTP interaction - provider&#x27;s perspective</h3><p>Finally, back to implementing feature related to published tours activation.</p><p>Let&#x27;s imagine that <span class="italic font-bold text-rose-400">Hank</span> needs to implement a web service endpoint that will be called whenever a published tour needs to be activated.</p><p>He immediately puts on his provider&#x27;s hat and starts implementing the HTTP endpoint using ASP.NET Core Minimal API.</p><p>Also, <span class="italic font-bold text-rose-400">Hank</span> remembers what he implemented, before he got interrupted by writing documentation, when it comes to <a href="https://talesfrom.dev/blog/the-ambiguity-of-application">application logic</a>.</p><p>But you know as it is dear Reader, to be 100% sure that his memory didn&#x27;t fool him, he checks the logic again.</p><p>Now, implementation time!</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line">app<span class="token punctuation">.</span><span class="token function">MapPost</span><span class="token punctuation">(</span><span class="token string">&quot;/tours/{tourId}/activate&quot;</span><span class="token punctuation">,</span> <span class="token keyword">async</span>
</span><span class="code-line"><span class="token punctuation">(</span>
</span><span class="code-line">    <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">FromRoute</span></span><span class="token punctuation">]</span> <span class="token class-name">Guid</span> tourId<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">FromServices</span></span><span class="token punctuation">]</span> <span class="token class-name">TourActivationService</span> tourActivationService
</span><span class="code-line">    <span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
</span><span class="code-line"><span class="token punctuation">{</span>   
</span><span class="code-line">    <span class="token keyword">try</span> 
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">await</span> tourActivationService<span class="token punctuation">.</span><span class="token function">ActivateTour</span><span class="token punctuation">(</span>tourId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">return</span> Results<span class="token punctuation">.</span><span class="token function">Ok</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">InvalidOperationException</span> ex<span class="token punctuation">)</span> <span class="token keyword">when</span> <span class="token punctuation">(</span>ex<span class="token punctuation">.</span>Message<span class="token punctuation">.</span><span class="token function">Contains</span><span class="token punctuation">(</span><span class="token string">&quot;Tour not found.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// 👈 Hank handled a scenario when a tour was not found</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">return</span> Results<span class="token punctuation">.</span><span class="token function">NotFound</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token punctuation">{</span> error <span class="token operator">=</span> ex<span class="token punctuation">.</span>Message <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">InvalidOperationException</span> ex<span class="token punctuation">)</span> <span class="token keyword">when</span> <span class="token punctuation">(</span>ex<span class="token punctuation">.</span>Message<span class="token punctuation">.</span><span class="token function">Contains</span><span class="token punctuation">(</span><span class="token string">&quot;Tour is already active.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// 👈 Hank handled a scenario when a tour was already active</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">return</span> Results<span class="token punctuation">.</span><span class="token function">Conflict</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token punctuation">{</span> error <span class="token operator">=</span> ex<span class="token punctuation">.</span>Message <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Exception</span> ex<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">return</span> Results<span class="token punctuation">.</span><span class="token function">BadRequest</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token punctuation">{</span> error <span class="token operator">=</span> ex<span class="token punctuation">.</span>Message <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre></div></div><p><span class="italic font-bold text-rose-400">Hank</span> ran the application couple of times and tested the endpoint using Postman, just to be sure that everything works as expected.</p><p>And of course, because he is quite good developer, everything worked as expected.</p><p>Nice job, <span class="italic font-bold text-rose-400">Hank</span>!</p><h3 id="needs"><a href="#needs" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Needs?</h3><p>&quot;Ok, but what is the point of those stories?&quot; - some might ask while being doubtful.</p><p>In every scenario, we&#x27;ve observed <span class="italic font-bold text-rose-400">Hank</span> doing some work - &quot;writing code&quot; or writing documentation.</p><p>Documentation part might feel a bit odd, but bear with me, dear Reader.</p><p>In both &quot;coding&quot; scenarios, <span class="italic font-bold text-rose-400">Hank</span> worked on the same feature, but on two different levels: on HTTP interaction handling level and on application logic level.</p><p>He started from low-level details, providing an implementation for geotracking session logic - he anticipated that <strong>maybe</strong> in the future, we might need to create active geotracking sessions right away.</p><p>Please note dear Reader that when I say &quot;logic&quot; I have a very specific meaning in mind - it is the knowledge about how things should work - what is the sequence of steps, what are the conditions/rules, what are return values, etc.</p><p>I should probably say &quot;an implementation of the knowledge about geotracking session creation&quot;, but it wouldn&#x27;t sound quite natural, hence I abstracted away the details and covered them under the term &quot;logic&quot;.</p><p>He moved &quot;up&quot; and went to &quot;application logic&quot; level - implementing the workflow and verifying if it works by writing two tests against that logic.</p><p>Finally, he moved &quot;up&quot; again and implemented the HTTP endpoint that will be called by web service clients.</p><p>&quot;So what? Everything seems fine to me.&quot; - many might comment.</p><p>But here comes the tricky part - if you, dear Reader, were asked about <strong>the role</strong> that <span class="italic font-bold text-rose-400">Hank</span> <strong>played</strong> in each of those scenarios, what would your answer be?</p><p>Well, at least according to section titles, he was a developer, an implementer, right?</p><p>So he <em>implemented</em> repository logic, which then <em>was consumed</em> by application logic, which he <em>implemented</em>, which then <em>was consumed</em> by HTTP endpoint logic, which he also <em>implemented</em>, which eventually <em>will be consumed</em> by web service clients.</p><p>A beautiful dance between implementing and consuming.</p><p>So <span class="italic font-bold text-rose-400">Hank</span> played two different roles - an implementer and a consumer.</p><p>Each implementation resulted in <em>providing</em> a certain <em>capability</em>: either creating a new geotracking session, activating a published tour, or handling an HTTP request.</p><p>Then, in a way, each implementation also <em>used</em> a certain <em>provided capability</em>: either creating a new geotracking session or activating a published tour (or, in case of HTTP endpoint, interacting with web service to activate published tour via HTTP protocol).</p><p>So <span class="italic font-bold text-rose-400">Hank</span> switched roles multiple times - from logic implementing provider to capability consumer, and back.</p><h3 id="god-like-architect"><a href="#god-like-architect" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>God-like architect</h3><p>Also, an avid Reader might notice that on various levels the decisions made were influenced and impacted by the omniscient knowledge of the designing person.</p><p>Implicitly.</p><p>Let&#x27;s play a role of an application service, just for a while.</p><p>Are you with me, dear Reader?</p><p>Ok, let&#x27;s become an application service - do we need to have <strong>the knowledge</strong> about <code>IsActive</code> property of a published tour, in this particular scenario?</p><p>Well, we could say that we do, because we need to check if the tour is already active, before activating it.</p><p>But wait a second - who decided that we need to have such knowledge in the first place?</p><p>The needs of ours are quite clear - we need to activate a published tour and if it succeeds, we need to create a new geotracking session.</p><p>This is the knowledge we are supposed to have, right?</p><p>It&#x27;s as if we didn&#x27;t trust <code>PublishedTour</code> object to provide us with the necessary behavior - we had to know about <code>IsActive</code> property and check it ourselves.</p><p>Shouldn&#x27;t we tell it to activate itself, and let it handle the details internally?</p><p>It looks as if <code>PublishedTour</code> was too dumb to know how to activate itself properly, so we had to take that responsibility upon ourselves.</p><p>Or as if it was too anemic, not having enough power to keep its internals safe.</p><p>A conseuqence of such anemic behavior is that we, as application service, had to know about <code>IsActive</code> property, and check it ourselves - which leads to broader change radius, whenever there are more details to take into account while activating a published tour.</p><p>Additionally, what are our (as application service, remember) needs when it comes to geotracking session creation?</p><p><code>IGeotrackingSessionRepository</code> provides a contract requiring us to have the knowledge about <code>isActive</code> parameter.</p><p>In this particular scenario, we know that we need to create an inactive session, which makes using that interface&#x27;s method with <code>isActive</code> parameter a bit <a href="https://talesfrom.dev/blog/the-ambiguity-of-interfaces">ambiguous</a> (from an application service perspective).</p><p>I know, I know - it is sooooooooo low-level that it might seem irrelevant, especially in cheap code production times as we have nowadays, thanks to LLMs.</p><p>But behind those nitty gritty details lies a very important problem - the designer is influencing the design by representing too much knowledge on levels which shouldn&#x27;t have that knowledge at all, unconsciously coupling those levels together.</p><p>In this tiny example, it might seem harmless, but training one&#x27;s sight to spot such issues is a very important skill for any software designer.</p><p>According to <a href="https://talesfrom.dev/blog/the-knowledge-gravity-problem">the knowledge gravity problem</a>, knowledge attracts more knowledge.</p><h3 id="provider-driven-design"><a href="#provider-driven-design" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Provider-driven design?</h3><p>Let&#x27;s jump to HTTP request handling level for a while.</p><p>The knowledge represented there also might look just fine - but when an avid Reader inspects it closely, they might notice that those message-checking conditions are quite smelly.</p><p><span class="italic font-bold text-rose-400">Hank</span> had to know about those error messages in order to handle them properly, on different level than application logic level.</p><p>So then he a provided capability for doing so - by using exception messages as a way to communicate error conditions.</p><p>But now it&#x27;s the consuming party that needs to have <strong>the knowledge</strong> about distinguishing those differrent error cases.</p><p>And unintended coupling was summoned.</p><p>Seems like the pattern was as follows: providing, consuming, providing, consuming, etc. - <span class="italic font-bold text-rose-400">Hank</span> firstly provided capabilities by implementing logic, then consumed whatever was produced by himself, but on a different level, and &quot;with different hat&quot;.</p><p>Which brings us to the main point - it was a provider-driven design, shaping the knowledge distribution, creating possible unintended coupling between different levels of the system.</p><h3 id="the-invisible-role-switching-problem"><a href="#the-invisible-role-switching-problem" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The invisible role-switching problem</h3><p>So, dear Reader, what is the hardest part of software designing?</p><p>Many say it&#x27;s naming and cache invalidation.</p><p>You might recall that <a href="https://talesfrom.dev/blog/the-ambiguity-of-naming">naming</a> is indeed impactful, because it frames our thinking.</p><p>But as we are developing and designing classes, objects collaboration, services interaction, architectural elements, we are switching roles constantly.</p><p>Sometimes it happens so subtly that we don&#x27;t even notice it.</p><p>We switch from being a capability provider to being a capability consumer, and back.</p><p>Often completly forgetting the needs of the consumer, and focusing solely on providing capabilities.</p><p>Obsessing ourselves with low-level implementation details, forgetting that we are designing <em>something</em> for a <em>purpose</em> (you might be interested in <a href="https://talesfrom.dev/blog/composing-a-pie">Composing a PIE</a>).</p><p>As you saw, dear Reader, <span class="italic font-bold text-rose-400">Hank</span> was jumping between roles, changing hats, without even realizing it.</p><p>It was transparent, invisible, under the radar.</p><p>A true designing requires awareness, mindfulness and discipline.</p><p>It requires a real role-playing skill.</p><p>Deliberate acting as a capability consumer, requesting a certain behavior, based on the needs, then switching to a capability provider role, implementing the requested behavior, and so on.</p><p>And this is exactly where TDD can help a lot - by forcing us to think in terms of <em>needs</em> first, then <em>providing</em> the necessary <em>capabilities</em>.</p><p>As we discussed in <a href="https://talesfrom.dev/blog/tdd-specify-satisfy-simplify">TDD: specify, satisfy, simplify</a>, it is about specifying consumer-expected behavior, using tests.</p><p>Tests are vital, as they ought to provide <a href="blog/fragile">rapid feedback</a>.</p><h3 id="documentation-and-the-invisible-role-switching-problem"><a href="#documentation-and-the-invisible-role-switching-problem" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Documentation and the invisible role-switching problem?</h3><p>You might still wonder, dear Reader, about documentation writing scenario - how does it relate to the invisible role-switching problem?</p><p>An interaction between two roles - a writer and a reader - also expresses similar relationship and dynamics, as we observed in &quot;coding&quot; scenarios.</p><p>When writing documentation, <span class="italic font-bold text-rose-400">Hank</span> had to think about the <em>needs</em> of the <em>reader</em>.</p><p>What would the reader need to know in order to successfully run database migrations and seed initial data?</p><p>What information is essential, what can be omitted, from the reader&#x27;s perspective?</p><p>What details might be helpful in two or three months&#x27; time?</p><p>Then, after identifying those needs, <span class="italic font-bold text-rose-400">Hank</span> should have <em>provided</em> the necessary <em>capabilities</em> by writing clear and concise instructions.</p><p>If one looks from a right level and angle, it also resembles provider-consumer relationship, expressing invisible role-switching problem.</p><p>But it might not be that easy to verify, as with the code, because documentation correctness is often subjective and context-dependent.</p><p>So it is consumer-expected capability specification, although feedback look is not as rapid and deterministic as with tests.</p><p>This also highlights a very important point - a consumer, a provider and their relationship appears on various levels, in different contexts, in different forms.</p><p>Those roles manifest fractally.</p><p>A consumer might be another object.</p><p>A consumer might be another module.</p><p>A consumer might be another web service.</p><p>A consumer might be another human being.</p><p>So when we play a role of a consumer, we should employ &quot;wishful amnesia&quot;, forgetting about &quot;hows&quot; (at least temporarily), focusing on &quot;whats&quot;.</p><p>Specifying the contract - what we are required to provide, what we expect to get.</p><p>Specifying expected behavior, according to the given contract.</p><p>This deliberate &quot;forgetting&quot; is very, very important, and I feel we don&#x27;t practice it enough.</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>Who is going to consume what I am about to provide? What are their needs?</p></div></div></div><h3 id="constraints-opportunities-and-discipline"><a href="#constraints-opportunities-and-discipline" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Constraints, opportunities and discipline</h3><p>The invisible role-switching problem is quite subtle and tricky.</p><p>But actually we might exploit this phenomenon to our advantage by consciously playing respective roles.</p><p>Start from consumer&#x27;s perspective - identify the needs, specify the expected behavior, then switch to provider&#x27;s perspective - implement the requested behavior.</p><p>In the code we have an advantage by using tests as a way to specify consumer-expected behavior, getting rapid feedback.</p><p>Taiichi Ohno, the father of Toyota Production System, pointed out that:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Overproduction is the biggest waste.</p></div></div></div><p>Knowing that, as designers, we should focus on <em>needs</em> of the consumers, avoiding overproduction.</p><p>By knowing the purpose, the needs, we switch hats to become a capability provider and provide exactly what is needed, no more, no less, for a particular use case, in a given context.</p><p>As a capability provider, we should empathize with the consumer - whether it is another object, a web service, or a human being.</p><p>Consumer&#x27;s needs matters and we should pay close attention to them, as they influence our design decisions.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Each constraint might be an opportunity, each opportunity might be a constraint.</p></div></div></div><p>Constraining ourselves and framing our thinking to <em>reason</em> either as a consumer or as a provider, liberates us from unnecessary complexity, overengineering and overproduction.</p><p>It gives us the right perspective, the right mindset.</p><p>But unfortunately, things are even harder than that.</p><p>Next to a (capability) consumer, a (capability) provider - we also need to play the role of a designer/an architect.</p><p>We need to constantly observe the big picture, the overall knowledge distribution, the boundaries between different levels of the system, how the knowledge is represented, coupled and if it is cohesive enough.</p><p>Suddenly, it becomes crucial to work on self-awareness, discipline, and knowing what role we are playing at a given moment.</p><p>Remembering, it is just a role and we are capable of switching it, whenever needed.</p><p>So next time, dear Reader, when you find yourself designing architectural elements, services, documentation, objects collaboration, pause for a moment and ask yourself a question:</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>Who am I, right now?</p></div></div></div> <div class="bg-slate-600 rounded-xl mt-8"><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Attention!</span></div><div class="pb-2 px-3"><div class="break-words"><p>If you want to learn more about practical way for applying Need-Driven Design in your software development, check out my next blog post: <a href="https://talesfrom.dev/blog/consumer-expected-need-driven-behavior-development">Consumer-expected, need-driven behavior development</a>.</p></div></div></div>]]></content:encoded>
    <pubDate>Tue, 06 Jan 2026 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>software engineering</category><category>software design</category><category>object-oriented design</category><category>modularity</category><category>design patterns</category><category>language patterns</category><category>software quality</category><category>knowledge working</category><category>modularity</category><category>modular monolith</category><category>boundaries</category><category>behavior specification</category><category>collaboration</category><category>concurrency</category><category>optimistic concurrency</category><category>composability</category><category>collaborative modelling</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/bounded-contexts-from-compile-time-hierarchies-to-runtime-composition</guid>
    <title>Bounded contexts: from compile-time hierarchies to runtime composition</title>
    <link>https://talesfrom.dev/blog/bounded-contexts-from-compile-time-hierarchies-to-runtime-composition</link>
    <description>How to design composable models?</description>
    <content:encoded><![CDATA[<h3 id="how-can-we-help"><a href="#how-can-we-help" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>How can we help?</h3><p>Meet Tom (you might recall him from <a href="https://talesfrom.dev/blog/many-faces-of-ddd-aggregates-in-fsharp">Many Faces of DDD Aggregates in F#</a>).</p><p>As a successful businessman, after he earned tons of money with disco clubs, gamedev and now he tries his luck in software for public speaking.</p><div class="flex flex-col "><div class="flex flex-col"><div class="flex justify-center items-center flex-col"><div class="flex max-sm:flex-col justify-between items-center"><img src="https://talesfrom.dev/static/images/business-man.png" class="max-h-[30rem]"/><div class="flex flex-col justify-between text-left"><span>Tom says:</span><span class="my-4 italic"><span class=""><p>Hi, my name is Tom.</p></span><div class="my-3"><span class="">I think there&#x27;s a big opportunity in the market for software that helps public speakers </span><span class="mr-2">managing slide decks</span><span class="">.</span></div><div class="my-3"><span class="">You know - it&#x27;s about </span><span class="mr-2">adding slides</span><span class="">and </span><span class="mr-2">reordering slides</span><span class="">, </span><span class="mr-2">adding some content</span><span class="">, </span><span class="mr-2">adding notes for speakers</span><span class="">. Nothing fancy.</span></div><span class=""><p>Can you help me with some ideas?</p></span></span></div></div></div></div><div class="flex justify-around mt-10 lg:mx-32"><button class="bg-gray-600 border-gray-100 text-gray-400 p-2 rounded">Just talk</button><button class="bg-green-700 text-white border-2 p-2 rounded">Listening carefully</button></div></div><p>Tom showed us a rough sketch of his idea, in the form of low-fidelity wireframe:</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/bounded-contexts-from-compile-time-hierarchies-to-runtime-composition-business-idea-1.png" class="max-h-[24rem]"/></div><div class="italic mx-24">Low-fidelity glimpse of UI</div></div><p>A slide deck, consisting of multiple, ordered slides, each slide having some content (and of course notes for the speaker, we know it even though Tom forgot to draw it).</p><h3 id="lets-present-some-ideas"><a href="#lets-present-some-ideas" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Let&#x27;s present some ideas</h3><p>Sounds like an interesting problem to tackle, right?</p><p>If you were able to listen carefully, dear Reader, you might have captured some important concepts Tom mentioned.</p><p>Let&#x27;s try to represent them using the code, firstly starting with the main, domain concept - <em>a slide deck</em>.</p><p>There are also <em>slides</em>, each having some <em>content</em>, <em>notes</em> and ordering within the deck.</p><p>Here is how we can sketch it on the whiteboard:</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/bounded-contexts-from-compile-time-hierarchies-to-runtime-composition-naive-decomposition.png" class="max-h-[24rem]"/></div><div class="italic mx-24">Initial idea how to translate a problem into a solution?</div></div><p>An avid reader might notice that a slide deck available under identifier &quot;D43&quot; <em>has many</em> slides, and has title &quot;Inspiring Business Topic&quot;.</p><p>Each slide has its own identifier (e.g. &quot;S-3012&quot;) and position within the deck (e.g. 1) and unique content, for instance, consisting of text only.</p><p>We can start by defining a <code>SlideDeck</code> class:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">class</span> <span class="token class-name">SlideDeck</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// data goes here</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Many times we&#x27;ve heard that focusing on nouns might lead us to build bags-of-data, rather than rich domain models.</p><p>What behaviours can we add to our <code>SlideDeck</code> class?</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">class</span> <span class="token class-name">SlideDeck</span> <span class="token punctuation">{</span>
</span><span class="code-line">    deckId<span class="token operator">:</span> DeckId<span class="token punctuation">;</span>
</span><span class="code-line">    title<span class="token operator">:</span> Title<span class="token punctuation">;</span>
</span><span class="code-line">    slides<span class="token operator">:</span> Slide<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token function">addSlide</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token punctuation">{</span> slideId<span class="token operator">:</span> SlideId<span class="token punctuation">,</span> position<span class="token operator">:</span> PositiveInt <span class="token punctuation">}</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">// ...</span>
</span><span class="code-line">    <span class="token punctuation">}</span><span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token function">deleteSlide</span><span class="token punctuation">(</span>slideId<span class="token operator">:</span> SlideId<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">// ...</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token function">duplicateSlide</span><span class="token punctuation">(</span>slideId<span class="token operator">:</span> SlideId<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token punctuation">{</span> newSlideId<span class="token operator">:</span> SlideId<span class="token punctuation">,</span> position<span class="token operator">:</span> PositiveInt <span class="token punctuation">}</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">// ...</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token function">moveSlide</span><span class="token punctuation">(</span>slideId<span class="token operator">:</span> SlideId<span class="token punctuation">,</span> newPosition<span class="token operator">:</span> PositiveInt<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">// ...</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token function">moveSlides</span><span class="token punctuation">(</span>slideIds<span class="token operator">:</span> SlideId<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span> newPosition<span class="token operator">:</span> PositiveInt<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">// ...</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token function">updateContent</span><span class="token punctuation">(</span>slideId<span class="token operator">:</span> SlideId<span class="token punctuation">,</span> content<span class="token operator">:</span> Content<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">// ...</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token function">updateNotes</span><span class="token punctuation">(</span>slideId<span class="token operator">:</span> SlideId<span class="token punctuation">,</span> notes<span class="token operator">:</span> Notes<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">// ...</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Self-describing set of capabilities that are provided by our rich domain model - <code>SlideDeck</code>.</p><p>Now, we can imagine that such model can be <a href="blog/the-ambiguity-of-application">applied</a> in a such a way:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">NewSlideDeckContext</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
</span><span class="code-line">    slideDeckRepository<span class="token operator">:</span> ForCreatingSlideDecks<span class="token punctuation">,</span>
</span><span class="code-line">    uuid<span class="token operator">:</span> ForGeneratingUuids
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line"><span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token function function-variable">newSlideDeck</span> <span class="token operator">=</span> <span class="token punctuation">(</span>context<span class="token operator">:</span> NewSlideDeckContext<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token builtin">Promise</span><span class="token operator">&lt;</span>DeckId<span class="token operator">&gt;</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">const</span> deckId <span class="token operator">=</span> context<span class="token punctuation">.</span>uuid<span class="token punctuation">.</span><span class="token function">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token keyword">const</span> slideDeck <span class="token operator">=</span> <span class="token keyword">await</span> context<span class="token punctuation">.</span>slideDeckRepository<span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span><span class="token punctuation">{</span> deckId <span class="token punctuation">}</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token keyword">return</span> deckId
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">AddSlideContext</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
</span><span class="code-line">    slideDeckRepository<span class="token operator">:</span> ForLoadingSlideDecks <span class="token operator">&amp;</span> ForSavingSlideDecks<span class="token punctuation">,</span>
</span><span class="code-line">    uuid<span class="token operator">:</span> ForGeneratingUuids
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line"><span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token function function-variable">addSlide</span> <span class="token operator">=</span> <span class="token punctuation">(</span>context<span class="token operator">:</span> AddSlideContext<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token keyword">async</span> <span class="token punctuation">(</span>deckId<span class="token operator">:</span> DeckId<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token builtin">Promise</span><span class="token operator">&lt;</span><span class="token punctuation">{</span> slideId<span class="token operator">:</span> SlideId<span class="token punctuation">,</span> position<span class="token operator">:</span> PositiveInt <span class="token punctuation">}</span><span class="token operator">&gt;</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">const</span> slideDeck <span class="token operator">=</span> <span class="token keyword">await</span> context<span class="token punctuation">.</span>slideDeckRepository<span class="token punctuation">.</span><span class="token function">load</span><span class="token punctuation">(</span>deckId<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token keyword">const</span> <span class="token punctuation">{</span> slideId<span class="token punctuation">,</span> position <span class="token punctuation">}</span> <span class="token operator">=</span> slideDeck<span class="token punctuation">.</span><span class="token function">newSlide</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token keyword">await</span> context<span class="token punctuation">.</span>slideDeckRepository<span class="token punctuation">.</span><span class="token function">save</span><span class="token punctuation">(</span>slideDeck<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token keyword">return</span> <span class="token punctuation">{</span> slideId<span class="token punctuation">,</span> position <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">MoveSlideContext</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
</span><span class="code-line">    slideDeckRepository<span class="token operator">:</span> ForLoadingSlideDecks <span class="token operator">&amp;</span> ForSavingSlideDecks
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line"><span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token function function-variable">moveSlide</span> <span class="token operator">=</span> <span class="token punctuation">(</span>context<span class="token operator">:</span> MoveSlideContext<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token keyword">async</span> <span class="token punctuation">(</span>deckId<span class="token operator">:</span> DeckId<span class="token punctuation">,</span> slideId<span class="token operator">:</span> SlideId<span class="token punctuation">,</span> newPosition<span class="token operator">:</span> PositiveInt<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token builtin">Promise</span><span class="token operator">&lt;</span><span class="token keyword">void</span><span class="token operator">&gt;</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">const</span> slideDeck <span class="token operator">=</span> <span class="token keyword">await</span> context<span class="token punctuation">.</span>slideDeckRepository<span class="token punctuation">.</span><span class="token function">load</span><span class="token punctuation">(</span>deckId<span class="token punctuation">)</span>
</span><span class="code-line">    slideDeck<span class="token punctuation">.</span><span class="token function">moveSlide</span><span class="token punctuation">(</span>slideId<span class="token punctuation">,</span> newPosition<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token keyword">await</span> context<span class="token punctuation">.</span>slideDeckRepository<span class="token punctuation">.</span><span class="token function">save</span><span class="token punctuation">(</span>slideDeck<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line"><span class="token comment">// ... and so on for other use cases</span>
</span></code></pre></div></div><p>One can now visualize that those functions (or commands, if you will), will be utilized in HTTP handlers or message handlers, depending on the needs.</p><p>We could say that for the sake of simplicity, those operations will be exposed as HTTP endpoints, e.g.:</p><ul><li><code>POST /slide-decks</code> -&gt; creates a new slide deck</li><li><code>POST /slide-decks/{deckId}/slides</code> -&gt; adds a new slide to the deck</li><li><code>PATCH /slide-decks/{deckId}/slides/{slideId}/move</code> -&gt; moves the slide to a new position</li></ul><h3 id="presenting-problems"><a href="#presenting-problems" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Presenting problems</h3><p>Well, everything was going well until Tom came back with some &quot;additional requirements&quot;.</p><p>Turned out that all worked fine, but there were some unspoken needs.</p><div class="flex flex-col "><div class="flex flex-col"><div class="flex justify-center items-center flex-col"><div class="flex max-sm:flex-col justify-between items-center"><img src="https://talesfrom.dev/static/images/business-man.png" class="max-h-[30rem]"/><div class="flex flex-col justify-between text-left"><span>Tom says:</span><span class="my-4 italic"><span class=""><p>The application really helps getting work done.</p></span><div class="my-3"><span class="">My typical </span><span class="mr-2">workflow</span><span class="">, as a creative businessman, </span><span class="mr-2">is to first draft rough slides with content and later improve them with more quality</span><span class="">.</span></div><span class=""><p>I am adding many notes so one of my assistants does the content polishing - I want to save my precious time.</p></span><div class="my-3"><span class="">So whenever </span><span class="mr-2">me and another person work on the same slide deck, we often step on each other&#x27;s toes</span><span class="">.</span></div><span class=""><p>I can&#x27;t move on, as an assistant changes the content, or the other way round.</p></span><span class=""><p>Can we do something about it?</p></span></span></div></div></div></div><div class="flex justify-around mt-10 lg:mx-32"><button class="bg-gray-600 border-gray-100 text-gray-400 p-2 rounded">Just talk</button><button class="bg-green-700 text-white border-2 p-2 rounded">Listening carefully</button></div></div><p>Initially, we only explored user interface, so the consequence that an end user sees - which is merely a snapshot of the state - we didn&#x27;t ask important questions about what is the workflow, what are the rules and constraints.</p><p>Seems like a typical concurrency problem.</p><p>Optimistic control for the rescue!</p><p>We can add a <code>version</code> property to our <code>SlideDeck</code> class, and bump it whenever we save the changes.</p><p>When loading the slide deck for modification, we also load the version.</p><p>When saving, we check if the version hasn&#x27;t changed in the meantime.</p><p><a href="https://talesfrom.dev/blog/simple-isnt-easy">Easy</a>!</p><p>But user experience might be a bit clunky - users will have to reload the slide deck and re-apply their changes.</p><p>Or maybe...We could work on the model level?</p><h3 id="rethinking-a-solution-1"><a href="#rethinking-a-solution-1" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Rethinking a solution #1</h3><p>If changing the title is independent from reordering slides, maybe we could isolate that responsibility?</p><p>We would then create a new solution.</p><p>We could potentially rethink our problem and organize behaviors around smaller pieces of the slide deck - <code>Slide</code>s.</p><p>Let&#x27;s try to perform further decomposition and treat each slide as a consistency unit, enabling concurrent modifications of different slides within the same deck.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/bounded-contexts-from-compile-time-hierarchies-to-runtime-composition-further-decomposition.png" class="max-h-[24rem]"/></div><div class="italic mx-24">Slide deck and slides as separate concepts</div></div><p>So now, it&#x27;s not a <code>SlideDeck</code> that has all the behaviors, but rather each <code>Slide</code> has its own behaviors, and stop being a mere data structure.</p><p>A <code>SlideDeck</code> keeps track of its title and each <code>Slide</code> keep track of its content, notes and position within the deck.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">class</span> <span class="token class-name">Slide</span> <span class="token punctuation">{</span>
</span><span class="code-line">    slideId<span class="token operator">:</span> SlideId<span class="token punctuation">;</span>
</span><span class="code-line">    deckId<span class="token operator">:</span> DeckId<span class="token punctuation">;</span>
</span><span class="code-line">    position<span class="token operator">:</span> PositiveInt<span class="token punctuation">;</span>
</span><span class="code-line">    content<span class="token operator">:</span> Content<span class="token punctuation">;</span>
</span><span class="code-line">    notes<span class="token operator">:</span> Notes<span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token function">updateContent</span><span class="token punctuation">(</span>content<span class="token operator">:</span> Content<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">// ...</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token function">updateNotes</span><span class="token punctuation">(</span>notes<span class="token operator">:</span> Notes<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">// ...</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token function">moveTo</span><span class="token punctuation">(</span>newPosition<span class="token operator">:</span> PositiveInt<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">// ...</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token function">duplicate</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> Slide <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">// ...</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>This new model establishes the collision boundary per slide, rather than per deck.</p><p>Now, two users can concurrently modify different slides, and their contents, within the same deck without stepping on each other&#x27;s toes.</p><p>Let&#x27;s examine updating a content of a single slide:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">UpdateSlideContentContext</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
</span><span class="code-line">    slidesRepository<span class="token operator">:</span> ForLoadingSlide <span class="token operator">&amp;</span> ForSavingSlide
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token function function-variable">updateSlideContent</span> <span class="token operator">=</span> <span class="token punctuation">(</span>context<span class="token operator">:</span> UpdateSlideContentContext<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token keyword">async</span> <span class="token punctuation">(</span>deck<span class="token operator">:</span> DeckId<span class="token punctuation">,</span> slideId<span class="token operator">:</span> SlideId<span class="token punctuation">,</span> newContent<span class="token operator">:</span> Content<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">const</span> slide <span class="token operator">=</span> <span class="token keyword">await</span> context<span class="token punctuation">.</span>slidesRepository<span class="token punctuation">.</span><span class="token function">getBy</span><span class="token punctuation">(</span><span class="token punctuation">{</span> deck<span class="token punctuation">,</span> slideId <span class="token punctuation">}</span><span class="token punctuation">)</span>
</span><span class="code-line">    slide<span class="token punctuation">.</span><span class="token function">updateContent</span><span class="token punctuation">(</span>newContent<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token keyword">await</span> context<span class="token punctuation">.</span>slidesRepository<span class="token punctuation">.</span><span class="token function">save</span><span class="token punctuation">(</span>slide<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Same goes for reordering slides...Right?</p><p>Hm, not quite.</p><p>Earlier, we had operations like <code>moveSlide(slideId: SlideId, newPosition: PositiveInt)</code> and <code>moveSlides(slideIds: SlideId[], newPosition: PositiveInt)</code> on the <code>SlideDeck</code>, but now each <code>Slide</code> can only move itself.</p><p>A <code>SlideDeck</code> model was responsible for ensuring, that after moving a slide or slides, everything is consistent.</p><p>The logic itself might have been non-trivial, as it required not only taking care of slides being a subject of reordering, but also other ones that are affected by such action.</p><p>Let&#x27;s see how previous model - based on <code>SlideDeck</code> - could satisfy a capability for moving a single slide:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token comment">// 👇 public method in `SlideDeck`</span>
</span><span class="code-line"><span class="token function">moveSlide</span><span class="token punctuation">(</span>slideId<span class="token operator">:</span> SlideId<span class="token punctuation">,</span> newPosition<span class="token operator">:</span> PositiveInt<span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">const</span> slideIndex <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>slides<span class="token punctuation">.</span><span class="token function">findIndex</span><span class="token punctuation">(</span>s <span class="token operator">=&gt;</span> s<span class="token punctuation">.</span>slideId <span class="token operator">===</span> slideId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">if</span> <span class="token punctuation">(</span>slideIndex <span class="token operator">===</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span><span class="token template-string"><span class="token string template-punctuation">`</span><span class="token string">Slide </span><span class="token interpolation"><span class="token punctuation interpolation-punctuation">${</span>slideId<span class="token punctuation interpolation-punctuation">}</span></span><span class="token string"> not found in deck</span><span class="token string template-punctuation">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    
</span><span class="code-line">    <span class="token keyword">const</span> currentPosition <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>slides<span class="token punctuation">[</span>slideIndex<span class="token punctuation">]</span><span class="token punctuation">.</span>position<span class="token punctuation">;</span>
</span><span class="code-line">    
</span><span class="code-line">    <span class="token keyword">if</span> <span class="token punctuation">(</span>currentPosition <span class="token operator">===</span> newPosition<span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">return</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    
</span><span class="code-line">    <span class="token keyword">if</span> <span class="token punctuation">(</span>newPosition <span class="token operator">&lt;</span> currentPosition<span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token function">moveAffectedSlidesUp</span><span class="token punctuation">(</span><span class="token punctuation">{</span> newPosition<span class="token punctuation">,</span> currentPosition <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token comment">// 👈 private method in `SlideDeck`</span>
</span><span class="code-line">    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token function">moveAffectedSlidesDown</span><span class="token punctuation">(</span><span class="token punctuation">{</span> newPosition<span class="token punctuation">,</span> currentPosition <span class="token punctuation">}</span><span class="token punctuation">)</span>  <span class="token comment">// 👈 private method in `SlideDeck`</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    
</span><span class="code-line">    <span class="token keyword">this</span><span class="token punctuation">.</span>slides<span class="token punctuation">[</span>slideIndex<span class="token punctuation">]</span><span class="token punctuation">.</span>position <span class="token operator">=</span> newPosition<span class="token punctuation">;</span>
</span><span class="code-line">    
</span><span class="code-line">    <span class="token keyword">this</span><span class="token punctuation">.</span>slides<span class="token punctuation">.</span><span class="token function">sort</span><span class="token punctuation">(</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span> b<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> a<span class="token punctuation">.</span>position <span class="token operator">-</span> b<span class="token punctuation">.</span>position<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p><code>SlideDeck</code>&#x27;s private methods <code>moveAffectedSlidesUp</code> and <code>moveAffectedSlidesDown</code> methods take care of other slides and update their position, accordingly.</p><p>Here we can see that our previous model needed to make some decisions to keep consistency.</p><p>Now, we <a href="https://talesfrom.dev/blog/the-ambiguity-of-software-architecture">organized responsibilities</a> differently, which does not mean that this logic (knowledge application, &quot;ifs&quot;) disappeared.</p><p>As someone said: &quot;complexity does not disappear, it gets moved&quot;.</p><p>Each <code>Slide</code> is responsible for moving itself, so where would we locate the logic for coordinating multiple <code>Slide</code>s?</p><p>One of the possible solutions, given a new <code>Slide</code>-based model we selected, would be:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">MoveSlideContext</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
</span><span class="code-line">    slidesRepository<span class="token operator">:</span> ForLoadingsManySlides <span class="token operator">&amp;</span> ForSavingManySlides
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token comment">// 👇 public function int he module scope</span>
</span><span class="code-line"><span class="token keyword">const</span> <span class="token function function-variable">moveSlide</span> <span class="token operator">=</span> <span class="token punctuation">(</span>context<span class="token operator">:</span> MoveSlideContext<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token keyword">async</span> <span class="token punctuation">(</span>deck<span class="token operator">:</span> DeckId<span class="token punctuation">,</span> slideId<span class="token operator">:</span> SlideId<span class="token punctuation">,</span> newPosition<span class="token operator">:</span> PositiveInt<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">const</span> allSlides <span class="token operator">=</span> <span class="token keyword">await</span> context<span class="token punctuation">.</span>slidesRepository<span class="token punctuation">.</span><span class="token function">loadAllIn</span><span class="token punctuation">(</span><span class="token punctuation">{</span> deck <span class="token punctuation">}</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token keyword">const</span> slideToMove <span class="token operator">=</span> allSlides<span class="token punctuation">.</span><span class="token function">find</span><span class="token punctuation">(</span>slide <span class="token operator">=&gt;</span> slide<span class="token punctuation">.</span>Id <span class="token operator">===</span> slideId<span class="token punctuation">)</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span>slideToMove<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span><span class="token template-string"><span class="token string template-punctuation">`</span><span class="token string">Slide </span><span class="token interpolation"><span class="token punctuation interpolation-punctuation">${</span>slideId<span class="token punctuation interpolation-punctuation">}</span></span><span class="token string"> not found in deck </span><span class="token interpolation"><span class="token punctuation interpolation-punctuation">${</span>deck<span class="token punctuation interpolation-punctuation">}</span></span><span class="token string template-punctuation">`</span></span><span class="token punctuation">)</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">if</span><span class="token punctuation">(</span>slideToMove<span class="token punctuation">.</span>position <span class="token operator">===</span> newPosition<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token keyword">return</span><span class="token punctuation">;</span>
</span><span class="code-line">    
</span><span class="code-line">    <span class="token keyword">if</span><span class="token punctuation">(</span>slideToMove<span class="token punctuation">.</span>position <span class="token operator">&lt;</span> newPosition<span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token function">moveAffectedSlidesDown</span><span class="token punctuation">(</span><span class="token punctuation">{</span>  <span class="token comment">// 👈 private function in the module scope</span>
</span><span class="code-line">            allSlides<span class="token punctuation">,</span>
</span><span class="code-line">            newPosition<span class="token punctuation">,</span>
</span><span class="code-line">            currentPosition<span class="token operator">:</span> slideToMove<span class="token punctuation">.</span>position
</span><span class="code-line">        <span class="token punctuation">}</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token function">moveAffectedSlidesUp</span><span class="token punctuation">(</span><span class="token punctuation">{</span>   <span class="token comment">// 👈 private function in the module scope</span>
</span><span class="code-line">            allSlides<span class="token punctuation">,</span>
</span><span class="code-line">            newPosition<span class="token punctuation">,</span>
</span><span class="code-line">            currentPosition<span class="token operator">:</span> slideToMove<span class="token punctuation">.</span>position
</span><span class="code-line">        <span class="token punctuation">}</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    slideToMove<span class="token punctuation">.</span><span class="token function">moveTo</span><span class="token punctuation">(</span>newPosition<span class="token punctuation">)</span> <span class="token comment">// 👈 public method in `Slide`</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">await</span> context<span class="token punctuation">.</span>slidesRepository<span class="token punctuation">.</span><span class="token function">saveMany</span><span class="token punctuation">(</span>slidesToUpdate<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>In a way, many things changed, but nothing really changed - except we moved the logic between different levels.</p><p>Maybe we were able to isolate updating contents of two different slides, but reordering still isn&#x27;t free from &quot;stepping on each other toes&quot;.</p><p>What&#x27;s more, we haven&#x27;t explored &quot;duplicating slide&quot; capability which probably involves duplicating contents of a slide <strong>and</strong> doing the work on <em>reordering level</em>.</p><p>So that action isn&#x27;t free from &quot;stepping on each other toes&quot; too.</p><p>Moving a single slide involves other slides: their positions and contents too.</p><p>This again, does not feel right, isn&#x27;t it?</p><p>Of course, we could still bet on delegating that to infrastructure level and use optimistic concurrency with retries, but under the skin it feels there&#x27;s something more.</p><p>Should we again work on the model level?</p><h3 id="rethinking-a-solution-2"><a href="#rethinking-a-solution-2" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Rethinking a solution #2</h3><p>If changing the title is independent from reordering slides, maybe we could isolate that responsibility?</p><p>We would then create yet another solution.</p><p>In some scenarios, a single <code>Slide</code> model was doing great - especially when it came to updating its contents (and possibly with speaker notes too).</p><p>But that model wasn&#x27;t enough when we explored operations spanning multiple <code>Slide</code>s - like reordering.</p><p>Related logic (knowledge, &quot;ifs&quot;) manifested itself in &quot;the application level&quot;, where commands/queries (or application services) live typically.</p><p>An avid designer might take this &quot;problem&quot; as a diagnostic signal, a symptom.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Complexity does not disappear, it gets moved.</p></div></div></div><p>We could use <a href="https://particular.net/blog/antirequirements">anti-requirements</a> heuristic and check the rules - if there are any of these that require both slide position <strong>and</strong> its content, at the same time.</p><p>For example: how probable is it that we wouldn&#x27;t be able to move a slide if it contains, e.g. five rectangles?</p><p>Or another case, what about the rule: &quot;only slides having images with size lower than 5MB can be moved&quot;?</p><p>It sounds silly, isn&#x27;t it?</p><p>Yet another diagnostic signal to incorporate in our designing process.</p><p>Should we <a href="https://talesfrom.dev/blog/the-ambiguity-of-software-architecture">reorganize responsibilities</a> differently, again?</p><p>If reordering was &quot;a weak point&quot; of single <code>Slide</code>, maybe a <code>SlideDeck</code> will be a good fit for it?</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/bounded-contexts-from-compile-time-hierarchies-to-runtime-composition-two-models.png" class="max-h-[24rem]"/></div><div class="italic mx-24">Slide deck and slides as separate concepts</div></div><p>In this design, a <code>Slide</code> knows to which deck it belongs to and what its contents are (along with related speaker notes).</p><p>Contrary to that, a <code>SlideDeck</code> knows its title and what is the correct ordering (represented by a position, e.g. 1) of each slide (represented as slide identifier, e.g. &quot;S-3012&quot;).</p><p>Now, a <code>Slide</code> got a little slimmer:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">class</span> <span class="token class-name">Slide</span> <span class="token punctuation">{</span>
</span><span class="code-line">    slideId<span class="token operator">:</span> SlideId<span class="token punctuation">;</span>
</span><span class="code-line">    deckId<span class="token operator">:</span> DeckId<span class="token punctuation">;</span>
</span><span class="code-line">    content<span class="token operator">:</span> Content<span class="token punctuation">;</span>
</span><span class="code-line">    notes<span class="token operator">:</span> Notes<span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token function">updateContent</span><span class="token punctuation">(</span>content<span class="token operator">:</span> Content<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">// ...</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token function">updateNotes</span><span class="token punctuation">(</span>notes<span class="token operator">:</span> Notes<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">// ...</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token function">duplicate</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token punctuation">{</span> notes<span class="token operator">:</span> Notes<span class="token punctuation">,</span> content<span class="token operator">:</span> Content <span class="token punctuation">}</span> <span class="token punctuation">{</span> <span class="token comment">// 👈 we&#x27;re duplicating only contents and notes</span>
</span><span class="code-line">        <span class="token comment">// ...</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>There&#x27;s no knowledge about its position. Shall we check <code>SlideDeck</code>?</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">class</span> <span class="token class-name">SlideDeck</span> <span class="token punctuation">{</span>
</span><span class="code-line">    deckId<span class="token operator">:</span> DeckId<span class="token punctuation">;</span>
</span><span class="code-line">    title<span class="token operator">:</span> Title<span class="token punctuation">;</span>
</span><span class="code-line">    slidePositions<span class="token operator">:</span> <span class="token punctuation">{</span> slideId<span class="token operator">:</span> SlideId<span class="token punctuation">,</span> position<span class="token operator">:</span> PositiveInt <span class="token punctuation">}</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token function">appendSlide</span><span class="token punctuation">(</span>slideId<span class="token operator">:</span> SlideId<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token punctuation">{</span> position<span class="token operator">:</span> PositiveInt <span class="token punctuation">}</span> <span class="token punctuation">{</span> <span class="token comment">// 👈 we renamed &quot;addSlide&quot; to &quot;appendSlide&quot;</span>
</span><span class="code-line">        <span class="token comment">// ...</span>
</span><span class="code-line">    <span class="token punctuation">}</span><span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token function">deleteSlide</span><span class="token punctuation">(</span>slideId<span class="token operator">:</span> SlideId<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">// ...</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token function">insertSlide</span><span class="token punctuation">(</span>slideId<span class="token operator">:</span> SlideId<span class="token punctuation">,</span> position<span class="token operator">:</span> PositiveInt<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span> <span class="token comment">// 👈 a new method</span>
</span><span class="code-line">        <span class="token comment">// ...</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token function">moveSlide</span><span class="token punctuation">(</span>slideId<span class="token operator">:</span> SlideId<span class="token punctuation">,</span> newPosition<span class="token operator">:</span> PositiveInt<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">// ...</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token function">moveSlides</span><span class="token punctuation">(</span>slideIds<span class="token operator">:</span> SlideId<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span> newPosition<span class="token operator">:</span> PositiveInt<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">// ...</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token function">updateTitle</span><span class="token punctuation">(</span>newTitle<span class="token operator">:</span> Title<span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">// ...</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>In this configuration, <code>SlideDeck</code> knows how to reorder slides, based on the needs.</p><p>Also, there&#x27;s no collision when it comes to modifying slide&#x27;s content and move it in the deck, at the same time - in complete isolation.</p><p>An avid reader might notice that all operations we saw and examined so far, are related to changing the state of the system.</p><p>Moving a slide, updating its contents, changing slide deck&#x27;s title, etc. - all of these aim at state change.</p><p>Both <code>Slide</code> and <code>SlideDeck</code> are responsible to make decisions, based on the responsibilities we assigned to each of them.</p><h3 id="strange-bug"><a href="#strange-bug" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Strange bug</h3><p>Imagine we deployed the new model (or rather - models, because there are two), which made Tom and his crew amazed.</p><p>There were no &quot;stepping on each other toes&quot;, Tom could employ his creative workflow and his assitants were putting required details.</p><p>When he felt that some slides were fitting elswhere, in the narrative, he just moved them, trusting that the system does its job to ensure the consistency.</p><p>Everything worked smoothly, until one day...</p><p>...When he decided to rename his presentation title from &quot;Inspiring Business Topic&quot; to &quot;Inspiring Business Topic - 2025 Edition&quot;.</p><p>But the operation failed saying something like &quot;Cannot change the title&quot;, giving the option to retry.</p><p>Tom did so, but because he&#x27;s a curious being, he decided to ask his assistant if he changed something.</p><p>&quot;Hmmm, at that time I moved 7 slides related to estimations after team topologies part, as you wished&quot; - the assitant replied.</p><p>Tom was puzzled.</p><p>He brought those concerns to us, and we can start tinkering around the problem.</p><p>Strange.</p><p>Tom and his assistant changed the title and reordered slides, at the same time.</p><p>Hmm, we&#x27;ve never asked Tom whether changing the title has any constraints related to slide ordering.</p><p>The best way to remove assumptions is to collaborate with people, directly.</p><p>Imagine that we called Tom and asked an <a href="https://particular.net/blog/antirequirements">anti-requirement</a> question: <em>Should we make a rule that whenever a title is longer than 40 characters we cannot move slides?</em></p><div class="flex flex-col "><div class="flex flex-col"><div class="flex justify-center items-center flex-col"><div class="flex max-sm:flex-col justify-between items-center"><img src="https://talesfrom.dev/static/images/business-man.png" class="max-h-[30rem]"/><div class="flex flex-col justify-between text-left"><span>Tom says:</span><span class="my-4 italic"><span class=""><p>That would be silly, right?</p></span><div class="my-3"><span class="">I don&#x27;t get </span><span class="mr-2">why would the title length affect moving slides?</span></div><span class=""><p>I don&#x27;t see any reason for that.</p></span><div class="my-3"><span class="">In my mind, </span><span class="mr-2">changing the title is independent from reordering slides.</span></div><span class=""><p>Can we fix it, please?</p></span></span></div></div></div></div><div class="flex justify-around mt-10 lg:mx-32"><button class="bg-gray-600 border-gray-100 text-gray-400 p-2 rounded">Just talk</button><button class="bg-green-700 text-white border-2 p-2 rounded">Listening carefully</button></div></div><p>Well, that&#x27;s a clear answer!</p><p>It seems we need to rethink our model(s) again.</p><h3 id="rethinking-a-solution-3"><a href="#rethinking-a-solution-3" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Rethinking a solution #3</h3><p>If changing the title is independent from reordering slides, maybe we could isolate that responsibility?</p><p>We would then create a new model - third one.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/bounded-contexts-from-compile-time-hierarchies-to-runtime-composition-three-models.png" class="max-h-[24rem]"/></div><div class="italic mx-24">A new model emerged - slides ordering</div></div><p>New organization of responsibilities yields very interesting qualities - with this design, Tom can change the title of the slide deck, while his assistant can reorder slides, at the same time.</p><p>We explicitly represented the knowledge about slides ordering in its own model.</p><p>Such model was not explicitly communicated through conversations, but rather emerged from observing our struggles (or rather previous models struggles).</p><p>It was &quot;living&quot; there implicitly, until we found out that it truly makes sense to manifest it explicitly.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">class</span> <span class="token class-name">SlidesOrdering</span> <span class="token punctuation">{</span>
</span><span class="code-line">    deckId<span class="token operator">:</span> DeckId<span class="token punctuation">;</span>
</span><span class="code-line">    slidePositions<span class="token operator">:</span> <span class="token punctuation">{</span> slideId<span class="token operator">:</span> SlideId<span class="token punctuation">,</span> position<span class="token operator">:</span> PositiveInt <span class="token punctuation">}</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token function">appendSlide</span><span class="token punctuation">(</span>slideId<span class="token operator">:</span> SlideId<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token punctuation">{</span> position<span class="token operator">:</span> PositiveInt <span class="token punctuation">}</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">// ...</span>
</span><span class="code-line">    <span class="token punctuation">}</span><span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token function">deleteSlide</span><span class="token punctuation">(</span>slideId<span class="token operator">:</span> SlideId<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">// ...</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token function">insertSlide</span><span class="token punctuation">(</span>slideId<span class="token operator">:</span> SlideId<span class="token punctuation">,</span> position<span class="token operator">:</span> PositiveInt<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span> <span class="token comment">// 👈 a new method</span>
</span><span class="code-line">        <span class="token comment">// ...</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token function">moveSlide</span><span class="token punctuation">(</span>slideId<span class="token operator">:</span> SlideId<span class="token punctuation">,</span> newPosition<span class="token operator">:</span> PositiveInt<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">// ...</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token function">moveSlides</span><span class="token punctuation">(</span>slideIds<span class="token operator">:</span> SlideId<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span> newPosition<span class="token operator">:</span> PositiveInt<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">// ...</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p><code>SlidesOrdering</code> provides capabilities related to managing slides positions within the deck, whereas <code>SlideDeck</code> is now only responsible for its identity and title.</p><p><code>Slide</code>s remain unchanged - each of them keep track of its contents and notes.</p><p>Those models are isolated enough to allow concurrent modifications without &quot;stepping on each other&#x27;s toes&quot;.</p><p>Although there is one capability of the system that now spans multiple models - duplicating a slide.</p><p>When duplicating a slide, we need to duplicate its contents and notes (handled by <code>Slide</code>), and also insert a new slide in the ordering (handled by <code>SlidesOrdering</code>).</p><p>This is the moment when we are composing their capabilities in runtime:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">DuplicateSlideContext</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
</span><span class="code-line">    slidesRepository<span class="token operator">:</span> ForLoadingSlide <span class="token operator">&amp;</span> ForSavingSlide<span class="token punctuation">,</span>
</span><span class="code-line">    slidesOrderingRepository<span class="token operator">:</span> ForLoadingSlidesOrdering <span class="token operator">&amp;</span> ForSavingSlidesOrdering<span class="token punctuation">,</span>
</span><span class="code-line">    uuid<span class="token operator">:</span> ForGeneratingUuids
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token function function-variable">duplicateSlide</span> <span class="token operator">=</span> <span class="token punctuation">(</span>context<span class="token operator">:</span> DuplicateSlideContext<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token keyword">async</span> <span class="token punctuation">(</span>deckId<span class="token operator">:</span> DeckId<span class="token punctuation">,</span> slideId<span class="token operator">:</span> SlideId<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token builtin">Promise</span><span class="token operator">&lt;</span><span class="token punctuation">{</span> newSlideId<span class="token operator">:</span> SlideId<span class="token punctuation">,</span> position<span class="token operator">:</span> PositiveInt <span class="token punctuation">}</span><span class="token operator">&gt;</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">const</span> slide <span class="token operator">=</span> <span class="token keyword">await</span> context<span class="token punctuation">.</span>slidesRepository<span class="token punctuation">.</span><span class="token function">getBy</span><span class="token punctuation">(</span><span class="token punctuation">{</span> deckId<span class="token punctuation">,</span> slideId <span class="token punctuation">}</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token keyword">const</span> slidesOrdering <span class="token operator">=</span> <span class="token keyword">await</span> context<span class="token punctuation">.</span>slidesOrderingRepository<span class="token punctuation">.</span><span class="token function">load</span><span class="token punctuation">(</span>deckId<span class="token punctuation">)</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">const</span> <span class="token punctuation">{</span> notes<span class="token punctuation">,</span> content <span class="token punctuation">}</span> <span class="token operator">=</span> slide<span class="token punctuation">.</span><span class="token function">duplicate</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token keyword">const</span> newSlideId <span class="token operator">=</span> context<span class="token punctuation">.</span>uuid<span class="token punctuation">.</span><span class="token function">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token keyword">const</span> newSlide <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Slide</span><span class="token punctuation">(</span><span class="token punctuation">{</span> slideId<span class="token operator">:</span> newSlideId<span class="token punctuation">,</span> deckId<span class="token punctuation">,</span> notes<span class="token punctuation">,</span> content <span class="token punctuation">}</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token keyword">await</span> context<span class="token punctuation">.</span>slidesRepository<span class="token punctuation">.</span><span class="token function">save</span><span class="token punctuation">(</span>newSlide<span class="token punctuation">)</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">const</span> <span class="token punctuation">{</span> position <span class="token punctuation">}</span> <span class="token operator">=</span> slidesOrdering<span class="token punctuation">.</span><span class="token function">insertSlide</span><span class="token punctuation">(</span>newSlideId<span class="token punctuation">,</span> slidesOrdering<span class="token punctuation">.</span><span class="token function">getPositionAfter</span><span class="token punctuation">(</span>slideId<span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token keyword">await</span> context<span class="token punctuation">.</span>slidesOrderingRepository<span class="token punctuation">.</span><span class="token function">save</span><span class="token punctuation">(</span>slidesOrdering<span class="token punctuation">)</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">return</span> <span class="token punctuation">{</span> newSlideId<span class="token punctuation">,</span> position <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p><code>duplicateSlide</code> command coordinates the work between two models - <code>Slide</code> and <code>SlidesOrdering</code> - to fulfill the use case.</p><p>Based on our past experiences, that operation is a bit tricky, as it spans multiple models, which might make concurrent state changes a bit challenging.</p><p>Saving a new slide might succeed, but saving the updated slides ordering might fail due to optimistic concurrency violation.</p><p>This is something that we could consult with Tom and his crew - what are the consequences of restoring the slides ordering, let&#x27;s say in 30 seconds?</p><p>Or what would happen if the slides ordering is restored, but after 2 minutes?</p><p>We definitely should ask Tom about his workflow and tolerance for such situations - maybe he could accept a slight delay, especially that there are multiple rounds of refining the presentation.</p><p>This would allow us, instead of pursuing immediate consistency, letting the system arrive at full consistency, eventually.</p><p>Either change the slides ordering firstly, showing some kind of &quot;a skeleton slide&quot; without any content, and later fill in the contents.</p><p>Or create the slide with its contents, but without position in the ordering, and later insert it in the correct place.</p><p>It is not our sole responsibility to decide on that - we should collaborate with Tom to find the best fit for his workflow.</p><p>But the most important aspect is that we would have options - having autonomous models (please remember that &quot;autonomous&quot; does not mean &quot;isolated&quot;) allow us to explore different consistency strategies, depending on the needs.</p><p>We could also bet on immediate consistency, if Tom&#x27;s workflow requires that, but then of course we would need to handle potential concurrency violations, e.g. with retries and hope that it would get resolved in a reasonable amout of attempts.</p><h3 id="new-type-of-content"><a href="#new-type-of-content" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>New type of content!</h3><p>This is a true banger!</p><p>Finally, Tom is confident about the solution and started presenting his ideas to the world.</p><p>We&#x27;re (Tom, actually) getting customers, and Tom is happy.</p><p>One day, Tom came back with a new idea.</p><div class="flex flex-col "><div class="flex flex-col"><div class="flex justify-center items-center flex-col"><div class="flex max-sm:flex-col justify-between items-center"><img src="https://talesfrom.dev/static/images/business-man.png" class="max-h-[30rem]"/><div class="flex flex-col justify-between text-left"><span>Tom says:</span><span class="my-4 italic"><span class=""><p>Hi, I have a new idea!</p></span><span class=""><p>Product is doing great, people love it!</p></span><div class="my-3"><span class="">I got a question from IT audience, </span><span class="mr-2">are we able to support collaboration diagrams?</span></div><div class="my-3"><span class="">You know, those </span><span class="mr-2">boxes and arrows things</span><span class="">.</span></div><span class=""><p>What do you think about it?</p></span></span></div></div></div></div><div class="flex justify-around mt-10 lg:mx-32"><button class="bg-gray-600 border-gray-100 text-gray-400 p-2 rounded">Just talk</button><button class="bg-green-700 text-white border-2 p-2 rounded">Listening carefully</button></div></div><p>And he immediately sketched a rough idea of how it could look like:</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/bounded-contexts-from-compile-time-hierarchies-to-runtime-composition-ordering-capability.png" class="max-h-[24rem]"/></div><div class="italic mx-24">Low-fidelity glimpse of new content type - collaboration diagram</div></div><p>Well, it&#x27;s just a content type, right?</p><p>It shouldn&#x27;t be a big deal.</p><p>Hmmm, but what about those numbers in front of the labels, close to the arrows?</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/bounded-contexts-from-compile-time-hierarchies-to-runtime-composition-ordering-capability-highlighted.png" class="max-h-[24rem]"/></div><div class="italic mx-24">Labeled interactions between elements</div></div><p>Should we ask Tom about it?</p><div class="flex flex-col "><div class="flex flex-col"><div class="flex justify-center items-center flex-col"><div class="flex max-sm:flex-col justify-between items-center"><img src="https://talesfrom.dev/static/images/business-man.png" class="max-h-[30rem]"/><div class="flex flex-col justify-between text-left"><span>Tom says:</span><span class="my-4 italic"><div class="my-3"><span class="">Those are </span><span class="mr-2">sequence numbers</span><span class="">right?</span></div><span class=""><p>I have a brillant idea - we could squeeze even more value out of that new type of content!</p></span><div class="my-3"><span class="">We could allow </span><span class="mr-2">easy reordering</span><span class="">those interactions, people will be able to focus on sketching and then on </span><span class="mr-2">ordering</span><span class="">them correctly.</span></div><span class=""><p>The same workflow as I use for slides!</p></span><span class=""><p>What do you think?</p></span></span></div></div></div></div><div class="flex justify-around mt-10 lg:mx-32"><button class="bg-gray-600 border-gray-100 text-gray-400 p-2 rounded">Just talk</button><button class="bg-green-700 text-white border-2 p-2 rounded">Listening carefully</button></div></div><p>Strange, isn&#x27;t it?</p><p>An avid reader might notice that reordering interactions within collaboration diagram is very similar to reordering slides within slide deck.</p><p>Do we really care what are we reordering?</p><p>We could easily say that in some contexts things are indistinguishable - we can reorder slides, interactions, people, widgets, books, pages, etc.</p><p>Such capability looks quite agnostic to slides so maybe we could distill even more reusable model?</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/bounded-contexts-from-compile-time-hierarchies-to-runtime-composition-ordering-capability-distillation.png" class="max-h-[30rem]"/></div><div class="italic mx-24">ItemsOrdering model covering two use cases</div></div><p>And that is how <code>ItemsOrdering</code> model emerged:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">class</span> <span class="token class-name">ItemsOrdering</span> <span class="token punctuation">{</span>
</span><span class="code-line">    collectionId<span class="token operator">:</span> CollectionId<span class="token punctuation">;</span>
</span><span class="code-line">    itemPositions<span class="token operator">:</span> <span class="token punctuation">{</span> itemId<span class="token operator">:</span> ItemId<span class="token punctuation">,</span> position<span class="token operator">:</span> PositiveInt <span class="token punctuation">}</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token function">appendItem</span><span class="token punctuation">(</span>itemId<span class="token operator">:</span> ItemId<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token punctuation">{</span> position<span class="token operator">:</span> PositiveInt <span class="token punctuation">}</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">// ...</span>
</span><span class="code-line">    <span class="token punctuation">}</span><span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token function">deleteItem</span><span class="token punctuation">(</span>itemId<span class="token operator">:</span> ItemId<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">// ...</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token function">insertItem</span><span class="token punctuation">(</span>itemId<span class="token operator">:</span> ItemId<span class="token punctuation">,</span> position<span class="token operator">:</span> PositiveInt<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">// ...</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token function">moveItem</span><span class="token punctuation">(</span>itemId<span class="token operator">:</span> ItemId<span class="token punctuation">,</span> newPosition<span class="token operator">:</span> PositiveInt<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">// ...</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token function">moveItems</span><span class="token punctuation">(</span>itemIds<span class="token operator">:</span> ItemId<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span> newPosition<span class="token operator">:</span> PositiveInt<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">// ...</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>This model can be used in various use cases, including both slide decks and collaboration diagrams.</p><p>The knowledge is kept inside of the single boundary, and we can compose its capabilities in runtime, depending on the needs.</p><p>An avid reader might notice that this model - <code>ItemsOrdering</code> - is completely ignorant about what kind of items it is ordering.</p><p>There is no notion about slides - that is the responsibility of &quot;someone else&quot;, to <strong>give meaning</strong> to those items.</p><p>It can be either <code>duplicateSlide</code> slide command we saw earlier, or maybe <code>moveInteraction</code> command for collaboration diagrams.</p><p>Such translation might happen, at runtime - <code>ForLoadingSlidesOrdering</code> required capability by <code>duplicateSlide</code> use case (application level), provided by, e.g. <code>SlidesOrderingRepository</code>, would do such translation.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">class</span> <span class="token class-name">SlidesOrderingRepository</span> <span class="token keyword">implements</span> <span class="token class-name">ForLoadingSlidesOrdering</span><span class="token punctuation">,</span> ForSavingSlidesOrdering <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// ...</span>
</span><span class="code-line">    <span class="token keyword">async</span> <span class="token function">load</span><span class="token punctuation">(</span>deckId<span class="token operator">:</span> DeckId<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token builtin">Promise</span><span class="token operator">&lt;</span>SlidesOrdering<span class="token operator">&gt;</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">const</span> itemsOrdering <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token keyword">this</span><span class="token punctuation">.</span>itemsOrderingStorage<span class="token punctuation">.</span><span class="token function">load</span><span class="token punctuation">(</span><span class="token punctuation">{</span> collectionId<span class="token operator">:</span> CollectionId<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span>deckId<span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">SlidesOrdering</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
</span><span class="code-line">            deckId<span class="token punctuation">,</span>
</span><span class="code-line">            slidePositions<span class="token operator">:</span> itemsOrdering<span class="token punctuation">.</span>itemPositions<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>ip <span class="token operator">=&gt;</span> <span class="token punctuation">(</span><span class="token punctuation">{</span> slideId<span class="token operator">:</span> ip<span class="token punctuation">.</span>itemId<span class="token punctuation">,</span> position<span class="token operator">:</span> ip<span class="token punctuation">.</span>position <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">}</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token comment">// ...</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p><code>duplicateSlide</code> command would remain unchanged, still coordinating the work between <code>Slide</code> and <code>SlidesOrdering</code>.</p><p>But the most important part is that we have options to pick from.</p><h3 id="where-is-the-presentation"><a href="#where-is-the-presentation" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Where is the presentation?</h3><p>&quot;Ok Damian, but where is the presentation now? I only see slide deck, slides, slide ordering&quot; - you might ask, dear Reader.</p><p>It is everywhere and nowhere at the same time.</p><p>Presentation that is visible in the screen (along with slides and their contents, speaker notes), ordered correctly, with title &quot;Inspiring Business Topic - 2025 Edition&quot; - everything is composed together, at runtime.</p><p>Of course, there might be other techniques to prepare such view model more efficiently, etc. but the main point is that it gets composed from multiple, autonomous models.</p><p>Many contexts contribute into &quot;a concept&quot; of presentation - each of them support a separate <a href="https://talesfrom.dev/blog/context-segregation-principle">perspective</a> of it.</p><p>Each context establishes a boundary, providing a set of capabilities, and encapsulating related knowledge (and language).</p><p>The most important aspect is that those contexts can coexist and evolve independently, without &quot;stepping on each other&#x27;s toes&quot;.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/bounded-contexts-from-compile-time-hierarchies-to-runtime-composition-a-presentation.png" class="max-h-[24rem]"/></div><div class="italic mx-24">&quot;A concept&quot; of presentation that is composed of many perspectives, related to contextual models providing certain capabilities.</div></div><p>Of course, we&#x27;ve seen that there are some use cases that might span multiple contexts, but it is our decision to compose them on our terms, not how models dictate so.</p><p>Throughout the whole tale, we were able to observe how compile-time composition (compile-time hierarchies) gave us struggles and challenges, especially when it comes to problems related to concurrent/competetive/collaborative problems.</p><p>We used all the occurring problems as diagnostic signals - feedback - and we were able to rethink our models, reorganizing responsibilities, distilling new models, until we reached satisfying level of autonomy (which does not mean isolation).</p><p>In a way, we moved from <a href="https://talesfrom.dev/blog/the-ambiguity-the-curse-and-the-fallacy-of-domain-model"><strong>the</strong> domain model</a> into a set of models that can be composed at runtime.</p><p>Each of &quot;the components&quot; (<a href="https://talesfrom.dev/blog/time-angle-and-depth-dimensions-in-software-design">a perspective</a>, <a href="https://talesfrom.dev/blog/context-segregation-principle">a context</a>) of a presentation: &quot;slide deck&quot; (providing title), &quot;slides&quot; (providing contents and notes) and &quot;items ordering&quot; (providing proper sequencing of slides) - are autonomous enough to allow concurrent modifications and independent evolution.</p><p>Whenever there will be another capability required, we should evaluate whether it fits into existing contexts, or maybe we should distill a new one.</p><h3 id="itemsordering---pure-fabrication"><a href="#itemsordering---pure-fabrication" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>ItemsOrdering - pure fabrication?</h3><p><a href="https://en.wikipedia.org/wiki/GRASP_(object-oriented_design)">GRASP</a> defines a concept of <em>a pure fabrication</em>:</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">Pure Fabrication</div><div class="pb-2 px-3"><div class="break-words"><p>A pure fabrication is a class that does not represent a concept in the problem domain, specially made up to achieve low coupling, high cohesion, and the reuse potential thereof derived (when a solution presented by the information expert pattern does not).</p></div></div></div><p>So in a way, Tom has never mentioned anything about &quot;items ordering&quot;, at least explicitly.</p><p>Initially, we started with &quot;slides ordering&quot;, but when we hit another variation of the same problem - it turned out that both use cases required a common capability.</p><p>By observing <code>SlidesOrdering</code> and potential <code>InteractionsOrdering</code> (for collaboration diagrams), we noticed that neither of them were &quot;true&quot; <a href="https://talesfrom.dev/blog/the-ambuiguity-of-abstraction">abstractions</a> - they &quot;abstracted away&quot; only parts of the details.</p><p>When we started asking different questions, we were able to spot that in certain contexts it does not really matter what is being ordered - this actually allowed us to distill <code>ItemsOrdering</code> model, which abstracted the details even more, completely changing the level on which one operates.</p><p>&quot;But we already had it - SlideDeck!&quot; - someone might say.</p><p>Well, yes and no.</p><p><code>SlideDeck</code> composed multiple perspectives in compile-time - which made concurrent workflows challenging.</p><p>Additionally, <code>SlideDeck</code> encapsulated too much knowledge, making it less cohesive, which directly contributed to <a href="https://talesfrom.dev/blog/the-knowledge-gravity-problem">the knowledge gravity problem</a>.</p><p><a href="https://talesfrom.dev/blog/the-ambiguity-of-naming">Naming is framing</a> - the name, <code>SlideDeck</code>, would frame one&#x27;s thinking so that whenever there will be a need, one would try to fit the new requirements into existing model, rather than exploring new possibilities.</p><p><code>SlideDeck</code> would grow, grow and grow, and become even bigger compile-time hierarchy, attracting more knowledge.</p><p>So moving &quot;ordering capability&quot; into a separate boundary, encapsulating knowledge (rules, information required to make decisions) explicitly, allowed us to isolate that &quot;component&quot;.</p><p>In fact, everything boiled down to <a href="https://talesfrom.dev/blog/the-ambiguity-of-software-architecture">a certain way of organizing responsibilities to achieve desired qualities and goals</a>.</p><p>As you saw, dear Reader, we were able to walk through different designs, exploring various options (and related trade-offs), knowing that each of the models might bring a certain <a href="https://talesfrom.dev/blog/the-cost-of-modeling">cost of modelling</a>.</p><p>The abstractions (<a href="https://talesfrom.dev/blog/time-angle-and-depth-dimensions-in-software-design">perspectives</a>) we&#x27;ve found, opened possibilities to move <a href="https://talesfrom.dev/blog/from-concepts-to-architecture">from concepts to architecture</a>.</p><h3 id="from-compile-time-hierarchies-to-runtime-composition"><a href="#from-compile-time-hierarchies-to-runtime-composition" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>From compile-time hierarchies to runtime composition</h3><p>Phew, that was a hell of a journey, wasn&#x27;t it?</p><p>We started with a single model - <code>SlideDeck</code> - encapsulating all the knowledge about slide decks, slides, their contents, notes, ordering, etc.</p><p>We initially tried to model &quot;the absolute&quot; concept of presentation, that we could visualize on the screen.</p><p>Slowly but steadily, we visited various options and arrived at the point where we have many contextual models in our inventry so that we can compose them as we want.</p><p>I know that we faced a toy example and of course you, dear Reader, might be dealing with much more complicated and sophisticated domains - a simple slide deck might be &quot;too easy&quot;.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Simplicity often mean making more things, not fewer</p></div></div></div><p>Nevertheless, it&#x27;s all about the way of thinking - whether we try to see beyond compile-time hierarchies and embrace runtime composition of autonomous models.</p><p>Next time, when you face a problem that seems to be solvable,e.g. only on the infrastructure level, ask yourself, dear Reader:</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>Is there an abstract idea that I might need to represent explicitly?</p></div></div></div>]]></content:encoded>
    <pubDate>Tue, 09 Dec 2025 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>software engineering</category><category>software design</category><category>object-oriented design</category><category>modularity</category><category>design patterns</category><category>language patterns</category><category>software quality</category><category>knowledge working</category><category>modularity</category><category>modular monolith</category><category>boundaries</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/boundaries-modularity-and-a-diaper-effect</guid>
    <title>Boundaries, modularity and a diaper effect</title>
    <link>https://talesfrom.dev/blog/boundaries-modularity-and-a-diaper-effect</link>
    <description>What is a diaper effect when it comes to software design?</description>
    <content:encoded><![CDATA[<h3 id="look-at-this-magnificent-cathedral"><a href="#look-at-this-magnificent-cathedral" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Look at this magnificent cathedral!</h3><p>Imagine that two architects - <span class="italic font-bold text-yellow-300">Alex</span> and <span class="italic font-bold text-blue-300">Adam</span> - discuss a potential architecture for a new part of the system.</p><p>The main idea is to modernize technology, as it is pretty outdated and brings friction.</p><p>For sure there will be k8s, event-driven architecture and possibly gRPC - because it&#x27;s fast.</p><p>&quot;But what the system does?&quot;, some might ask in their curious minds.</p><p>Well, it is a system for managing local guided tours - <span class="italic font-bold text-yellow-300">Alex</span> was assigned to architect it.</p><p>This pair review process aims at ensuring that the architecture is well thought through, and that both architects agree on the proposed solution, and workers, I mean, software engineers will be able to deliver it.</p><p>That is how it <a href="https://talesfrom.dev/blog/the-ambiguity-of-team-work">works</a>, right?</p><p>Architects architect, developers develop.</p><p><span class="italic font-bold text-yellow-300">Alex</span> brings the diagram created in Miro board and starts the conversation:</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>I made required analysis of all the language stakeholders used, took all existing database schema and it found out that we will need: Tours, Participants and Guides subsystems.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-blue-300">Adam, an architect:</span><span>I do like that you didn&#x27;t create more than needed - it was called Ockham&#x27;s razor, right?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>Exactly! Each subsystem will be responsible for its own data and logic. For example, the Tours subsystem will manage tour creation, scheduling, and details. The Participants subsystem will handle participant registration, profiles, and preferences. The Guides subsystem will oversee guide assignments, availability, and ratings.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-blue-300">Adam, an architect:</span><span>Sounds good. How will these subsystems communicate with each other?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>We will use event-driven architecture. Each subsystem will publish events when significant actions occur, and other subsystems can subscribe to these events to stay updated. Also, for more direct communication we will use gRPC, because it is faster than REST</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-blue-300">Adam, an architect:</span><span>Yes, great that you thought about using gRPC - many times we proved that REST services are pain in the ass - serializing and deserializing JSON over and over is so old-fashioned way</span></div></span></div><p>Architecture pair review was over, rates were given, &quot;The Corporate Architecture Guild&quot;™️ approved the design, as it was modular, reinforcing important terms living in the local tourism domain.</p><h3 id="why-so-many-changes"><a href="#why-so-many-changes" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Why so many changes?</h3><p>Three teams were organized - each for the subsystem.</p><p>Kick-off happened, development started, feature factory rushed producing software.</p><p>Even <a href="https://talesfrom.dev/blog/code-knowledge-ai">&quot;AI&quot;</a> was employed to increase productivity.</p><p>Enormous amounts of code was generated, but sooner rather than later, things started slowing down.</p><p>Even though there were only three modules, they interacted with each other in so many different ways, making a seemingly simple change a nightmare to introduce.</p><p>That made teams overcoordinating, blocking releases and making agility only on paper and daily standups (which were coordinated, by the way).</p><p>Lost payments, tours without guides, unplanned tours - all these issues started to pile up.</p><p><span class="italic font-bold text-yellow-300">Alex, an architect</span> was called to investigate what was going on.</p><p>He decomposed solution into modules, he paid attention to the language of stakeholders - but what was wrong?</p><p>Wasn&#x27;t DDD supposed to help with that?</p><p>Tour, Participants, Guides - all these concepts were clearly defined in the language of stakeholders and have been represented in the code!</p><p>Isn&#x27;t a domain model supposed to help with modularity?</p><p><span class="italic font-bold text-yellow-300">Alex, an architect</span> felt that he got tricked.</p><h3 id="the-ambiguity-the-curse-and-the-fallacy-of-domain-model"><a href="#the-ambiguity-the-curse-and-the-fallacy-of-domain-model" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a><a href="https://talesfrom.dev/blog/the-ambiguity-the-curse-and-the-fallacy-of-domain-model">The ambiguity, the curse and the fallacy of domain model</a></h3><p>Modularity - the holy grail of software design.</p><p>Who does not want to have modularized system, with clear boundaries, low coupling and high cohesion?</p><p>Often times, it ends up being a mirage, living in the PowerPoint slides, Miro boards and architecture decision records.</p><p>&quot;It was decided that system will be modular&quot; - sounds good, but what does it really mean?</p><p>Turns out that modularity hardly manifests itself while observing things standing still, motionless.</p><p>Drawing boxes, arrows between them, defining interfaces - all these activities are necessary, but not sufficient.</p><p>Let&#x27;s use the tool for testing the design - <em>a change</em>.</p><p>What will be the impact of a given change?</p><p>How many modules will be affected?</p><p>How many teams will need to be involved?</p><p>Ultimate goal is reducing the blast radius of a change, the need for coordination and cognitive load on developers (of course, it all depends so that&#x27;s why we use <a href="https://talesfrom.dev/blog/the-ambiguity-of-software-architecture">software architecture</a> to tackle that, right?).</p><p>Autonomous teams.</p><p>Autonomous modules.</p><p>Autonomous models.</p><p>So the real deal is establishing boundaries that will yield certain quality attributes.</p><p>But why Alex&#x27;s design faced challenges?</p><p><a href="https://talesfrom.dev/blog/the-ambiguity-the-curse-and-the-fallacy-of-domain-model">Compile-time hierarchies</a> was one of the main reasons - pursuing &quot;the reality&quot;, not taking into account <a href="https://talesfrom.dev/blog/context-segregation-principle">perspectives</a> and <a href="https://talesfrom.dev/blog/time-angle-and-depth-dimensions-in-software-design">time</a>, and more.</p><p>Single domain model encompassing all the aspects, in compile-time, makes <a href="https://talesfrom.dev/blog/the-knowledge-gravity-problem">knowledge gravity</a> mercilessly manifesting itself with every change.</p><p>Instead of composing perspectives in runtime, Alex focused on &quot;absolute&quot; concepts, ignoring real abstractions.</p><h3 id="a-diaper"><a href="#a-diaper" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>A diaper</h3><p>One of the most crucial aspects of any module is its boundaries.</p><p>Boundaries define what is inside and what is outside.</p><p>What are provided capabilities (<a href="https://talesfrom.dev/blog/the-ambiguity-of-interfaces">interfaces</a>) for its consumers and what is hidden (<a href="https://talesfrom.dev/blog/the-ambiguity-of-encapsulation">implementation details</a>) from its consumers.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/boundaries-modularity-and-a-diaper-effect-diaper.png" class="max-h-[24rem]"/></div><div class="italic mx-24">A diaper?</div></div><p>A diaper is quite a nice model for understanding boundaries, and problems that can arise when boundaries are not well defined and designed.</p><p>As with every model or metaphor, it is designed to be imperfect, highlighting certain aspects, while ignoring others (did I just described abstracting process?)</p><p>Nevertheless, a diaper has clear <a href="https://talesfrom.dev/blog/composing-a-pie">purposes</a> - keep things that are supposed to be inside, inside, and do not let them leak outside.</p><p>It has pretty well defined interfaces, with stated capabilities - absorb liquids, contain waste, fasteners to keep it in place.</p><p>And a big deal of a module, I mean a diaper, is that it should be easily changeable - when it is full, it should be replaced with a new one, without much hassle.</p><p>So whenever a change happens, it should be easy job to be performed.</p><p>When we look at diapers when they are unused and there are no changes, they are clean, dry, nicely looking.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/boundaries-modularity-and-a-diaper-effect-clean-diapers.png" class="max-h-[24rem]"/></div><div class="italic mx-24">An architecture of system modules</div></div><p>Motionlessly laying down, one can&#x27;t state anything about how the boundaries will behave and be protected.</p><p>Until...</p><h3 id="a-diaper-effect"><a href="#a-diaper-effect" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>A diaper effect</h3><p>...A change happens.</p><p>Parents know that changing a diaper is not a walk in the park.</p><p>Sometimes it is easy, sometimes it is messy.</p><p>Similar to working with modules - when a change is introduced, the entire architecture is put to the stress test.</p><p>And the nightmare begins when modules start leaking.</p><p>When one needs to touch many, many places to adjust the system&#x27;s behavior, we are in the big trouble.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/boundaries-modularity-and-a-diaper-effect-touching.png" class="max-h-[24rem]"/></div><div class="italic mx-24">A brave architect trying to adjust the system after introducing a change</div></div><p>And that is what I call <em>a diaper effect</em> - when models leak, boundaries are established incorrectly (according to the context we are currently operating in), and modules become entangled.</p><p>They become entangled because of the shared, leaked knowledge (if you haven&#x27;t, please grab a copy of <a href="https://www.amazon.com/Balancing-Coupling-Software-Design-Addison-Wesley-ebook/dp/B09RV3Z3TP">Balancing Coupling</a> by <a href="https://vladikk.com/">Vlad Khononov</a>, it will change how you think about designing systems!).</p><p>Such leaked knowledge creates hidden dependencies between modules, due to <a href="https://talesfrom.dev/blog/the-knowledge-gravity-problem">knowledge gravity</a>.</p><p>Each change leaks into many modules, requiring coordination, excessive testing of the entire system, and making delivery slow and painful.</p><p>Seemingly unimportant knowledge that gets located in the wrong module, not represented at all, or represented in two or more modules, makes the necessity to <em>touch</em> many places when a change is introduced.</p><h3 id="counteracting-a-diaper-effect"><a href="#counteracting-a-diaper-effect" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Counteracting a diaper effect?</h3><p>We don&#x27;t need to wrestle with big systems to learn how to avoid a diaper effect.</p><p>Firstly, let&#x27;s start learning how to modularize things in the lower levels - application level.</p><p>How to ensure that objects interact with each other in a way, that limits the scope of change?</p><p>How to ensure that interaction participants have clean interfaces, based on needs, and they follow the correct protocol of communication/interaction?</p><p>If you can&#x27;t modularize in a small scale, how would you do that in a big one?</p><p><a href="https://www.youtube.com/watch?v=1FPsJ-if2RU">The art of destroying software</a> is a great starter too.</p><p>&quot;Write small things&quot; - easy job, ain&#x27;t it?</p><p>Putting jokes aside, definitely there are some heuristics one can employ to increase chances of avoiding a diaper effect and reduce potential problems.</p><p>Taking <a href="time-angle-and-depth-dimensions-in-software-design">software dimensions</a> into account might help - separating different perspectives, composing them in runtime, based on use cases.</p><p>Trying to escape <a href="https://talesfrom.dev/blog/the-inverse-matrix-problem">Inverse Matrix</a> might be also vital - seeing the world behind the code, understanding the real needs of stakeholders.</p><p>In general, paying attention to the business area in which we operate and we try to deliver software solutions for.</p><p>This also mean <strong>not</strong> following &quot;the reality&quot; blindly, but actually looking for abstractions that &quot;live&quot; in the given context.</p><p>Those abstractions - often are many different <a href="https://talesfrom.dev/blog/context-segregation-principle">perspectives</a> on the &quot;same thing&quot;, required in different moments of <a href="time-angle-and-depth-dimensions-in-software-design">time</a>.</p><p>Eventually, one might understand that there is no single domain model, but rather a set of domain models, each serving its own purpose.</p><p>Another great opportunity is to simulate potential changes and see how they would impact the system - have a playful attitude and put a stress test on the architecture.</p><p>You might see how boundaries break, where the knowledge gravity attracts more knowledge, and where the modules start leaking.</p><p>And what about Domain-Driven Design - weren&#x27;t it supposed to help with modularity?</p><p>Naive approaches, full of noun-based thinking, focusing on compile-time hierarchies, often lead to a diaper effect.</p><p>There are other <a href="https://talesfrom.dev/blog/modeling-maturity-levels">levels</a> from which we can model the domain, representing the knowledge.</p><p>Beware a diaper effect, dear Reader.</p><p>Beware the knowledge leaks!</p>]]></content:encoded>
    <pubDate>Wed, 03 Dec 2025 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>software engineering</category><category>software design</category><category>object-oriented design</category><category>modularity</category><category>design patterns</category><category>language patterns</category><category>software quality</category><category>knowledge working</category><category>modularity</category><category>modular monolith</category><category>boundaries</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/tdd-specify-satisfy-simplify</guid>
    <title>TDD: specify, satisfy, simplify</title>
    <link>https://talesfrom.dev/blog/tdd-specify-satisfy-simplify</link>
    <description>Why is it easy to miss the point of TDD?</description>
    <content:encoded><![CDATA[<div class="bg-slate-600 rounded-xl mt-10"><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Kudos! 🙏🏻</span></div><div class="pb-2 px-3"><div class="break-words"><p>I really want to thank <a href="https://twitter.com/GGalezowski">Grzegorz Gałęzowski</a> for patience, knowledge and sharing experience with me!</p>
<p>We have tons of discussions (or rather me asking a plethora of questions and learning from <a href="https://twitter.com/GGalezowski">Grzegorz Gałęzowski</a>), especially on Test-Driven Development and Object-Oriented Analysis &amp; Design.</p>
<p>Grzegorz also wrote a book - <a href="https://leanpub.com/tdd-ebook">Test-Driven Development: Extensive Tutorial</a> - you might find it interesting and useful!</p></div></div></div><h3 id="the-ambiguity-of-tdd"><a href="#the-ambiguity-of-tdd" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a><a href="https://talesfrom.dev/blog/the-ambiguity-of-tdd">The ambiguity of TDD</a></h3><p>&quot;2025 and people are still posting stuff about TDD?&quot; - some of Readers might think, seeing the title of this tale.</p><p>Developers can conjure applications without writing a single line of code, build with using English as &quot;a programming language&quot; (you know it isn&#x27;t true, do you?).</p><p>In the age of AI-assisted coding, TDD seems like a relic of the past, because AI can generate code for us, right?</p><p>Some time ago I wrote <a href="https://talesfrom.dev/blog/the-ambiguity-of-tdd">a tale</a> about TDD, trying to explain why &quot;TDD&quot; as a slogan is ambiguous and can lead to misunderstandings.</p><p>Writing tests <strong>after</strong> implementation is still a common practice, and many developers never grasped <em>idea</em> behind TDD, stating that &quot;writing tests first&quot; is just a waste of time.</p><p>As with other <a href="https://talesfrom.dev/blog/the-ambiguity-of-abstraction"><em>abstractions</em></a>, the concept, &quot;the symbol&quot; - TDD - takes away details, trying to amplify the essence.</p><p><em>Test-Driven Development</em> - &quot;using tests to drive development&quot; - what could possibly go wrong?</p><p>Many learn: &quot;write failing test, make it pass, refactor&quot;, which describe <em>how</em>, not capturing <em>what</em>.</p><p>TDD is an engineering discipline, a workflow, that is meant to create conditions, the environment, in which one can deliver high-quality software - combining both functional requirements and quality attributes like modularity and maintainability.</p><p>That&#x27;s why I deliberately <a href="https://talesfrom.dev/blog/the-ambiguity-of-tdd">decomposed</a> TDD into: verification and specification.</p><p>But those two perspectives are also &quot;artificial&quot;, mostly created to highlight those two important aspects of TDD.</p><h3 id="driven-by-specification"><a href="#driven-by-specification" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Driven by specification?</h3><p>Turns out that quite a lot of developers focus too much on tests themselves.</p><p>Tests are important, for sure, but they are materialization, an implementation, of something more abstract.</p><p>As well as &quot;tests&quot;, &quot;three steps&quot; - &quot;red, green refactor&quot; or &quot;write failing test, make it pass, refactor&quot; - feel like not telling the story completely.</p><p>And it might be that&#x27;s the case, as they are useful &quot;mnemonics&quot;, to get them easily remembered.</p><p>But <em>what</em> do they actually mean?</p><p>As with (business) capabilities - &quot;<strong>WHAT, not WHO and HOW</strong>&quot; - it would be nice to capture that <em>WHAT</em> of TDD.</p><p>Here comes <strong>3S</strong>, which stands for: <strong>specify, satisfy, simplify</strong>.</p><h3 id="specify"><a href="#specify" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Specify</h3><p>The first step is to <strong>specify</strong> the observable behavior, the expected results.</p><p>Such behavior specification must take the needs of the consumer, be it a human, a service, an object or a module, into account.</p><p>This is the moment when the miracle of &quot;<a href="https://talesfrom.dev/blog/i-interface">interface</a> discovery&quot; might actually happen - and one can observe <a href="https://jmock.org/oopsla2004.pdf">Need-Driven Development</a> in action.</p><p>Taking the consumers needs into account, treating it as an input (for both providing expected results and finding the &quot;just enough&quot; design), is one of the important ways for designign software, that greatly impacted and influenced me - <a href="https://www.amazon.com/Growing-Object-Oriented-Software-Guided-Tests/dp/0321503627">outside-in approach</a>.</p><p>But this requires one of the hardest things in software design: pretending to have a (wishful) amnesia and forgetting about the &quot;designers&quot; perspective (which strongly focuses on implementation details), putting oneself into the shoes of the consumer.</p><p>Such act of emphathy is hard, but crucial, and in a way it constitutes the essence of thinking like an engineer, a designer.</p><p>We can specify by writing tests, we can specify by writing bullet points or by drawing diagrams - no all of those <em>how</em>s will be automated and effective, but each will manifest <em>what</em> - the act of specifying.</p><p>The important part is to focus on <em>what</em> the consumer needs, not <em>how</em> it will be implemented.</p><h3 id="satisfy"><a href="#satisfy" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Satisfy</h3><p>The second step is to <strong>satisfy</strong> the needs, expressed through structured specification, with the easiest implementation of knowledge representation.</p><p>And by saying &quot;knowledge representation&quot;, I refer to <a href="https://talesfrom.dev/blog/the-ambiguity-of-application">applying our current understanding</a> of the problem, providing &quot;logic&quot; and &quot;rules&quot;, with all required information to &quot;make those decisions&quot;.</p><p>Additionally, &quot;the easiest&quot; has a very special meaning here - as you probably already know, dear Reader, <a href="https://talesfrom.dev/blog/simple-isnt-easy">Simple isn&#x27;t easy</a>.</p><p>In my current model of the world, &quot;easy&quot; means &quot;the least effort required&quot;, in contrary to &quot;simple&quot;, which actually might require quite some effort to achieve.</p><p>So this might take duplication, static and hardcoded values, and other &quot;hacks&quot; into account, to ensure that specification is satisfied.</p><p>All those <em>how</em>s manifest <em>what</em> - the act of satisfying.</p><p>Here is the moment when one can use &quot;Fake It Till You Make It&quot; or &quot;Obvious implementation&quot; approaches, to get the needs of the consumer satisfied as soon as possible (thanks <a href="https://twitter.com/GGalezowski">Grzegorz</a> for bringing that one up!).</p><p>This is also the time to put everything in the single file, completely forgetting how to organize things.</p><p>Why not putting things in the controller?</p><p>The act of simplification will come, soon.</p><p>Often times it might feel quite unnatural to even consider doing that, but one tremendously important part of quick transition between specification and needs satisfaction is <strong>providing the value</strong> (and as we know, the value is in the eye of the consumer), and followed by <strong>getting feedback</strong>.</p><p>And feedback is about learning.</p><p>Learning about the needs, about the problem itself.</p><p>So the sooner one understands whether the specified behavior is actually what the consumer needs, the better.</p><p>When feeling under control, take bigger steps.</p><p>When feeling uncertain, take smaller steps.</p><p>This is also the moment when focus on the current consumer needs is crucial - we don&#x27;t want to produce something what is not needed, avoiding waste.</p><p>As we explored in another tale (<a href="https://talesfrom.dev/blog/code-knowledge-and-ai">Code, knowledge and &quot;AI&quot;</a>), here are the words from Taiichi Ohno, the father of Toyota Production System:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Overproduction is the biggest waste.</p></div></div></div><p>We strive to satisfy the specified consumer needs, not more, not less.</p><h3 id="simplify"><a href="#simplify" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Simplify</h3><p>The third step is to <strong>simplify</strong> the implementation, trying to achieve quality attributes like modularity, understandability, maintainability, and so on.</p><p>If we used tests to specify consumer-expected behavior, we can see that those some of the needs were already satisfied by seeing &quot;the green bar&quot; (this might not mean we finished providing <em>all</em> required functions!).</p><p>If we used manual verification, we can hope we didn&#x27;t break anything in between.</p><p>But remembering Rich Hickey&#x27;s words about simplicity:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Simplicity often mean making more things, not fewer</p></div></div></div><p>Now we want to reflect on the implementation and make a decision - do we want to keep it as is, and continue with the workflow, going back to the first step, considering we don&#x27;t have all the needs specified.</p><p>If we decided that it&#x27;s the right time to improve the implementation, we can start simplifying it.</p><p>We can refactor the structure (of the knowledge representation) - introduce new objects, extract functions, put more boundaries, and so on.</p><p>It is also the time to take care of things like duplications and look for new abstractions (the importance of that process is nicely presented in <a href="https://blog.thecodewhisperer.com/permalink/putting-an-age-old-battle-to-rest">this</a> blog post).</p><p>Sometimes it will be renaming, introducing new concepts using classes, capturing important <a href="https://talesfrom.dev/blog/the-ambiguity-of-interfaces">capability by using an interface</a>.</p><p>All this effort is to <a href="https://talesfrom.dev/blog/composing-a-pie">organize elements and interactions between</a> differently, so that we get something back (when it comes to &quot;organizing things&quot;, you might be interested in <a href="https://talesfrom.dev/blog/the-ambiguity-of-software-architecture">The ambiguity of software architecture</a>).</p><p>Such &quot;simplifying&quot; work can be moving things around - separate files, separate directories.</p><p>All those <em>how</em>s manifest <em>what</em> - the act of simplifying.</p><h3 id="specify---satisfy---simplify-repeat"><a href="#specify---satisfy---simplify-repeat" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Specify -&gt; Satisfy -&gt; Simplify, repeat</h3><p>The magic is in the workflow.</p><p>But actually, to be efficient and get the results, &quot;the designer&quot; (or &quot;the operator&quot;) must know techniques, approaches, practices and mindfully spot &quot;hacks&quot; introduced while satisfying.</p><p>When a person not that experienced is left alone, &quot;commanded&quot; to &quot;do TDD&quot;, quite often the result is suboptimal.</p><p>&quot;Be soft on the operator, hard on the process&quot; - as Deming used to say.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/tdd-specify-satisfy-simplify-cycle.png" class="max-h-[24rem]"/></div><div class="italic mx-24">An engineering workflow</div></div><p>Also, just starting from &quot;specification&quot; step might be quite late - it might feel that when all people are busy doing their work in <a href="https://talesfrom.dev/blog/the-ambiguity-of-team-work">isolation</a>, we reached the optimal way of utilizing brilliant minds of people.</p><p>Many times the perfect specification, with perfect and simple implementation, is horribly incorrect - because we missed the problem.</p><p>&quot;We always can quickly do the wrong thing&quot; or &quot;we always can run fast in the wrong direction&quot;, as some say.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/tdd-specify-satisfy-simplify-collaboration.png" class="max-h-[24rem]"/></div><div class="italic mx-24">Collaborative, engineering workflow</div></div><p>It might be that the whole cycle starts earlier - when people meet and draw together, discuss together.</p><p>&quot;When one teaches, two learn&quot; - and it is not only about technical skills and knowledge, often times it&#x27;s about things like the why of the currently explored problem, other possible ways of providing a solution.</p><p>The best would be to sit together and go through all three steps together - specifying, satisfying, simplifying.</p><p>The amount of learning might be huge, and the quality of the result might be outstanding.</p><p>There are prerequisites, of course - psychological safety, technical excellence of at least some people in the software teaming session.</p><h3 id="tdd--consumer-expected-behavior-specification-through-tests"><a href="#tdd--consumer-expected-behavior-specification-through-tests" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>TDD = Consumer-expected behavior specification through tests?</h3><p>So, dear Reader, next time you hear &quot;TDD&quot;, think about <strong>3S</strong> - <strong>specify, satisfy, simplify</strong>.</p><p>TDD itself can be thought of as a symbol, an abstraction, but I believe it might be really worth exploring all the steps and find what we want to achieve in each of them.</p><p>Such deepened understanding might contribute to actually using the discipline in much more mindful, more aware way.</p><p>It is important to remember that all those steps are about <em>what</em> we want to achieve, not <em>how</em> we want to do it.</p><p>So specification might not include automated tests, but then we are risking losing the feedback loop, later defects and much worse maintainability.</p><p>The best person to trick and deceive us is ourselves, so we can easily say that &quot;writing tests slows us down&quot;, but it quickly might turn out to be a false economy.</p><p>Also, not having executable specifications (tests) often leads to <a href="https://talesfrom.dev/blog/overdebugging">Overdebugging</a>, which is a completely different story.</p><p>So next time, dear Reader, if you are challenged with a problem to solve, pretend to have &quot;wishful amnesia&quot;, temporarily forget about implementation details and ask yourself:</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>What do I, as a consumer, need? How can I specify that?</p></div></div></div>]]></content:encoded>
    <pubDate>Sun, 30 Nov 2025 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>software engineering</category><category>software design</category><category>object-oriented design</category><category>modularity</category><category>design patterns</category><category>language patterns</category><category>software quality</category><category>knowledge working</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/the-ambiguity-of-naming</guid>
    <title>The ambiguity of naming</title>
    <link>https://talesfrom.dev/blog/the-ambiguity-of-naming</link>
    <description>Why naming is hard, and can even be dangerous?</description>
    <content:encoded><![CDATA[<h3 id="whats-behind-a-variable"><a href="#whats-behind-a-variable" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What&#x27;s behind a variable?</h3><p>Imagine that there is a discussion between developers: <span class="text-blue-500">Dylan</span> and <span class="text-yellow-500">Don</span> regarding a variable name in the code.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div class=""><span class="italic font-bold text-blue-500">Dylan, Developer</span>: I somehow don&#x27;t like the name of that variable.</div></span><span class="text-white"> </span><span class="text-white"><div class=""><span class="italic font-bold text-yellow-500">Don, Developer</span>: Why you don&#x27;t like it?</div></span><span class="text-white"> </span><span class="text-white"><div class=""><span class="italic font-bold text-blue-500">Dylan, Developer</span>: What do you mean by <code>userData</code>?</div></span><span class="text-white"> </span><span class="text-white"><div class=""><span class="italic font-bold text-yellow-500">Don, Developer</span>: Lol, data of the user?</div></span><span class="text-white"> </span><span class="text-white"><div class=""><span class="italic font-bold text-blue-500">Dylan, Developer</span>: But <code>data</code> sounds so technical, can&#x27;t we just drop it and just have <code>user</code>?</div></span><span class="text-white"> </span><span class="text-white"><div class=""><span class="italic font-bold text-yellow-500">Don, Developer</span>: Come on, it&#x27;s just a detail. I can rename it, but please don&#x27;t be a grammar nazi...</div></span></div><p><code>Rename</code> in your favorite IDE is just a few keystrokes away, so Don agrees to change the name.</p><p>Soon there&#x27;s a new requirement to satisfy - display a date of birth of the user.</p><p>Both <span class="text-blue-500">Dylan</span> and <span class="text-yellow-500">Don</span> discuss how to implement it.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div class=""><span class="italic font-bold text-blue-500">Dylan, Developer</span>: So, birth date...</div></span><span class="text-white"> </span><span class="text-white"><div class=""><span class="italic font-bold text-yellow-500">Don, Developer</span>: Yeah. Should we add it to <code>User</code> class?</div></span><span class="text-white"> </span><span class="text-white"><div class=""><span class="italic font-bold text-blue-500">Dylan, Developer</span>: But wouldn&#x27;t it have too much on its plate? You know, handling shipping, billing addresses, information about accepting terms and conditions. And now, out of nowhere, it will know about the birthd date.</div></span><span class="text-white"> </span><span class="text-white"><div class=""><span class="italic font-bold text-yellow-500">Don, Developer</span>: Remember about purchased accesses. <code>User</code> has this information also.</div></span><span class="text-white"> </span><span class="text-white"><div class=""><span class="italic font-bold text-blue-500">Dylan, Developer</span>: Hm, yes, that&#x27;s true. But it is just a new field, right?</div></span></div><p>Eventually, they decide to add a new field to the <code>User</code> class.</p><p>Because it is just another field, right?</p><h3 id="whats-behind-a-feature"><a href="#whats-behind-a-feature" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What&#x27;s behind a feature?</h3><p>Imagine that in another company, there&#x27;s a brief sprint planning between <span class="text-fuchsia-500">Derek</span> and <span class="text-red-500">Diego</span> and the product owner, <span class="text-green-500">Paul</span>, regarding a new feature to implement.</p><p>They talk about <code>Tours</code> service and adding a new functionality to support multi-city local tours.</p><p>This company creates software supporting local, guided tours in various cities all around the world.</p><p>So far they supported only single-city tours, but now they want to expand their offering.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div class=""><span class="italic font-bold text-green-500">Paul, Product Owner</span>: Our customers asked for the ability to book multi-city tours. How can we implement this feature in <code>Tours</code> service effectively?</div></span><span class="text-white"> </span><span class="text-white"><div class=""><span class="italic font-bold text-fuchsia-500">Derek, Developer</span>: We can extend the existing <code>Tour</code> entity to include multiple cities. This way, we can keep the current structure and just add a list of cities to it.</div></span><span class="text-white"> </span><span class="text-white"><div class=""><span class="italic font-bold text-red-500">Diego, Developer</span>: But wouldn&#x27;t that make the <code>Tour</code> entity too complex? It already handles details like pricing, availability, and reviews. Adding multiple cities might clutter it. Maybe we should have another class?</div></span><span class="text-white"> </span><span class="text-white"><div class=""><span class="italic font-bold text-green-500">Paul, Product Owner</span>: We need to ensure that the booking process remains straightforward for our users. Multi-city tour will have only one booking, but will require additional transportation between cities. Should we indicate if a tour is multi-city or not?</div></span><span class="text-white"> </span><span class="text-white"><div class=""><span class="italic font-bold text-fuchsia-500">Derek, Developer</span>: We could add a boolean flag <code>isMultiCity</code> to the <code>Tour</code> entity. This is super <a href="https://talesfrom.dev/blog/simple-aint-easy">easy</a>.</div></span><span class="text-white"> </span><span class="text-white"><div class=""><span class="italic font-bold text-red-500">Diego, Developer</span>: Hm, I see your point, but what if we need to add more details specific to multi-city tours in the future? Like transportation options or layover times? Maybe a separate <code>MultiCityTour</code> class that <a href="https://talesfrom.dev/blog/the-ambiguity-the-curse-and-the-fallacy-of-domain-model">inherits</a> from <code>Tour</code> would be more flexible.</div></span><span class="text-white"> </span><span class="text-white"><div class=""><span class="italic font-bold text-fuchsia-500">Derek, Developer</span>: That&#x27;s true. Like a list of cities to visit?</div></span><span class="text-white"> </span><span class="text-white"><div class=""><span class="italic font-bold text-green-500">Paul, Product Owner</span>: I thought it is straightforward - if a tour is multi-city then we have many cities to visit?</div></span><span class="text-white"> </span><span class="text-white"><div class=""><span class="italic font-bold text-fuchsia-500">Derek, Developer</span>: As expected! Glad we have that discussion.</div></span></div><p>Couple of sprints later, it turned out that multi-city tours can span more than one day, and people might opt-out for visiting certain cities.</p><p><span class="text-green-500">Paul</span> also thought about adding a possibility to pre-order food for tours - initially only for multi-city tours, but then he changed his mind and included both types of tours.</p><p>Developers had a hard time adjusting the <a href="https://talesfrom.dev/blog/the-ambiguity-of-code">code</a> accordingly, managing multiple concerns.</p><h3 id="what-is-behind-a-name"><a href="#what-is-behind-a-name" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What is behind a name?</h3><p>Many people say a cautionary anecdote: &quot;there are two hard things in computer science: cache invalidation and naming things&quot;.</p><p>Giving a good name became both a meme on its own and a scary tale to tell around the campfire.</p><p>But why is naming so hard?</p><p>Is it because a variable name or a class name are ambiguous and hard to read, and then to understand?</p><p>Turns out that there might be something more fundamental going on.</p><p>We use names to communicate.</p><p>We express our thoughts, beliefs, as well as concepts and abstract ideas living in a given area of human of business activity.</p><p>But this act of naming is extremely profound for the consequences it brings.</p><p>As soon as we name something, we basically create a boundary protecting what is inside from what is outside.</p><p>Before, none of that existed - we couldn&#x27;t point at it and say &quot;this is...&quot;.</p><p>Let&#x27;s take <code>User</code> as an example - if we use this label <code>User</code> we create a boundary which splits the world into two: those things that are <code>User</code> and those things that are <code>non-User</code>.</p><p>Same with a <code>Tour</code> and other &quot;ideas&quot;, or &quot;things&quot;.</p><p>As if we start with a blank &quot;space&quot;:</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-naming-restricted-reality.png" class="max-h-[24rem]"/></div><div class="italic mx-24">&quot;a reality&quot; (it should be unbounded, but then it will be &quot;hardly visible&quot;)</div></div><p>Then we organize &quot;the knowledge space&quot; by introducing a name:</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-naming-carving-concepts-out.png" class="max-h-[24rem]"/></div><div class="italic mx-24">naming slices &quot;reality&quot; into smaller &quot;realities&quot;</div></div><p>the <code>non-User</code> part is barely considered when we talk about <code>User</code>, but it is there, lurking in the shadows.</p><p>In a simplified terms, when a new requirements arrive, we use &quot;knowledge boundaries&quot; to reason about the information we get.</p><p>Subconsciously, we &quot;compare&quot; - &quot;is it a <code>User</code> or not?&quot;, analyze and decide.</p><p>Those names frame our thinking, shape boundaries in which our minds operate.</p><p>What happens when we have too few &quot;names&quot;?</p><p>We try to organize everything using only those few boundaries.</p><p>As with a hammer and nails metaphor, &quot;if you have a User, everything looks like a User.&quot;</p><h3 id="naming-is-framing"><a href="#naming-is-framing" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Naming is framing</h3><p>Also, it is not just some random and arbitraty names, that we shall use - they need to be meaningful.</p><p>Meaningful in a given area of human or business activity.</p><p>We need to pull and organize information, from the area we try to provide a solutions for, to create &quot;a common language&quot;, also referred as &quot;Ubiquitous Language&quot; in Domain-Driven Design lingo.</p><p>And those names/labels, they are not only about &quot;business concepts&quot; - in our industry we come up with something we started naming (yet again, another boundary!) as &quot;language patterns&quot; - like design patterns, architectural patterns, and so on.</p><p>Those labels can be regarded as symbols - a representation of something, an abstraction, taking away the unnecessary details.</p><p>Of course, we use them to communicate effectively, which is one of its roles.</p><p>But as a side-effect, often unspoken, is that they limit our thinking by putting an invisible frame around it.</p><p>There was a tiny anecdote we explored in <a href="https://talesfrom.dev/blog/the-ambiguity-of-problems/">the ambiguity of problems</a>:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>A little crayfish and a little fish were swimming in the lake and having fun underwater, until the crayfish was mature enough to leave the water and enter the beach. Crayfish was amazed about the sky, about trees, birds chirping and humans running around. He came back underwater and said &quot;Little fish, there&#x27;s a whole new world outside water!&quot; and little fish replied &quot;Water? What is that?&quot;.</p></div></div></div><p>Why little fish didn&#x27;t understand what little crayfish was talking about?</p><p>What concepts were missing in its &quot;knowledge space&quot;?</p><p>Framing brings <a href="https://talesfrom.dev/blog/the-knowledge-gravity-problem/">the knowledge gravity problem</a> too - each time we label something, one could imagine that there&#x27;s a &quot;meaning capacity&quot; created.</p><p>The more capacious name, the more knowledge it attracts.</p><p>In a way, &quot;the more fits in&quot;.</p><p>This impacts the questions we ask ourselves - &quot;how to add that to <code>User</code>?&quot; or &quot;what is the best way of changing <code>Tour</code>?&quot;, whereas we might actually need more names (concepts) or just different ones.</p><p>Even if we might be aware that we need to use <a href="https://talesfrom.dev/blog/the-ambiguity-the-curse-and-the-fallacy-of-domain-model">domain model</a>, we might be limited by the names we use to think.</p><h3 id="technical-jargon"><a href="#technical-jargon" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Technical jargon</h3><p>There is a constant tension and battles between not adding too much technical jargon and at the same time being precise enough.</p><p>Balancing that is quite hard, because we need names to communicate effectively, but at the same time we don&#x27;t want to create too many &quot;knowledge frames&quot;.</p><p>Later comparisons and analysis take time, energy, and effort.</p><p>All those pointless discussions about whether something <strong>is</strong> SOLID or not, or whether something <strong>is</strong> microservices or not, are just symptoms of that tension.</p><p>Naming is framing - the more frames we create, the more fragmented our thinking becomes.</p><p>And yet again it often comes with trying to compare things (concepts) based on their &quot;being&quot; aspect - while there are other ways, but one needs to change <a href="https://talesfrom.dev/blog/modeling-maturity-levels">a level</a> or a <a href="https://talesfrom.dev/blog/context-segregation-perspective">perspective</a>.</p><p>That&#x27;s why it is important to know many tools, to learn different designing approaches, explore various patterns, and understand the context in which they apply - there are more concepts we can use and the frames are organized differently.</p><p>Suddenly, we might stop seeing everything as a database table, CRUD entity, or a service.</p><p>&quot;The beauty is in the eye of the beholder&quot;, as they say.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Naming is framing.</p></div></div></div><p>So whenever you hear, dear Reader, someone saying &quot;it&#x27;s just a name, let&#x27;s not overcomplicate things&quot;, remember that naming is framing.</p><p>Remember that assigning meaning to a symbol - a name - creates a boundary that can either limit or expand our thinking.</p><p>Symbol, name, label - they all relate to something we call (yet another name) - a model.</p><p>We want our models to be independent, autonomous and cohesive - all representing what they should emphasize, ensuring clarity and <a href="https://talesfrom.dev/blog/composing-a-pie">purpose</a> in designing.</p><p>And as we discuss models, what about their <a href="https://talesfrom.dev/blog/composing-a-pie">interactions</a>?</p><p>How do &quot;knowledge boundaries&quot; interact with each other?</p><h3 id="the-ambiguity"><a href="#the-ambiguity" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The ambiguity</h3><p>Whenever we name, we create boundaries.</p><p>Not everything fits neatly to everything we organized - sometimes there are &quot;fluffy&quot; points, gray areas, and borderline cases.</p><p>But this, yet again, might be a good diagnostic signal that when observed and interpreted correctly, can help us to improve our understanding of the problem domain.</p><p>Additionally, when we hear names like &quot;interface&quot;, &quot;service&quot;, &quot;module&quot;, and so on - are we sure that we all agree on what they mean?</p><p>What if your understanding (frame) is &quot;more beneficial&quot; than mine?</p><p>How can we compare that?</p><p>I bet it&#x27;s not by actively arguing about what things <strong>are</strong> or not, but more how they are used, what is their purpose and what role they play.</p><p><a href="https://talesfrom.dev/blog/modeling-maturity-levels">Levels</a>, <a href="https://talesfrom.dev/blog/context-segregation-perspective">perspectives</a> and <a href="time-angle-and-depth-dimensions-in-software-design">time</a> might be a help here.</p><p>So next time, dear Reader, whenever communicating, designing or just being a human, and ask yourself:</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>What does it mean? Is there a frame I can&#x27;t see?</p></div></div></div>]]></content:encoded>
    <pubDate>Mon, 27 Oct 2025 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>design thinking</category><category>domain-driven design</category><category>language patterns</category><category>design patterns</category><category>object-oriented design</category><category>functional programming</category><category>software architecture</category><category>mental models</category><category>communication</category><category>knowledge working</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/code-knowledge-and-ai</guid>
    <title>Code, knowledge and &quot;AI&quot;</title>
    <link>https://talesfrom.dev/blog/code-knowledge-and-ai</link>
    <description>What is the relationship between &quot;AI&quot; and waste?</description>
    <content:encoded><![CDATA[<h3 id="code-production"><a href="#code-production" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Code production</h3><p>Imagine that two developers, <span class="text-cyan-600">Chris</span> and <span class="text-rose-600">Paul</span>, are working on a feature together.</p><p>They are using recent advancements of &quot;AI&quot; assistants to help them with the task.</p><p>They more or less understand what problems they are trying to solve, but they don&#x27;t have a clear picture of the solution.</p><p>So they start prompting &quot;AI&quot; to generate code snippets that they can use.</p><p>Couple of tabs later, they have &quot;a working code&quot; (as they referred during daily standup).</p><p>Product stakeholders are happy, as they can see progress pretty quickly.</p><p>Each time &quot;AI&quot; produces something that doesn&#x27;t quite fit, they just re-prompt it, and get a new snippet.</p><p>Soon, each PR is consisting of growing number of files changed.</p><p>Tons and tons of code is getting produced.</p><p>Product stakeholders are happy, as they can see progress pretty quickly.</p><p>&quot;AI&quot; assistant is very good at exploring existing codebase, hence it reuses <code>Tour</code> and <code>Customer</code> classes, putting there more and more knowledge.</p><p><span class="text-cyan-600">Chris</span> and <span class="text-rose-600">Paul</span> are also happy as changes take really little time to happen.</p><p>Product owner suggested that maybe even he could try to prompt &quot;AI&quot; to produce code himself.</p><p>&quot;I know what I want, right?&quot;, he said.</p><p>Developers were a bit skeptical, but agreed to give it a try, and they offered some guidance, when needed.</p><h3 id="knowledge-production"><a href="#knowledge-production" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Knowledge production</h3><p>Soon, both developers realize that they don&#x27;t really understand what is really happening.</p><p>What&#x27;s even worse, they weren&#x27;t involved in the process of designing, so they lack the context needed to make informed decisions about the code.</p><p>They start asking questions to &quot;AI&quot; assistant, trying to understand the code.</p><p>Soon they are able to re-gain control, and start making changes again.</p><p>&quot;AI&quot; assistant uses what it has been trained on, and produces code that is similar to what it has seen.</p><p>Vertical Slices, Clean Architecture, CQRS - they caught all the pokemons.</p><p>Yet again, the real struggle happens as they don&#x27;t really understand the code that got produced.</p><p>Of course, they have some notion, but it&#x27;s shallow.</p><p>They see the &quot;patterns&quot;, but they don&#x27;t understand the &quot;why&quot;.</p><p>They ask another person from the team to review a 121-file pull request, getting &quot;LGTM&quot; as a response.</p><p>At some point, even the &quot;AI&quot; assistant starts to struggle, as the codebase is getting more and more complex.</p><p>They start visualizing the code structure, sequence diagrams, and other artifacts to get a better understanding.</p><p>But it&#x27;s too much.</p><p>Too much of information produced in the process.</p><p>Too much knowledge represented in the codebase.</p><p><code>Tour</code> and <code>Customer</code> concepts are getting quite unwieldy, as they are used in many different places.</p><p>But they got all &quot;best practices&quot; in place.</p><p>Why is it at the same time easier and harder to introduce changes?</p><h3 id="problem"><a href="#problem" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Problem?</h3><p>Many people are excited about the possibilities that &quot;AI&quot; brings to the table.</p><p>I am myself, but probably in a different way.</p><p>No more programmers needed, as we are one step between &quot;ready product&quot; and &quot;idea&quot; - did you hear or think so, dear Reader?</p><p>&quot;Look ma, no hands&quot; - just prompt &quot;AI&quot; to do the job, &quot;vibe code it&quot;.</p><p>Mark Seeman already pointed out in one of his great articles that <a href="https://blog.ploeh.dk/2018/09/17/typing-is-not-a-programming-bottleneck/">typing is not a bottleneck</a>.</p><p>But what is &quot;typing&quot;?</p><p>In its bare form, it is putting characters on the screen, using a keyboard.</p><p>Those characters form &quot;a program&quot;, which can be regarded as &quot;code&quot;.</p><p>One could then conclude that &quot;typing is code production&quot;.</p><p>This code got produced to solve a particular problem, which should be studied and analyzed beforehand, at least in some extent.</p><p>We operate in <a href="https://en.wikipedia.org/wiki/VUCA">VUCA</a> world (see more in <a href="https://talesfrom.dev/blog/from-concepts-to-architecture">From concepts to architecture</a>) - building up basic concepts is necessary, if not representing them in the code, at least for efficient communication (!).</p><p>So the real problem is understanding a problem.</p><p>Taiichi Ohno, the father of Toyota Production System, pointed out that:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Overproduction is the biggest waste.</p></div></div></div><p>Producing code that is not needed, or producing more code than needed, is a waste.</p><p>And now it&#x27;s getting cheaper.</p><p>One can easily &quot;generate&quot; more code, just by prompting &quot;AI&quot; assistant.</p><p>New models, less tokens, more context - what a bargain!</p><h3 id="overproduction-of-code"><a href="#overproduction-of-code" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Overproduction of code</h3><p>Back then, it was hard and expensive to produce code - IDEs were not advanced, computers had limited resources, internet was not widely available.</p><p>People needed to chisel, tinker, and &quot;sweat&quot; to produce code.</p><p>We got source code generators, taking away boilerplate code and more.</p><p>We got ORMs and other tools, automating away stuff like writing migration scripts by hand - more code got produced.</p><p>Now, everything gets easier and easier - and don&#x27;t get me wrong, dear Reader, I really do admire that it&#x27;s getting cheaper to materialize ideas in the form of working solutions.</p><p>I am benefitting from it myself, each day.</p><p>But this easiness comes with a cost - as we tried to discuss it earlier - <a href="https://talesfrom.dev/blog/easy-will-make-you-dizzy/">Easy will make you dizzy?</a>.</p><p>Each time we advanced capabilities by using the tool, we delegated some part of the work to it too.</p><p>What do we want to delegate?</p><p>Software engineering professionals are knowledge workers - our &quot;material&quot; we work on and work with is knowledge, information.</p><p>Our sword is understanding.</p><p>&quot;AI&quot; machinery is very good at producing code, but can it that easily produce understanding?</p><p>When not done consciously, it can be really hazardous with this flashy effect of &quot;getting tons of lines of code produced&quot;.</p><p>How is this code, that got produced, used?</p><p>What is our intention, dear Reader?</p><p>Do I want to have a working solution that will go straight to production as I want to &quot;close a ticket&quot;?</p><p>Or maybe, I want to understand the problem better?</p><p>Hard questions.</p><h3 id="underproduction-of-understanding"><a href="#underproduction-of-understanding" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Underproduction of understanding</h3><p>Turns out that it is still &quot;an operator&quot; who must <strong>understand</strong> what is getting produced.</p><p><strong>Understand</strong>: <strong>what</strong> is expected to be produced, <strong>what</strong> is the reason for production and <strong>why</strong> it is important.</p><p>As &quot;material&quot; is knowledge, and a product is also knowledge, that sometimes is materialized as code, other times as a diagram - &quot;an operator&quot; must build up the <strong>understanding</strong>.</p><p>Not &quot;just code stuff&quot;.</p><p>And this problem really existed even before &quot;code production&quot; machines were invented.</p><p>No amount of efficient code production, low-code/no-code tools, and so forth, is needed when we work on and solve incorrectly understood problems.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>So the real problem is understanding a problem.</p></div></div></div><p>Along with &quot;code production&quot; machinery, we are also getting bespoke &quot;understanding production&quot; machinery too - some vendors provide &quot;assistants&quot; that help us doing <strong>code</strong> reviews, that help us orienting in the maze of all the files changed in the process of development.</p><p>How modern is that, dear Reader?</p><p>As both Gerald Weinberg and John Gall concluded - &quot;every solution becomes a new problem&quot;.</p><p>We overproduce code, and it becomes a problem.</p><p>So &quot;fast typing&quot; stops to be a bottleneck (was it ever a real problem?) and &quot;fast understanding&quot; of the &quot;produced code&quot; is.</p><p>To fight against that problem, we get more tools that enhance our ability to comprehend and manage the code we produce.</p><p>But what was a real problem in the first place?</p><p>What if <a href="https://talesfrom.dev/blog/tools-make-fools">tools make fools?</a></p><h3 id="cheap-production-upsides"><a href="#cheap-production-upsides" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Cheap production upsides?</h3><p>It&#x27;s easy to moan and complain - &quot;an old man yells at the cloud&quot; - but is there a benefit of cheal code production?</p><p>In hands of an experienced professional, this becomes a tool for rapid ideas verification.</p><p>&quot;Code production&quot; machinery amplifies experimenting abilities - shaping and molding solutions to see if it makes sense.</p><p>Getting a feedback sooner and adjusting - the heart of agile software development (if you want more on that topic, please visit <a href="https://talesfrom.dev/blog/fragile">(Fr)Agile</a>.</p><p>So when used pragmatically and consciously, for sure &quot;code production&quot; can increase <a href="https://x.com/RealGeneKim/status/1890540385275097454">option value</a>, but it not necessarily needs to happen.</p><p>And yet again, it&#x27;s the operator who steers everything - from concept to cash.</p><p>From analysis, through building understanding, to controlling &quot;code production line&quot;, and verifying if it actually yields results we want to see.</p><p>Who is the biggest bottleneck - a machinery or an operator?</p><p>Do we want to remove an operator or use their time and energy, in an economically efficient way, to focus on building understanding and problem-solving?</p><p>In Toyota Production System, the core value is put on &quot;utilizing the intelligence of ordinary people&quot;.</p><p>Think about that.</p><h3 id="code-production-downsides"><a href="#code-production-downsides" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Code production downsides?</h3><p>I once wrote a haiku, dedicated to yin-yang of problem solving using software:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Code overproduction</p>
<p>Understanding underproduction</p>
<p>People laughing</p>
<p>People screaming</p></div></div></div><p>Putting to much focus on code production and all the glitter around it might drag us away from the real problem - understanding the problem.</p><p>Even though &quot;cheap code&quot; should encourage escaping <a href="https://talesfrom.dev/blog/the-inverse-matrix-problem">Inverse Matrix</a>, it might lure into the lair of &quot;you need better models&quot;.</p><p>We need to be aware that each tool teases and pleases our senses, as if a brave sailor was seduced by singing mermaids - you probably can guess how this typically ended up, dear Reader.</p><p>But what is even more concering is that more and more &quot;operators&quot; - software architects, software designers and software engineers - will get disconnected from &quot;the material&quot; they are working on and working with.</p><p>&quot;Coding abilities&quot; will decay, reasoning in &quot;code&quot; way will stop be natural, &quot;mechanical sympathy&quot; will become obsolute and oldfashion.</p><p>When I say (write?) &quot;coding abilities&quot;, I think of representing knowledge and understanding as code - call it modelling, designing.</p><p>Clearly expressing what we know at the moment of enchanting it in the form of code.</p><p>Some say that &quot;people will be able to reason on higher levels&quot;, &quot;it&#x27;s just another abstraction&quot; - and I can agree on that, however, one must remember that when all works as we expect, you don&#x27;t need to care.</p><p>But when things go in a way that we didn&#x27;t expect - &quot;you need to look under the hood&quot;.</p><p>Abstractions are necessary and useful, until you don&#x27;t need to peel them, inlining covered concepts and elements.</p><p>Who will &quot;look under the hood&quot;?</p><h3 id="investing-in-details"><a href="#investing-in-details" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Investing in details?</h3><p>&quot;You think you are smartass Damian? Then, what should we do?&quot; - one might ask.</p><p>I would probably reply: <a href="https://talesfrom.dev/blog/i-dont-know">I don&#x27;t know</a>.</p><p>Let&#x27;s see what is the landscape and analyze the conditions we are operating in.</p><p>As we explored the topic of <a href="https://talesfrom.dev/blog/software-engineering-for-busy-parents">software engineering for busy parents</a>, there are some easy gains one can get.</p><p>Maybe we could look at the investment domain and see what people recommend?</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>The wisest rule in investment is: <strong>when others are selling, buy. When others are buying, sell</strong>. Usually, of course, we do the opposite. When everyone else is buying, we assume they know something we don&#x27;t, so we buy. Then people start selling, panic sets in, and we sell too.</p></div></div></div><p>Allegedly said <a href="https://en.wikipedia.org/wiki/Jonathan_Sacks,_Baron_Sacks">Jonathan Sacks</a> (please correct me if I am wrong here).</p><p>Then, <a href="https://en.wikipedia.org/wiki/J._Paul_Getty">J. Paul Getty</a> observed in a similar fashion:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>I buy when other people are selling.</p></div></div></div><p>Based on those observations, I believe we could forge a similar heuristic, when it comes to IT and software engineering domain:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>When others invest in code generation, learn fundamentals. When others are struggling, help/consult.</p></div></div></div><p>&quot;Fundamentals? Do you want me to learn design patterns?&quot;, you might be wondering, dear Reader.</p><p>Well, all the language patterns we use are concepts that we can use to effectively communicate with each other - LLMs can understand them too (there were trained on them, weren&#x27;t they?).</p><p>For me, fundamentals are related to the core of what we are doing - methods, tools and recurring patterns for managing complexity, designing solutions in response to arising needs.</p><p>At some point, when dealing with &quot;patterns&quot; and &quot;loading&quot; them to one&#x27;s head - they will &quot;emerge&quot; (or become visible) when interacting with a problem.</p><p>As with &quot;code production&quot;, we still need to be doubtful, in a paranoid-esque way, trying to understand if our design choices and understanding we built are correct.</p><p>We can&#x27;t escape that.</p><p>And if we get back to &quot;AI&quot; assistants - they can be a great tool for learning, for exploring and for building understanding - as this is the hardest part in our profession.</p><p>&quot;Ask&quot; them to explain concepts behind produced code (=knowledge represented).</p><p>So next time, dear Reader, when watching how LLMs are (over)producing code for you, think about formed understanding and ask yourself:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>What problem am I solving right now?</p></div></div></div>]]></content:encoded>
    <pubDate>Mon, 20 Oct 2025 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>lean software development</category><category>toyota production system</category><category>knowledge working</category><category>design thinking</category><category>systems thinking</category><category>language patterns</category><category>mental models</category><category>software architecture</category><category>software design</category><category>domain-driven design</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/the-inverse-matrix-problem</guid>
    <title>The Inverse Matrix problem</title>
    <link>https://talesfrom.dev/blog/the-inverse-matrix-problem</link>
    <description>Are we trapped in Inversed Matrix?</description>
    <content:encoded><![CDATA[<h3 id="refactoring"><a href="#refactoring" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Refactoring</h3><p>Imagine that there&#x27;s a development team and their day started as usual - a typical daily meeting, each team member contributes to the mass illusion of doing Agile (we release every quarter), all staring at Jira.</p><p>Tasks dispatched, workers...I mean, engineers assigned - the whole production can start working!</p><p>Days passed and <span class="text-yellow-500">Mary</span> got a notification that her peer, <span class="text-rose-600">Rick</span>, assigned her to perform a code review (as we all know, it&#x27;s about the code as it&#x27;s the most important thing, right?).</p><p><span class="text-yellow-500">Mary</span> had completely no idea about the conceptual advancement that the reviewed PR introduces, as there are 37 files touched.</p><p>She went through one file by one file and suddenly spotted a change that checked a bunch of ifs, throwing exceptions here and there.</p><p>It was hard to get the context of this PR; the conditions seemed reasonable, but the lack of tests didn&#x27;t provide enough understanding of the rules behind.</p><p>And those exceptions.</p><p>Imagine they decided to have a quick sync about this PR, using a video call.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><span class=""><span class="italic font-bold text-rose-600">Rick, a developer</span>: Yo, what&#x27;s up?</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-yellow-500">Mary, a developer</span>: Hi! We&#x27;re doing code review, as you assigned us. Can we have a bunch of questions?</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-rose-600">Rick, a developer</span>: Sure! Did you like the decorator pattern? It&#x27;s quite clever - now we can...</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-yellow-500">Mary, a developer</span>: Why do you throw an exception in line 9872? Seems like it is a regular step in the process. Shouldn&#x27;t we notify an operator instead?</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-rose-600">Rick, a developer</span>: Good question. I actually didn&#x27;t know what to do, so decided to throw an exception. I think front-end guys will figure out if they want to show a fancy spinner or other UI-esque thing.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-yellow-500">Mary, a developer</span>: Hmm, but the process should continue, just another path?</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-rose-600">Rick, a developer</span>: Yes, path - if the condition is not met, we enter inside the if body.</span></span></div><p><span class="text-yellow-500">Mary</span> requested changes, but PR was merged anyway, as there was a demo in the next day, and product owner couldn&#x27;t wait more.</p><p>After a couple of days, someone couldn&#x27;t continue with the process as &quot;Sorry, please try again&quot; message started popping up, with a nice, flashy UI.</p><h3 id="a-new-feature"><a href="#a-new-feature" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>A new feature</h3><p>Next sprint planning just finished.</p><p>Motivated team was ready to brainstorm new features.</p><p>Discussions were mostly about new possible 3rd packages needed (both NuGet and npm), along with necessary infrastructure changes.</p><p>We had a great time, as we all love to discuss technical stuff.</p><p>Suddenly, one of the team members, <span class="text-yellow-500">Mary</span>, raised a question. <span class="text-rose-600">Rick</span> and <span class="text-cyan-500">Henry</span> participated in the discussion.</p><p>The debate was related to <code>User</code> class.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><span class=""><span class="italic font-bold text-yellow-500">Mary, a developer</span>: Guys, I don&#x27;t think we should add more properties to <code>User</code> class.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-rose-600">Rick, a developer</span>: Why? Didn&#x27;t you pay attention to UI? Wallet, number of tenders, email - it was all there.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-cyan-500">Henry, a developer</span>: Personally, I don&#x27;t like to have too many classes - there&#x27;s more to understand. I fear spaghetti code.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-yellow-500">Mary, a developer</span>: Product Owner clearly stated that tenders might grow pretty fast, especially when tenders are tiny. Wouldn&#x27;t that impact database?</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-cyan-500">Henry, a developer</span>: I don&#x27;t know - I just want to have it in the single place - it&#x27;s easier to reason about. And remember Mary, we are going to maintain that.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-rose-600">Rick, a developer</span>: What&#x27;s more, recently we added connected traders to <code>User</code> and nothing bad happened.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-cyan-500">Henry, a developer</span>: See, another good point to keep it in the single place.</span></span></div><p>In six months and many more properties added to <code>User</code>, the team suffered from performance issues, which they tried to cure with scaling up and out.</p><p>But what&#x27;s worse - the team was constantly fixing bugs related to <code>User</code> class, as it was hard to understand all the implications of changes.</p><h3 id="a-bug"><a href="#a-bug" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>A bug</h3><p>The same team struggled with a critical bug in production.</p><p>The bug was related to a tendering process - some users were not able to place tenders.</p><p>A tiny discussion started in the team chat.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><span class=""><span class="italic font-bold text-rose-600">Rick, a developer</span>: Don&#x27;t worry guys, I know this area of the system. This will be an easy fix.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-yellow-500">Mary, a developer</span>: I hope it won&#x27;t be in a <code>User</code> class...</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-cyan-500">Henry, a developer</span>: You should just place if after this statement (<em>shows with a mouse</em>).</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-rose-600">Rick, a developer</span>: Yeah, exactly. But we need to make another call to a database. Hmmm</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-yellow-500">Mary, a developer</span>: What if this is not the right place for this if?</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-rose-600">Rick, a developer</span>: Pardon? What do we mean &quot;not the right place&quot;?</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-cyan-500">Henry, a developer</span>: Look - there are other ifs around, so it seems it&#x27;s the right place.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-yellow-500">Mary, a developer</span>: But those other ifs are related to user profile and e-mail being correct, not about tendering.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-cyan-500">Henry, a developer</span>: Sorry, but we don&#x27;t have time right now. I&#x27;ll put a ticket for it.</span></span></div><p>After quick fix was deployed, more ifs started popping up in the code, as more and more edge cases were discovered.</p><p>Soon, the team was overwhelmed with bugs, as the code became hard to understand and change.</p><p>And the mantra was &quot;just add another if&quot;.</p><h3 id="an-improvement"><a href="#an-improvement" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>An improvement</h3><p>The brave team gathered again - during sprint planning - ready to take another challenge.</p><p>Yet again, it was related to tendering process - according to Product Owner, there was another step required, after it was completed.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><span class=""><span class="italic font-bold text-rose-600">Rick, a developer</span>: Seems like we need another status in the <code>Tender</code> class - <code>Verification</code>?</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-yellow-500">Mary, a developer</span>: But we didn&#x27;t ask why it is required at all?</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-cyan-500">Henry, a developer</span>: Well, Product Owner told us so it&#x27;s our job to do it, isn&#x27;t it?</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-rose-600">Rick, a developer</span>: I think we need to create <code>AggregateRoot</code> base class and let <code>User</code> inherit it - our job is to keep tendering consistent according to rules.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-cyan-500">Henry, a developer</span>: <code>AggregateRoot</code>? What is that?</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-rose-600">Rick, a developer</span>: It&#x27;s a design pattern that comes from Domain-Driven Design - basically you expose methods on your classes and keep logic there.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-yellow-500">Mary, a developer</span>: <code>User</code> class contains much more information than we need to maintain consistency for tendering process, isn&#x27;t it?</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-cyan-500">Henry, a developer</span>: I really would like to keep <code>User</code> as it is - it allows easier reasoning for related database tables.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-rose-600">Rick, a developer</span>: I am good with that, as long as we use <code>AggregateRoot</code> pattern - it will help maintaining consistency.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-yellow-500">Mary, a developer</span>: I am not quite sure if...</span></span></div><p>Eventually, <code>AggregateRoot</code> was introduced, with <code>User</code> inheriting it.</p><p><code>User</code> class <a href="https://talesfrom.dev/blog/the-knowledge-gravity-problem">attracted</a> more and more logic, and it turned into a benovelent dictator of the system.</p><p>Soon, developers became hostages of <code>User</code> class, as it was hard to change anything without breaking something.</p><h3 id="the-code"><a href="#the-code" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>THE code</h3><p>How do you feel, dear Reader?</p><p>I hope you feel those situations are pretty exaggerated and such things don&#x27;t happen in real life.</p><p>Or maybe you can relate to them?</p><p>It is quite typical that we, software engineers, focus on code, as it&#x27;s the most tangible thing we have.</p><p>Even though it is pretty virtual, this is the most &quot;tangible&quot; thing many interact with.</p><p>Slicing, merging, reviewing, moving, deleting, copying, pasting, committing, breaking - we do a lot of things with code.</p><p><em>Code</em> is our <em>material</em> we work on.</p><p>Sometimes it might seem that there&#x27;s nothing else but code.</p><p>We even get called &quot;coders&quot;.</p><p>Some might even say that our job is solely about writing code and to get paid for that.</p><p>In a way, code constructs our identity, as software engineers.</p><h3 id="matrix"><a href="#matrix" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Matrix</h3><p>Have you seen <a href="https://en.wikipedia.org/wiki/The_Matrix">&quot;the Matrix&quot;</a> movie?</p><p>If you didn&#x27;t, I highly recommend watching it.</p><p>Here&#x27;s a little spoiler (or a main point, if you wish): people lived there, unaware that the reality was a deep and advanced simulation.</p><p>And the true reality was quite different.</p><p>Pretty grim and dystopian, where human beings were bred and used as an energy source by machines.</p><p>One time the main character, Neo, started seeing beyond the reality he knew and understood that the world was nothing more than &quot;a code&quot;.</p><p>Literally, <em>code</em>.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-inverse-matrix-problem-code.png" class="max-h-[30rem]"/></div><div class="italic mx-24">the &quot;reality&quot; in Matrix</div></div><p>All his gestures, all actions, all dreams, senses - everything were just a software construct, until he &quot;woke up&quot;, and saw the true reality.</p><p>During and after watching the first movie out of three parts, one might start questioning the symbols, the reality, and the true nature of things.</p><p>What was the significant event that happened was looking beyond the current &quot;reality&quot;, which turned out to be a mass illusion.</p><h3 id="the-inverse-matrix-problem"><a href="#the-inverse-matrix-problem" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The Inverse Matrix problem</h3><p>One could say that people living in Matrix had a big problem - they were trapped in an illusion that prevented them from seeing the harsh truth of their existence.</p><p>What if &quot;coders&quot; are also trapped, but in an alternative way?</p><p>We convinced ourselves (by various means) that code is the most important thing, the only thing that matters.</p><p>It is our &quot;reality&quot;.</p><p>&quot;The code&quot; covers something truly important, something that really impacts what we do and why we do it.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-inverse-matrix-problem-matrix-reality.png" class="max-h-[30rem]"/></div><div class="italic mx-24">Matrix &quot;realities&quot;: perceived, actual, hidden</div></div><p>&quot;The code as reality&quot; manifests as characters on the screen - &quot;it&#x27;s just an if&quot;, &quot;it&#x27;s just a class&quot;, &quot;it&#x27;s just a service&quot;.</p><p>We are really good at deceiving ourselves (in general, as human beings, but here we refer to &quot;coders&quot;) with &quot;code&quot; being <strong>the most</strong> important thing, reinforcing the illusion.</p><p>Believing that tools can solve all our problems with existing <strong>code</strong>, we employ BDDs, DDDs, ATDDs, Design Patterns, and so on.</p><p>But the magic is that there is no magic (and be aware that <a href="https://talesfrom.dev/blog/tools-make-fools">Tools make fools?</a>).</p><p>Are we overlooking the &quot;true reality&quot; of our work?</p><p>What if we are all trapped in the &quot;Inverse Matrix&quot;?</p><p>We see &quot;the code&quot; as our &quot;reality&quot;, but in reality there is much more: there are people, processes, drivers, goals, culture, and so on.</p><p>Remember: we build <a href="https://talesfrom.dev/blog/systems-by-with-for-people">Systems: by, with, for people</a>.</p><p>There are areas for which our efforts are supposed to provide solutions.</p><p>Most often those solutions are related to artifacts like &quot;executable code&quot;, but it shouldn&#x27;t neglect people using and benefitting from our systems, processes that are supported to make other people work/lives easier and culture in which we operate while organizing ourselves.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-inverse-matrix-problem-inverse-matrix-reality.png" class="max-h-[30rem]"/></div><div class="italic mx-24">Inverse Matrix &quot;realities&quot;: perceived, actual, hidden</div></div><p>Often, &quot;hidden reality&quot; depicted above could be understood as &quot;sociotechnical system&quot;, where &quot;people and machines&quot; exist together, interact with each other and co-evolve.</p><p>Only when <a href="blog/composing-a-pie">interactions</a> happen, there is a probability that an expected behavior will emerge, leading to providing the value.</p><p>But is there anything we can do to escape the &quot;Inverse Matrix&quot;?</p><p>(you can, dear Reader, think about a related question: why one might want to escape the &quot;Inverse Matrix&quot;?)</p><h3 id="escaping-the-inverse-matrix"><a href="#escaping-the-inverse-matrix" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Escaping the Inverse Matrix?</h3><p>Turns out that might be quite <a href="https://talesfrom.dev/blog/simple-not-easy">simple, but not easy</a> (when I say &quot;easy&quot;, I mean &quot;requiring low/no effort&quot;).</p><p>Don&#x27;t rush to writing code.</p><p>Don&#x27;t envision the solution right away.</p><p>Start with questions.</p><p><a href="https://talesfrom.dev/blog/slow-down">Slow down</a> and build the context.</p><p>Who is going to use this piece of information?</p><p>How is it going to be used?</p><p>Who is paying for it?</p><p>What is the expected behavior?</p><p>What does someone want to accomplish?</p><p>And collaborate - involve others, share your assumptions, and seek to understand.</p><p>Techniques, approaches and methods like Strategic Domain-Driven Design (in general: looking <em>beyond</em> code, visualizing the knowledge and understanding) can be a really good first step into a beautiful journey, full of traps and ambiguities, but also full of discoveries and learning.</p><p>What business capabilities are required to provide a necessary level of service?</p><p>&quot;Ah, but I am not a business analyst or an architect!&quot;, one might say.</p><p>Even though one might not have a specific job title, we still can train ourselves in asking questions, building shared context.</p><p>&quot;Yeah, but it will be slower this way - asking those questions, collaborating, etc.?&quot;, another might comment.</p><p>Yeah, it will be slower for sure - but what is the goal?</p><p>As someone said: &quot;we always can build the wrong thing quickly&quot;.</p><p>Let&#x27;s visualize &quot;escaping the Inverse Matrix&quot;.</p><p>Imagine that as we got trapped in a frame of being &quot;coders&quot;, we put a special &quot;glasses&quot; on our noses, that distort the perception by filtering out everything, except <em>the code</em>.</p><p>It framed ourselves in &quot;thinking in code&quot;, rather the business areas, people, processes, business capabilities.</p><p>Our job is to &quot;take the glasses off&quot; and start seeing bigger picture.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-inverse-matrix-problem-escaping-inverse-matrix.png" class="max-h-[30rem]"/></div><div class="italic mx-24">Metaphorical representation of escaping the Inverse Matrix</div></div><p>And especially in the time when &quot;AI&quot; is becoming more and more prevalent, focusing only on &quot;the code&quot; might be a trap, as &quot;AI&quot; can generate code for us - but can it synethesize understanding?</p><p>Free yourself from the &quot;Inverse Matrix&quot;.</p><p>Next time, dear Reader, when you start working on something, vocalize a question:</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>Is there something I don&#x27;t see as the code covers it?</p></div></div></div><p>Take the glasses off.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-inverse-matrix-problem-there-is-no-code.png" class="max-h-[30rem]"/></div></div>]]></content:encoded>
    <pubDate>Mon, 06 Oct 2025 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>design thinking</category><category>domain-driven design</category><category>language patterns</category><category>design patterns</category><category>software architecture</category><category>mental models</category><category>communication</category><category>knowledge working</category><category>balancing coupling</category><category>collaboration</category><category>software teaming</category><category>understanding</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/the-ambiguity-of-architecture-decision-records</guid>
    <title>The ambiguity of architecture decision records</title>
    <link>https://talesfrom.dev/blog/the-ambiguity-of-architecture-decision-records</link>
    <description>Is a &quot;decision recording&quot; what we are really looking for?</description>
    <content:encoded><![CDATA[<h3 id="i-architect"><a href="#i-architect" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;I architect&quot;</h3><p>Imagine that there is a discussion during the daily standup where the team is trying to overcome a technical challenge.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div class=""><span class="italic font-bold text-blue-500">Dylan, Developer</span>: Yesterday, I made changes in BVM to support asynchronous job scheduling.</div></span><span class="text-white"> </span><span class="text-white"><div class=""><span class="italic font-bold text-yellow-500">Don, Developer</span>: What is BVM?</div></span><span class="text-white"> </span><span class="text-white"><div class=""><span class="italic font-bold text-green-500">David, Developer</span>: Wait Dylan, why?</div></span><span class="text-white"> </span><span class="text-white"><div class=""><span class="italic font-bold text-blue-500">Dylan, Developer</span>: Somehow it felt right, I mean we already have parts of code that use in-memory eventing so I thought that we could move from in-process to database. I am quite sure that we will need it some day.</div></span><span class="text-white"> </span><span class="text-white"><div class=""><span class="italic font-bold text-yellow-500">Don, Developer</span>: Guys, could you explain what a BVM is?</div></span><span class="text-white"><p><em><span class="italic font-bold text-red-500">Adam, Architect</span>, greatly delayed, enters the virtual room</em></p></span><span class="text-white"><div class=""><span class="italic font-bold text-red-500">Adam, Architect</span>: Sorry for being late, had architecture guild where we discussed a common way of using common services. Can I help somehow?</div></span><span class="text-white"> </span><span class="text-white"><div class=""><span class="italic font-bold text-yellow-500">Don, Developer</span>: Hey Adam! Maybe you could tell me what BVM is...</div></span><span class="text-white"> </span><span class="text-white"><div class=""><span class="italic font-bold text-red-500">Adam, Architect</span>: BVM? Why are you asking about it now?</div></span><span class="text-white"> </span><span class="text-white"><div class=""><span class="italic font-bold text-yellow-500">Don, Developer</span>: Dylan mentioned it&#x27;s going to support async job scheduling, but I still don&#x27;t understand what it is.</div></span><span class="text-white"> </span><span class="text-white"><div class=""><span class="italic font-bold text-red-500">Adam, Architect</span>: Wait, what? I don&#x27;t want to destroy your ideas, but I never said anything about async job scheduling - neither in BVM or elsewhere.</div></span><span class="text-white"> </span><span class="text-white"><div class=""><span class="italic font-bold text-blue-500">Dylan, Developer</span>: I don&#x27;t want to disappoint you Adam, but someone needed to make this decision as we were in the dead corner - it felt like a natural place, I mean, BVM.</div></span><span class="text-white"> </span><span class="text-white"><div class=""><span class="italic font-bold text-yellow-500">Don, Developer</span>: So, what exactly is BVM?</div></span><span class="text-white"><p><em>All looked at each other, confused.</em></p></span></div><h3 id="i-decide"><a href="#i-decide" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;I decide&quot;</h3><p>Imagine that we are in a meeting, observing a discussion related to the architecture of a new part of the system.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div class=""><span class="italic font-bold text-blue-500">Dylan, Developer</span>: I believe we should use BVM service to start the whole workflow.</div></span><span class="text-white"> </span><span class="text-white"><div class=""><span class="italic font-bold text-green-500">David, Developer</span>: BVM? What about Integration Platform - didn&#x27;t we decide to use it next time for this type of job?</div></span><span class="text-white"> </span><span class="text-white"><div class=""><span class="italic font-bold text-yellow-500">Don, Developer</span>: Sorry for a dummy question, but I am new here - what is...</div></span><span class="text-white"> </span><span class="text-white"><div class=""><span class="italic font-bold text-red-500">Adam, Architect</span>: I don&#x27;t want to destroy your ideas, but I planned this architecture long time ago - here is the primary sketch I did 2 years ago.</div></span><span class="text-white"><p><em>All looked at the PowerPoint presentation that <span class="italic font-bold text-red-500">Adam, Architect</span> is showing them.</em></p></span><span class="text-white"><div class=""><span class="italic font-bold text-green-500">David, Developer</span>: Adam, this won&#x27;t work. Your sketch misses one important part - configuration API isn&#x27;t ready, as our Shared Host Integration Terminal team is still gathering requirements from the entire company.</div></span><span class="text-white"> </span><span class="text-white"><div class=""><span class="italic font-bold text-red-500">Adam, Architect</span>: Wait, so we don&#x27;t use CCP - Common Configuration Platform?</div></span><span class="text-white"> </span><span class="text-white"><div class=""><span class="italic font-bold text-blue-500">Dylan, Developer</span>: Yhm, no. We wrote our own to deliver sooner.</div></span><span class="text-white"> </span><span class="text-white"><div class=""><span class="italic font-bold text-red-500">Adam, Architect</span>: Just to remind you, I am the single point for making decisions. You really need to ask me to get a green light.</div></span><span class="text-white"><p><em>All developers looked at each other, confused.</em></p></span></div><p>Confused people remained confused, PowerPoint presentation kept all the decisions, completely ignoring the facts that happened since 2 years passed, when this presentation was made.</p><h3 id="i-record"><a href="#i-record" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;I record&quot;</h3><p>Next time, there was another meeting named &quot;Dev team &amp; arch sync&quot;, where the same people gathered. There was no agenda, 25 min planned.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div class=""><span class="italic font-bold text-red-500">Adam, Architect</span>: Hey guys! I&#x27;ve learned about recording decisions using a special template, hence I prepared a short decision record on using abstract classes. It is available on department&#x27;s sharepoint. If you have any questions we can continue, else just go for lunch.</div></span><span class="text-white"><p><em>All looked at the Word document describing the decision that <span class="italic font-bold text-red-500">Adam, Architect</span> is showing them.</em></p></span><span class="text-white"><div class=""><span class="italic font-bold text-green-500">David, Developer</span>: Adam, what about TypeScript and SPAs - we don&#x27;t use abstract classes.</div></span><span class="text-white"> </span><span class="text-white"><div class=""><span class="italic font-bold text-red-500">Adam, Architect</span>: So why don&#x27;t you just start using them?</div></span><span class="text-white"> </span><span class="text-white"><div class=""><span class="italic font-bold text-blue-500">Dylan, Developer</span>: Well, I think we should focus on the recent outage and finding a way to improve how we handle the excessive load.</div></span><span class="text-white"> </span><span class="text-white"><div class=""><span class="italic font-bold text-red-500">Adam, Architect</span>: Just to remind you, I am the single point for making decisions. You really need to ask me to get a green light.</div></span><span class="text-white"><p><em>All developers looked at each other, confused.</em></p></span></div><h3 id="where-is-the-value"><a href="#where-is-the-value" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Where is the value?</h3><p>Have you experienced something similar, dear Reader?</p><p>Decisions in PowerPoint slides, outdated and forgotten Word documents that are never read.</p><p>Produced by individuals, not even architects, but in total isolation from &quot;the doers&quot;.</p><p>&quot;Architecture Decision Records are not needed, as no one reads them&quot; - one might say.</p><p>&quot;Only architects should decide, as they have the big picture&quot; - another one could argue.</p><p>Well, both observations, and many others, might be actually &quot;true&quot;.</p><p>It varies from company to company, team to team, and even person to person.</p><p>It&#x27;s a slippery slope to say &quot;we do ADRs here&quot; and not fall into <a href="https://talesfrom.dev/blog/tools-make-fools">Tools make fools</a> type of a problem.</p><p>But as with other tools (and I believe ADRs are &quot;just&quot; a tool), the value is in the reason we use them.</p><p>Often, people are not aligned on <em>why</em> they do certain things.</p><p>A solution is picked and all just do what is needed to satisfy going in this direction.</p><p>What about other options?</p><p>What is the current context?</p><p>Every best practice, when misapplied, becomes an anti-pattern.</p><p>Are there any design constraints?</p><h3 id="any-decision-records"><a href="#any-decision-records" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Any Decision Records?</h3><p>Turns out that we often &quot;feel&quot; what might be a good approach for a given problem.</p><p>Considering that we are dealing with an actual problem, not the one that got &quot;solutioned&quot; (or in other words, &quot;coming up with a problem to bravely solve it&quot;).</p><p>It might be that the real value of &quot;Architecture Decision Records&quot; is not in recording decisions, but in <em>thinking</em> about them.</p><p>Going through the processes of collaborative designing, sketching, and figuring out the surroundings.</p><p>It&#x27;s very easy (as a reminder - <a href="https://talesfrom.dev/blog/simple-isnt-easy">Simple isn&#x27;t easy</a>!) to look at ADRs as a static &quot;thing&quot;, just <a href="https://talesfrom.dev/blog/modeling-maturity-levels">being</a> there.</p><p>Magic starts when we think of it as <strong>a process</strong>.</p><p>A stream of events that is produced when people meet together and <a href="https://talesfrom.dev/blog/modeling-maturity-levels">become</a> <a href="https://talesfrom.dev/blog/the-ambiguity-of-team-work">the Overmind</a> - all to collectively bring multitude of perspectives, experiences and knowledge.</p><p>During such sessions, all learn - sometimes it&#x27;s about approaching architectural problems, dealing with trade-offs, and in other times - <em>just</em> learning that patience is really vital when working together.</p><p>A nice side effect is that we get a record that more-a-less captures the context, rejected options and the solution candidate.</p><p>Recently, LLMs can help with mundane tasks like formatting, etc.</p><p>What&#x27;s more, when decisions are recorded, LLMs could help with building the knowledge stream of decisions.</p><p>Of course, it&#x27;s a different problem how to make it useful, but we have tools at our disposal.</p><h3 id="design-deciding-process"><a href="#design-deciding-process" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Design Deciding Process?</h3><p>Similar to a Zen Koan, we could express:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>“When a wise man points at a collaborative designing with recording decisions, the fools look at recording decisions, not at a collaborative designing.”</p></div></div></div><p>Play a role in the stream, participate in the process, experience <a href="https://en.wikipedia.org/wiki/Panta_rhei_(doctrine)">Panta rhei</a>!</p><p><a href="https://talesfrom.dev/blog/slow-down">Slow down</a> and become one with <a href="https://talesfrom.dev/blog/the-ambiguity-of-team-work">the Overmind</a>.</p><p>Laying down the options, seeing the current context - this really contributes to better understanding.</p><p>And <em>seeing</em> those trade-offs.</p><p>A true power of a senior engineer or an architect is the ability to &quot;produce&quot; more senior engineers and architects, not solving hard problems or drawing eye-catching sketches.</p><p>No single ninja, rockstar developer or hero architect will provide a long-term value.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>The Toyota Production System (TPS) embodies the wisdom of ordinary people through its foundational principles that empower every employee to contribute to continuous improvement and quality.</p></div></div></div>]]></content:encoded>
    <pubDate>Fri, 22 Aug 2025 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>design thinking</category><category>domain-driven design</category><category>language patterns</category><category>design patterns</category><category>software architecture</category><category>mental models</category><category>communication</category><category>knowledge working</category><category>balancing coupling</category><category>collaboration</category><category>software teaming</category><category>understanding</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/the-knowledge-gravity-problem</guid>
    <title>The knowledge gravity problem</title>
    <link>https://talesfrom.dev/blog/the-knowledge-gravity-problem</link>
    <description>Is there a force driving our systems towards complexity?</description>
    <content:encoded><![CDATA[<div class="bg-slate-600 rounded-xl "><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Attention #1!</span></div><div class="pb-2 px-3"><div class="break-words"><p>I hugely recommend reading <a href="https://www.amazon.com/Balancing-Coupling-Software-Design-Addison-Wesley-ebook/dp/B09RV3Z3TP">Balancing Coupling</a> by <a href="https://www.linkedin.com/in/vladikk/">Vlad Khononov</a>, it&#x27;s worth reading and tinkering!</p></div></div></div> <div class="bg-slate-600 rounded-xl mt-5"><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Attention #2!</span></div><div class="pb-2 px-3"><div class="break-words"><p>The example comes from one of the comments to this <a href="https://www.youtube.com/watch?v=YTydbtFGfdk&amp;t=4s&amp;ab_channel=CodeOpinion">video</a>, and got a follow-up by Derek <a href="https://youtu.be/ZvY5fREVyZk?si=ppFcW-b8ufMbvqSR">here</a></p></div></div></div><h3 id="total-innovation"><a href="#total-innovation" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Total innovation!</h3><p>This is Tom (you might recognize him from <a href="https://talesfrom.dev/blog/the-ambiguity-the-curse-and-the-fallacy-of-domain-model">The ambiguity, the curse and the fallacy of domain model</a> or from <a href="https://talesfrom.dev/blog/many-faces-of-ddd-aggregates-in-fsharp">Many Faces of DDD Aggregates in F#</a>).</p><p>He is a business owner and really likes helping people.</p><p>He came to us to get some help with his new idea.</p><div class="flex flex-col "><div class="flex flex-col"><div class="flex justify-center items-center flex-col"><div class="flex max-sm:flex-col justify-between items-center"><img src="https://talesfrom.dev/static/images/business-man.png" class="max-h-[30rem]"/><div class="flex flex-col justify-between text-left"><span>Tom says:</span><span class="my-4 italic"><span class=""><p>Hi! I&#x27;m Tom and I have a great idea to start up a new initiative.</p></span><span class=""><p>It&#x27;s about gathering specialists and allowing them to share their knowledge.</p></span><div class="my-3"><span class="">To do that, we will organize a special </span><span class="mr-2">group chat</span><span class="">. Each </span><span class="mr-2">group chat</span><span class="">will </span><span class="mr-2">have a specific topic</span><span class="">and will </span><span class="mr-2">have chat members</span><span class="">- they will be able to discuss the topic.</span></div><div class="my-3"><span class="">Each </span><span class="mr-2">member</span><span class="">will </span><span class="mr-2">have a profile</span><span class="">with </span><span class="mr-2">details about their expertise</span><span class="">.</span></div><div class="my-3"><span class="">Additionally, each </span><span class="mr-2">member</span><span class="">will </span><span class="mr-2">have a status indicating if they get accepted to this chat</span><span class="">.</span></div><span class=""><p>Do you think we can build it?</p></span></span></div></div></div></div><div class="flex justify-around mt-10 lg:mx-32"><button class="bg-gray-600 border-gray-100 text-gray-400 p-2 rounded">Just talk</button><button class="bg-green-700 text-white border-2 p-2 rounded">Listening carefully</button></div></div><p>That&#x27;s really intersting, Tom!</p><p>It&#x27;s great that we learned Domain-Driven Design and we can apply the knowledge.</p><p>To express the domain language, also known as Ubiquitous Language, let&#x27;s capture important <em>entities</em> like <code>GroupChat</code> and <code>Member</code>.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">GroupChat</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> Topic <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">init</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">List<span class="token punctuation">&lt;</span>Member<span class="token punctuation">&gt;</span></span> Members <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">init</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Member</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">MemberProfile</span> Profile <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">init</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">bool</span></span> IsAccepted <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">init</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">MemberProfile</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">Guid</span> Id <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">init</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> Name <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">init</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> Expertise <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">init</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Let&#x27;s check with Tom if we understood him correctly.</p><p>But before that, one should not forget that many people interested in Domain-Driven Design (DDD) say that rules are a very important concept in DDD - much more important than just <em>entities</em>.</p><p>If you recall dear Reader, in <a href="https://talesfrom.dev/blog/many-faces-of-ddd-aggregates-in-fsharp">Many Faces of DDD Aggregates in F#</a> we tried to think about rules (also known as invariants) and make them always &quot;valid&quot;.</p><p>Should we do the same here?</p><div class="flex flex-col "><div class="flex flex-col"><div class="flex justify-center items-center flex-col"><div class="flex max-sm:flex-col justify-between items-center"><img src="https://talesfrom.dev/static/images/business-man.png" class="max-h-[30rem]"/><div class="flex flex-col justify-between text-left"><span>Tom says:</span><span class="my-4 italic"><span class=""><p>Rules? Yes, of course!</p></span><div class="my-3"><span class="">We have some rules for our </span><span class="mr-2">group chat</span><span class="">.</span></div><div class="my-3"><span class="">There can be only </span><span class="mr-2">1000 members accepted</span><span class="">in a </span><span class="mr-2">group chat</span><span class="">.</span></div><div class="my-3"><span class="">Also, each </span><span class="mr-2">member</span><span class="">can be </span><span class="mr-2">accepted only once</span><span class="">to a given </span><span class="mr-2">group chat</span><span class="">.</span></div></span></div></div></div></div><div class="flex justify-around mt-10 lg:mx-32"><button class="bg-gray-600 border-gray-100 text-gray-400 p-2 rounded">Just talk</button><button class="bg-green-700 text-white border-2 p-2 rounded">Listening carefully</button></div></div><p>Finally, rules, hence some operations that need to be performed on our <em>entities</em>!</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">GroupChat</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> Topic <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">init</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">List<span class="token punctuation">&lt;</span>Member<span class="token punctuation">&gt;</span></span> Members <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">init</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">void</span></span> <span class="token function">AddMember</span><span class="token punctuation">(</span><span class="token class-name">Member</span> member<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">if</span> <span class="token punctuation">(</span>Members<span class="token punctuation">.</span>Count <span class="token operator">&lt;</span> <span class="token number">1000</span> <span class="token operator">&amp;&amp;</span> <span class="token operator">!</span>Members<span class="token punctuation">.</span><span class="token function">Contains</span><span class="token punctuation">(</span>member<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// 👈 protecting invariants!</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            Members<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span>member<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            member<span class="token punctuation">.</span><span class="token function">Accept</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 👈 we&#x27;ve added domain-sounding method!</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Seems like <code>GroupChat</code> is a good candidate for an DDD <em>aggregate</em>, isn&#x27;t it?</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">GroupChat</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">AggregateRoot<span class="token punctuation">&lt;</span>GroupChatId<span class="token punctuation">&gt;</span></span></span> <span class="token comment">// 👈 must-have in a real DDD project!</span>
</span></code></pre></div></div><p>Ok, this looks good.</p><h3 id="change-change-never-changes"><a href="#change-change-never-changes" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Change, change never changes</h3><p>Imagine we got a quick chat (pun intended) with Tom and he told us that he wants to put a name on the <code>GroupChat</code>.</p><p>Fair enough. It&#x27;s a simple change.</p><p>&quot;Name quickly, rename even quicker&quot;, as they say, right?</p><p>So let&#x27;s add a possibility to rename a <code>GroupChat</code>.</p><p>We know that Tom did not asked about it, but it&#x27;s not the first system we built, and we know those business folks.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">GroupChat</span><span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">AggregateRoot<span class="token punctuation">&lt;</span>GroupChatId<span class="token punctuation">&gt;</span></span></span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> Topic <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">init</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> Name <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">init</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// 👈 new property!</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">List<span class="token punctuation">&lt;</span>Member<span class="token punctuation">&gt;</span></span> Members <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">init</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">void</span></span> <span class="token function">Rename</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> newName<span class="token punctuation">,</span> <span class="token class-name">Member</span> renamingMember<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">if</span><span class="token punctuation">(</span>renamingMember<span class="token punctuation">.</span><span class="token function">CanRenameGroupChat</span><span class="token punctuation">(</span>Id<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 👈 check if member can rename the group chat</span>
</span><span class="code-line">           Name <span class="token operator">=</span> newName<span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">        <span class="token keyword">throw</span> Domain<span class="token punctuation">.</span><span class="token function">Error</span><span class="token punctuation">(</span><span class="token string">&quot;Group chat cannot be renamed by this member.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Yeah, as we (speculatively) added a new behavior, we also needed to adjust <code>Member</code> to include information related to permissions.</p><p>We also heard that there&#x27;s an idea to let members establish nicknames for themselves in the <code>GroupChat</code>.</p><p>But let&#x27;s wait with implementing that.</p><h3 id="retrospection"><a href="#retrospection" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Retrospection!</h3><p>Now, let&#x27;s take a step back and look at what we have.</p><p>What do you think about this design, dear Reader?</p><p>I really hope you feel and see that I am exaggerating a bit, as no one creates such domain models, right?</p><p>We typically think about how concepts are going to be used, what are the conditions and contexts those concepts are operating in, isn&#x27;t it?</p><p>If we followed this design, we might eventually fall into the trap related to <a href="https://talesfrom.dev/blog/the-ambiguity-the-curse-and-the-fallacy-of-domain-model">The ambiguity, the curse and the fallacy of domain model</a>.</p><p>We would try to build up a compile-time, absolute-based, reality-chasing model - as we hear the language while talking with the &quot;business people&quot;.</p><h3 id="knowledge-attracts-knowledge"><a href="#knowledge-attracts-knowledge" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Knowledge attracts knowledge?</h3><p>But it seems that there&#x27;s an interesting phenomenon happening.</p><p>Imagine that we have a problem space - let&#x27;s represent it like this:</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-knowledge-gravity-problem-problem-space-1.png" class="max-h-[30rem]"/></div></div><p>As Tom <em>named</em> the concept living in this particular problem space, a boundary got established.</p><p>We could call it &quot;a knowledge boundary&quot; (you can read more about this topic by reading <a href="https://www.amazon.com/Balancing-Coupling-Software-Design-Addison-Wesley-ebook/dp/B09RV3Z3TP">Balancing Coupling</a>).</p><div class="flex justify-center items-center flex-col"><div class="flex flex-col justify-between items-center"><img src="https://talesfrom.dev/static/images/the-knowledge-gravity-problem-knowledge-boundary-1.png" class="max-h-[30rem]"/><div class="italic mx-24">A knowledge boundary that got established within a particular problem space.</div></div></div><p>By directly following the language, we could say that we brought <em>a named space</em> into existence.</p><p>The more we explore, the time flies by, and more and more concepts are appearing in this space.</p><div class="flex justify-center items-center flex-col"><div class="flex flex-col justify-between items-center"><img src="https://talesfrom.dev/static/images/the-knowledge-gravity-problem-more-concepts-1.png" class="max-h-[30rem]"/><div class="italic mx-24">More concepts are appearing.</div></div></div><p>In our tiny exercise, when a <code>Name</code> concept appeared (and he speculatively added &quot;renaming&quot; behavior), didn&#x27;t it seem almost &quot;natural&quot; to integrate it into the <code>GroupChat</code>?</p><p>As if <code>GroupChat</code> was attracting this concept, as it seemed conceptually &quot;close&quot; to it.</p><p>We could start reasoning: the knowledge boundary that got framed by <code>GroupChat</code> concept is attracting concepts with varying force.</p><p>Some words feel more conceptually close to <code>GroupChat</code> (or <code>Member</code>, which is conceptually close to <code>GroupChat</code>), while others are more &quot;distant&quot; (or different).</p><p>This seems like a very subtle process, especially when the existing &quot;structure&quot; (here: compile-time hierarchies, <strong>the</strong> domain model) is rigid and pushes back (resists) doing changes in an agile and swift manner.</p><p>And of course there&#x27;s a time pressure, deadlines, no time for &quot;refactoring&quot;, and so on.</p><p>So those structures accomodate more and more knowledge.</p><div class="flex justify-center items-center flex-col"><div class="flex flex-col justify-between items-center"><img src="https://talesfrom.dev/static/images/the-knowledge-gravity-problem-attracting-concepts.png" class="max-h-[30rem]"/><div class="italic mx-24">Knowledge is attracting more knowledge.</div></div></div><p><strong>The domain model</strong> attracts more concepts, integrating them into itself, hence growing.</p><p>As it grows, it attracts even more knowledge, as new appearing concepts are more likely to be conceptually close to this knowledge boundary.</p><p>And the cycle continues.</p><p>New requirements are coming, and when we take them and think where to &quot;place them&quot;, there&#x27;s a high chance that the most suitable place is within this all-the-time growing boundary.</p><p>Then &quot;the structure&quot; becomes complex, messy thing to work with.</p><p>And when we add data in the database, baking the structure up, it gets even more complex and knowledge-heavy.</p><div class="flex justify-center items-center flex-col"><div class="flex flex-col justify-between items-center"><img src="https://talesfrom.dev/static/images/the-knowledge-gravity-problem-structure-growing.png" class="max-h-[30rem]"/><div class="italic mx-24">Knowledge boundary growing over time</div></div></div><p>At some point, this little concept that started inside of &quot;a named space&quot;, became a &quot;God class&quot; - knowing everything about everything, and being responsible for everything.</p><p>There might be more of such concepts, each trying to attract more and more knowledge.</p><h3 id="a-force"><a href="#a-force" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>A force?</h3><p>Might it be that when we express &quot;the knowledge&quot; by naming something, &quot;a knowledge boundary&quot; gets established?</p><p>And immediately when it gets established, it starts attracting more and more knowledge?</p><p>Let&#x27;s summon <a href="https://www.linkedin.com/in/vladikk/">Vlad&#x27;s</a> formula:</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">PAIN dimensions</div><div class="pb-2 px-3"><div class="break-words"><p>PAIN = f(Strength, Volatility, Distance)</p>
<p>PAIN = Strength x Volatility x Distance</p></div></div></div><p>It uses three dimensions, one of which is &quot;(integration) strength&quot;, representing the knowledge shared among two <em>concepts</em>.</p><p>Let&#x27;s play and try to think about this &quot;strength&quot; dimension as &quot;a force&quot;.</p><p>I really like definitions so let&#x27;s check our <a href="https://www.merriam-webster.com/dictionary/force">match</a>:</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">a force - definition</div><div class="pb-2 px-3"><div class="break-words"><p><strong>strength</strong> or energy exerted or brought to bear : cause of motion or change : active power</p></div></div></div><p>It seems it makes sense.</p><p>We saw that the knowledge boundary (<code>KB</code>) was attracting more concepts (<code>C</code>), trying to close the distance between them.</p><p>The closer conceptually they were, the stronger the force was.</p><p>We could think about this force as a simple function:</p><div class="math math-display"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi mathvariant="bold">&quot;</mi><mi mathvariant="bold">f</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">r</mi><mi mathvariant="bold">c</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">&quot;</mi></mrow><mo stretchy="false">(</mo><mi>K</mi><mi>B</mi><mo separator="true">,</mo><mi>C</mi><mo separator="true">,</mo><mi>d</mi><mo stretchy="false">)</mo><mo>=</mo><mfrac><mrow><mi>K</mi><mi>B</mi><mo>⋅</mo><mi>C</mi></mrow><msup><mi>d</mi><mn>2</mn></msup></mfrac></mrow><annotation encoding="application/x-tex">\mathbf{&quot;force&quot;}(KB, C, d) = \frac{KB \cdot C}{d^2}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-.25em"></span><span class="mord"><span class="mord mathbf">&quot;force&quot;</span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:.07153em">K</span><span class="mord mathnormal" style="margin-right:.05017em">B</span><span class="mpunct">,</span><span class="mspace" style="margin-right:.1667em"></span><span class="mord mathnormal" style="margin-right:.07153em">C</span><span class="mpunct">,</span><span class="mspace" style="margin-right:.1667em"></span><span class="mord mathnormal">d</span><span class="mclose">)</span><span class="mspace" style="margin-right:.2778em"></span><span class="mrel">=</span><span class="mspace" style="margin-right:.2778em"></span></span><span class="base"><span class="strut" style="height:2.0463em;vertical-align:-.686em"></span><span class="mord"><span class="nulldelimiter mopen"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3603em"><span style="top:-2.314em"><span class="pstrut" style="height:3em"></span><span class="mord"><span class="mord"><span class="mord mathnormal">d</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:.7401em"><span style="top:-2.989em;margin-right:.05em"><span class="pstrut" style="height:2.7em"></span><span class="mtight reset-size6 size3 sizing"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span><span style="top:-3.23em"><span class="pstrut" style="height:3em"></span><span class="frac-line" style="border-bottom-width:.04em"></span></span><span style="top:-3.677em"><span class="pstrut" style="height:3em"></span><span class="mord"><span class="mord mathnormal" style="margin-right:.07153em">K</span><span class="mord mathnormal" style="margin-right:.05017em">B</span><span class="mspace" style="margin-right:.2222em"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:.2222em"></span><span class="mord mathnormal" style="margin-right:.07153em">C</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:.686em"><span></span></span></span></span></span><span class="nulldelimiter mclose"></span></span></span></span></span></span></div><p>Where:</p><ul><li><code>KB</code> is the knowledge boundary (or a concept)</li><li><code>C</code> is the concept (yet another knowledge boundary?)</li><li><code>d</code> is the conceptual difference between <code>KB</code> and <code>C</code> (the distance between them)</li></ul><p>Of course it&#x27;s completely made up and not based on any scientific research - just a thought experiment, pure anecdotal concept.</p><p>But wait a second, dear Reader.</p><p>Isn&#x27;t it strange?</p><p>Maybe there is a force that expresses how particles or celestial bodies attract each other?</p><p>Let&#x27;s bring the formula from <a href="https://en.wikipedia.org/wiki/Newton%27s_law_of_universal_gravitation">Newton&#x27;s law of universal gravitation</a>:</p><div class="math math-display"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mo>=</mo><mi>G</mi><mfrac><mrow><msub><mi>m</mi><mn>1</mn></msub><msub><mi>m</mi><mn>2</mn></msub></mrow><msup><mi>d</mi><mn>2</mn></msup></mfrac></mrow><annotation encoding="application/x-tex">F = G \frac{m_1 m_2}{d^2}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:.6833em"></span><span class="mord mathnormal" style="margin-right:.13889em">F</span><span class="mspace" style="margin-right:.2778em"></span><span class="mrel">=</span><span class="mspace" style="margin-right:.2778em"></span></span><span class="base"><span class="strut" style="height:1.7936em;vertical-align:-.686em"></span><span class="mord mathnormal">G</span><span class="mord"><span class="nulldelimiter mopen"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1076em"><span style="top:-2.314em"><span class="pstrut" style="height:3em"></span><span class="mord"><span class="mord"><span class="mord mathnormal">d</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:.7401em"><span style="top:-2.989em;margin-right:.05em"><span class="pstrut" style="height:2.7em"></span><span class="mtight reset-size6 size3 sizing"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span><span style="top:-3.23em"><span class="pstrut" style="height:3em"></span><span class="frac-line" style="border-bottom-width:.04em"></span></span><span style="top:-3.677em"><span class="pstrut" style="height:3em"></span><span class="mord"><span class="mord"><span class="mord mathnormal">m</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:.3011em"><span style="top:-2.55em;margin-left:0;margin-right:.05em"><span class="pstrut" style="height:2.7em"></span><span class="mtight reset-size6 size3 sizing"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:.15em"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">m</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:.3011em"><span style="top:-2.55em;margin-left:0;margin-right:.05em"><span class="pstrut" style="height:2.7em"></span><span class="mtight reset-size6 size3 sizing"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:.15em"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:.686em"><span></span></span></span></span></span><span class="nulldelimiter mclose"></span></span></span></span></span></span></div><p>As our &quot;force&quot; is made up, of course gravity is not an anecdotal, at all.</p><p>But could we say that &quot;knowledge&quot; generates gravity-like force?</p><h3 id="the-knowledge-gravity-problem"><a href="#the-knowledge-gravity-problem" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The knowledge gravity problem</h3><p>Considering that when we establish knowledge boundaries, &quot;create&quot; <em>named spaces</em>, we might be exposing ourselves to the knowledge gravity problem.</p><p>If knowledge boundary is too &quot;big&quot; (capacious), it might be conceptually close to many other concepts (knowledge particles), like we saw in the example with <code>GroupChat</code>.</p><p>We could take any other attempt to express <strong>the</strong> domain model that will be reality-chasing, absolute-based God class - we might end up with a similar phenomenon.</p><p>We all know that such &quot;God classes&quot; often follow Noun-based design, the way of thinking that is very common in the industry - &quot;what I hear, I represent&quot;.</p><p>It might be that all those cautionary tales about &quot;death stars&quot; have more &quot;truth&quot; than we think, as knowledge boundaries might generate gravitational-like force.</p><p>Noun-based, contextless and use case agnostic models, like &quot;User&quot;, &quot;Product&quot;, &quot;Customer&quot;, &quot;Tour&quot; (we used that one in the previous <a href="https://talesfrom.dev/blog/the-ambiguity-the-curse-and-the-fallacy-of-domain-model">tale</a>), will grow and generate even stronger forces.</p><p>And it all started with <a href="https://talesfrom.dev/blog/simple-isnt-easy">a simple</a> &quot;idea&quot; (a concept), like &quot;let&#x27;s have a group chat&quot; - and then we &quot;named the space&quot; in a very particular way, hence establishing a knowledge boundary.</p><p>We rush to model relationships in the database, which contributes to even &quot;heavier structure&quot;.</p><h3 id="bounded-planets"><a href="#bounded-planets" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Bounded planets?</h3><p><em>A bounded context</em> is one of the concepts used in the strategic level of Domain-Driven Design.</p><p>One could say it&#x27;s &quot;a conceptual (logical) context that has a model bounded to it&quot;.</p><p>Can one say that in some sense a bounded context is a &quot;knowledge boundary&quot;?</p><p>Hence, each of the contexts could be metaphorically represented as a &quot;planet&quot; in the universe (&quot;the solution space&quot;)?</p><p>If we take this metaphor, one could conclude that each of those &quot;planets&quot; generates its own gravitational force, supporting or contradicting each other.</p><div class="flex justify-center items-center flex-col"><div class="flex flex-col justify-between items-center"><img src="https://talesfrom.dev/static/images/the-knowledge-gravity-problem-planets.png" class="max-h-[30rem]"/><div class="italic mx-24">&quot;Knowledge planets&quot; in a solution space</div></div></div><p>If we take our <code>GroupChat</code> example and try to express boundaries in a slightly different way by applying <a href="https://talesfrom.dev/blog/context-segregation-principle">context segregation principle</a> and using various heuristics (like <a href="https://particular.net/blog/antirequirements">anti-requirements</a>), we might get different &quot;knowledge boundaries&quot;.</p><p>One of them could be <code>GroupChatMemberOnboarding</code>, which would be responsible for onboarding members to the <code>GroupChat</code>.</p><p>It would have only the knowledge required for running the process of onboarding members.</p><p>Of course, <a href="https://talesfrom.dev/blog/the-law-of-eventual-composition">The law of eventual composition</a> never stops, and by segregating the contexts in this way, we would need to integrate them back.</p><p>But we might get something back, like well-balanced gravity forces, which contribute to dealing with complexity in a different way.</p><p>Then, &quot;renaming a group chat&quot; knowledge would belong to a different context - <code>GroupChatDetails</code> - as it typically does not have huge traffic (of course we play with the example, but you get the point, dear Reader).</p><p>&quot;The knowledge gravity problem&quot; might be a fractal phenomenon, appearing on various levels of abstraction - functions, components, teams, and organizations - similarly to what we saw in Vlad&#x27;s book <a href="https://www.amazon.com/Balancing-Coupling-Software-Design-Addison-Wesley-ebook/dp/B09RV3Z3TP">Balancing Coupling</a>.</p><p>And (again) one of the conclusions might be:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Boundaries (encapsulation) are one of the most important aspects when designing software</p></div></div></div><p>By estabishing them carelessly, we might expose our systems, and ourselves to the problem discussed.</p><p>All the big systems should start <a href="https://talesfrom.dev/blog/from-concepts-to-architecture">From concepts to architecture</a>, making sure that there will be no &quot;God knowledge boundary&quot; attracting every concept in the horizon.</p><h3 id="software-knowledge-gravity"><a href="#software-knowledge-gravity" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Software? Knowledge? Gravity?</h3><p>&quot;How can you compare physics and software, Damian?&quot;, you might ask, dear Reader.</p><p>I can&#x27;t and I don&#x27;t even try to.</p><p>We are playing with ideas and metaphors (and I love them so much!) so that we can change our thinking and <a href="https://talesfrom.dev/blog/context-segregation-principle">perspective</a> and design better systems.</p><p>I hope that if next time at least one person thinks that &quot;this concept is too big&quot; or &quot;when I name, I create a knowledge boundary&quot;, the world would be a better place.</p><p>Even if no one formally examined &quot;knowledge partices&quot;, using the magnifying glass or microscope, we can still load certain mental models into our heads to <em>see</em> same things differently.</p><p>Tools are interesting and useful, but if the thinking isn&#x27;t supported by principles and going deeper in understanding why we do things in a certain way, <a href="https://talesfrom.dev/blog/tools-make-fools">we might become fools</a>.</p><p>So next time dear Reader when dealing with a problem or a task, think about the knowledge gravity, and ask yourself:</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>Why did we name <em>it</em> like this? What do we try to represent now?</p></div></div></div>]]></content:encoded>
    <pubDate>Thu, 07 Aug 2025 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>design thinking</category><category>domain-driven design</category><category>language patterns</category><category>design patterns</category><category>object-oriented design</category><category>functional programming</category><category>software architecture</category><category>mental models</category><category>communication</category><category>knowledge working</category><category>balancing coupling</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/the-ambiguity-the-curse-and-the-fallacy-of-domain-model</guid>
    <title>The ambiguity, the curse and the fallacy of domain model</title>
    <link>https://talesfrom.dev/blog/the-ambiguity-the-curse-and-the-fallacy-of-domain-model</link>
    <description>Is it possible to &quot;apply&quot; Entity Component System (ECS) thinking to System Design?</description>
    <content:encoded><![CDATA[<div class="bg-slate-600 rounded-xl "><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Attention #1!</span></div><div class="pb-2 px-3"><div class="break-words"><p>This tale referrs to topics presented in a great <a href="https://www.youtube.com/watch?app=desktop&amp;v=wo84LFzx5nI&amp;ab_channel=BetterSoftwareConference">presentation</a> given by <a href="https://x.com/cmuratori">Casey Muratori</a>. I strongly advise watching it (even before reading this tale).</p></div></div></div> <div class="bg-slate-600 rounded-xl mt-10"><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Attention #2!</span></div><div class="pb-2 px-3"><div class="break-words"><p>This blogpost is <strong>not</strong> an Entity Component System (ECS) tutorial, although we&#x27;re going to try to exploit some of the ideas from ECS.</p></div></div></div> <div class="bg-slate-600 rounded-xl mt-10"><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Attention #3!</span></div><div class="pb-2 px-3"><div class="break-words"><p>This blogpost will use pseudocode in a TypeScript (TS) like syntax - as TS does not support multiple inheritance, we still could use mixins to achieve similar reusability (and pains).</p></div></div></div> <div class="bg-slate-600 rounded-xl mt-10"><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Attention #4!</span></div><div class="pb-2 px-3"><div class="break-words"><p>I am not doing game development professionally (I am gamedev noob!), so I might be wrong in some places when it comes to ECS and gamedev related parts.</p></div></div></div><h3 id="how-can-we-help"><a href="#how-can-we-help" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>How can we help?</h3><p>Meet Tom (you might recall him from <a href="https://talesfrom.dev/blog/many-faces-of-ddd-aggregates-in-fsharp">Many Faces of DDD Aggregates in F#</a>).</p><p>As a successful businessman, after he earned tons of money with disco clubs, he decided to start creating games.</p><div class="flex flex-col "><div class="flex flex-col"><div class="flex justify-center items-center flex-col"><div class="flex max-sm:flex-col justify-between items-center"><img src="https://talesfrom.dev/static/images/business-man.png" class="max-h-[30rem]"/><div class="flex flex-col justify-between text-left"><span>Tom says:</span><span class="my-4 italic"><span class=""><p>Hi, my name is Tom.</p></span><span class=""><p>I have some money to invest in game development, as I heard is a very lucrative domain.</p></span><div class="my-3"><span class="">I want to </span><span class="mr-2">start small</span><span class="">and see if I can get some feedback.</span></div><span class=""><p>Can you help me with some ideas?</p></span></span></div></div></div></div><div class="flex justify-around mt-10 lg:mx-32"><button class="bg-gray-600 border-gray-100 text-gray-400 p-2 rounded">Just talk</button><button class="bg-green-700 text-white border-2 p-2 rounded">Listening carefully</button></div></div><p>Game dev? Woah, that for sure will be a fun project! Let&#x27;s help Tom!</p><p>Tell us more, Tom.</p><div class="flex flex-col "><div class="flex flex-col"><div class="flex justify-center items-center flex-col"><div class="flex max-sm:flex-col justify-between items-center"><img src="https://talesfrom.dev/static/images/business-man.png" class="max-h-[30rem]"/><div class="flex flex-col justify-between text-left"><span>Tom says:</span><span class="my-4 italic"><span class=""><span>We want to build a simple game where a player tries to survive the robot following him.</span></span><div class="my-3"><span class="mr-2">The player</span><span class="">can </span><span class="mr-2">move</span><span class="">around, and </span><span class="mr-2">the robot</span><span class="">will </span><span class="mr-2">move</span><span class="">too and try to catch the player.</span></div><div class="my-3"><span class="mr-2">A person</span><span class="">playing the game </span><span class="mr-2">gets points</span><span class="">for each second survived, and the game ends when the robot catches the player.</span></div></span></div></div></div></div><div class="flex justify-around mt-10 lg:mx-32"><button class="bg-gray-600 border-gray-100 text-gray-400 p-2 rounded">Just talk</button><button class="bg-green-700 text-white border-2 p-2 rounded">Listening carefully</button></div></div><p>Hmm, seems too small for me, but hell - he&#x27;s the boss, isn&#x27;t it?</p><p>Time for designing the game. We know that there is a concept of a player and a robot, so let&#x27;s start with that.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">class</span> <span class="token class-name">Player</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token keyword">public</span> name<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Even though Tom didn&#x27;t mention it, we know that the player will have a name, so let&#x27;s add it.</p><p>Everyone has a name, right?</p><p>Now a robot.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">class</span> <span class="token class-name">Robot</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token keyword">public</span> type<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>It&#x27;s not just a robot, it&#x27;s a specific type of robot, so let&#x27;s add a type to it.</p><p>Yeah, Tom didn&#x27;t mention it, but we know how those business guys think - for sure they will want to add more types of robots in the future.</p><p>Both entities should be able to move (if you listed carefully, dear Reader), so let&#x27;s fix that.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">class</span> <span class="token class-name">Player</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token keyword">public</span> name<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">,</span> <span class="token keyword">private</span> position_x<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">,</span> <span class="token keyword">private</span> position_y<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token function">moveLeft</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 👈 new code!</span>
</span><span class="code-line">        <span class="token keyword">this</span><span class="token punctuation">.</span>position_x <span class="token operator">-=</span> <span class="token number">2</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token function">moveRight</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">this</span><span class="token punctuation">.</span>position_x <span class="token operator">+=</span> <span class="token number">2</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token function">moveUp</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">this</span><span class="token punctuation">.</span>position_y <span class="token operator">+=</span> <span class="token number">2</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token function">moveDown</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">this</span><span class="token punctuation">.</span>position_y <span class="token operator">-=</span> <span class="token number">2</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">class</span> <span class="token class-name">Robot</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token keyword">public</span> type<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">,</span> <span class="token keyword">private</span> position_x<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">,</span> <span class="token keyword">private</span> position_y<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token function">moveLeft</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 👈 new code!</span>
</span><span class="code-line">        <span class="token keyword">this</span><span class="token punctuation">.</span>position_x <span class="token operator">-=</span> <span class="token number">1</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token function">moveRight</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">this</span><span class="token punctuation">.</span>position_x <span class="token operator">+=</span> <span class="token number">1</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token function">moveUp</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">this</span><span class="token punctuation">.</span>position_y <span class="token operator">+=</span> <span class="token number">1</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token function">moveDown</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">this</span><span class="token punctuation">.</span>position_y <span class="token operator">-=</span> <span class="token number">1</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Great, both entities can move now. The player can move faster than the robot.</p><p>This should make it a little easier for the player to survive and get some points.</p><h3 id="start-small-but-grow-big"><a href="#start-small-but-grow-big" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Start small, but grow big?</h3><p>Wait a second, we forgot something important.</p><p>Even though Tom mentioned we are going to start small, we know how this works - sooner or later there will be more enemies.</p><p>Let&#x27;s do some refactoring to prepare for that.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">abstract</span> <span class="token keyword">class</span> <span class="token class-name">MovableEntity</span> <span class="token punctuation">{</span> <span class="token comment">// 👈 new code!</span>
</span><span class="code-line">    <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token keyword">private</span> position_x<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">,</span> <span class="token keyword">private</span> position_y<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
</span><span class="code-line">    
</span><span class="code-line">    <span class="token function">moveLeft</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">this</span><span class="token punctuation">.</span>position_x <span class="token operator">-=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>movementSpeed<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token function">moveRight</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">this</span><span class="token punctuation">.</span>position_x <span class="token operator">+=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>movementSpeed<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token function">moveUp</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">this</span><span class="token punctuation">.</span>position_y <span class="token operator">+=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>movementSpeed<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token function">moveDown</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">this</span><span class="token punctuation">.</span>position_y <span class="token operator">-=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>movementSpeed<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    
</span><span class="code-line">    <span class="token keyword">abstract</span> <span class="token keyword">get</span> <span class="token function">movementSpeed</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">class</span> <span class="token class-name">Player</span> <span class="token keyword">extends</span> <span class="token class-name">MovableEntity</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token keyword">public</span> name<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">,</span> position_x<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">,</span> position_y<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">super</span><span class="token punctuation">(</span>position_x<span class="token punctuation">,</span> position_y<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    
</span><span class="code-line">    <span class="token keyword">get</span> <span class="token function">movementSpeed</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 👈 to make the player faster than the robot</span>
</span><span class="code-line">        <span class="token keyword">return</span> <span class="token number">2</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">class</span> <span class="token class-name">Robot</span> <span class="token keyword">extends</span> <span class="token class-name">MovableEntity</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token keyword">public</span> type<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">,</span> position_x<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">,</span> position_y<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">super</span><span class="token punctuation">(</span>position_x<span class="token punctuation">,</span> position_y<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    
</span><span class="code-line">    <span class="token keyword">get</span> <span class="token function">movementSpeed</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 👈 to make the robot slower than the player</span>
</span><span class="code-line">        <span class="token keyword">return</span> <span class="token number">1</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>There should probably be a base class for all entities that can move, so we created <code>MovableEntity</code>.</p><p>It also aligns with our understanding of the domain - exactly how Tom described it.</p><p>Of course Tom is not a technical person and he didn&#x27;t say so but we know that both entites should be renderable!</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">abstract</span> <span class="token keyword">class</span> <span class="token class-name">RenderableEntity</span> <span class="token punctuation">{</span> <span class="token comment">// 👈 new code!</span>
</span><span class="code-line">    <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token keyword">private</span> position_x<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">,</span> <span class="token keyword">private</span> position_y<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">abstract</span> <span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span><span class="token punctuation">;</span> <span class="token comment">// 👈 new code</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">class</span> <span class="token class-name">Player</span> <span class="token keyword">extends</span> <span class="token class-name">MovableEntity</span><span class="token punctuation">,</span> RenderableEntity <span class="token punctuation">{</span> <span class="token comment">// ⚠️ we simulate that TS supports multiple inheritance</span>
</span><span class="code-line">    <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token keyword">public</span> name<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">,</span> position_x<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">,</span> position_y<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">,</span> <span class="token keyword">private</span> context<span class="token operator">:</span> CanvasRenderingContext2D<span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">super</span><span class="token punctuation">(</span>position_x<span class="token punctuation">,</span> position_y<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">// existing code...</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 👈 new code</span>
</span><span class="code-line">        context<span class="token punctuation">.</span>fillStyle <span class="token operator">=</span> <span class="token string">&quot;blue&quot;</span><span class="token punctuation">;</span>
</span><span class="code-line">        context<span class="token punctuation">.</span><span class="token function">fillRect</span><span class="token punctuation">(</span>position_x<span class="token punctuation">,</span> position_y<span class="token punctuation">,</span> <span class="token number">100</span><span class="token punctuation">,</span> <span class="token number">100</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">class</span> <span class="token class-name">Robot</span> <span class="token keyword">extends</span> <span class="token class-name">MovableEntity</span><span class="token punctuation">,</span> RenderableEntity <span class="token punctuation">{</span> <span class="token comment">// ⚠️ we simulate that TS supports multiple inheritance</span>
</span><span class="code-line">    <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token keyword">public</span> type<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">,</span> position_x<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">,</span> position_y<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">,</span> <span class="token keyword">private</span> context<span class="token operator">:</span> CanvasRenderingContext2D<span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">super</span><span class="token punctuation">(</span>position_x<span class="token punctuation">,</span> position_y<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">// existing code...</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 👈 new code</span>
</span><span class="code-line">        context<span class="token punctuation">.</span>fillStyle <span class="token operator">=</span> <span class="token string">&quot;red&quot;</span><span class="token punctuation">;</span>
</span><span class="code-line">        context<span class="token punctuation">.</span><span class="token function">fillRect</span><span class="token punctuation">(</span>position_x<span class="token punctuation">,</span> position_y<span class="token punctuation">,</span> <span class="token number">100</span><span class="token punctuation">,</span> <span class="token number">100</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Tom for sure will be happy to see that we are thinking ahead and preparing for future requirements.</p><p>The game loop will be responsible for rendering the entities. We skip it for brevity.</p><p>Let&#x27;s check our architecture so far:</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/domain-driven-design-gaming-and-entity-component-system-inheritance-1.png" class="max-h-[30rem]"/></div><div class="italic mx-24">The Hierarchy of entities and their relationships</div></div><p>Makes sense - <code>Player</code> entity <strong>is a</strong> <code>MovableEntity</code> and <strong>is a</strong> <code>RenderableEntity</code>, and the same goes for <code>Robot</code>.</p><p>Let&#x27;s see what Tom thinks about it.</p><div class="flex flex-col "><div class="flex flex-col"><div class="flex justify-center items-center flex-col"><div class="flex max-sm:flex-col justify-between items-center"><img src="https://talesfrom.dev/static/images/business-man.png" class="max-h-[30rem]"/><div class="flex flex-col justify-between text-left"><span>Tom says:</span><span class="my-4 italic"><span class=""><p>Yeah, the game is amazing, even though it looks so simple.</p></span><span class=""><p>As we are Agile, I asked some gamers to play it and got some feedback. They said that it&#x27;s pretty boring that we are just running away and robot is so naive.</p></span><div class="my-3"><span class="">Can we make it more interesting by making </span><span class="mr-2">the robot</span><span class="">capable of </span><span class="mr-2">attacking the player</span><span class="">?</span></div><div class="my-3"><span class="">Then </span><span class="mr-2">the player</span><span class="">will </span><span class="mr-2">have health</span><span class="">and could run away longer...</span></div></span></div></div></div></div><div class="flex justify-around mt-10 lg:mx-32"><button class="bg-gray-600 border-gray-100 text-gray-400 p-2 rounded">Just talk</button><button class="bg-green-700 text-white border-2 p-2 rounded">Listening carefully</button></div></div><h3 id="boring-game-wont-sell"><a href="#boring-game-wont-sell" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Boring game won&#x27;t sell</h3><p>Well, Tom is right, the game is boring.</p><p>Let&#x27;s add some attacking logic to the robot.</p><p>Of course, sooner or later the player will be able to attack the robot too, so let&#x27;s prepare for that!</p><p>Hehe, that&#x27;s a smart move.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">abstract</span> <span class="token keyword">class</span> <span class="token class-name">AttackingEntity</span> <span class="token punctuation">{</span> <span class="token comment">// 👈 new code</span>
</span><span class="code-line">    <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token keyword">private</span> position_x<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">,</span> <span class="token keyword">private</span> position_y<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
</span><span class="code-line">    
</span><span class="code-line">    <span class="token keyword">abstract</span> <span class="token function">attack</span><span class="token punctuation">(</span>entity<span class="token operator">:</span> EntityWithHealth<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span><span class="token punctuation">;</span> <span class="token comment">// 👈 we will define it in the next section</span>
</span><span class="code-line">    <span class="token keyword">abstract</span> <span class="token keyword">get</span> <span class="token function">attackPower</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">class</span> <span class="token class-name">Robot</span> <span class="token keyword">extends</span> <span class="token class-name">MovableEntity</span><span class="token punctuation">,</span> RenderableEntity<span class="token punctuation">,</span> AttackingEntity <span class="token punctuation">{</span> <span class="token comment">// ⚠️ we simulate that TS supports multiple inheritance</span>
</span><span class="code-line">    <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token keyword">public</span> type<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">,</span> position_x<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">,</span> position_y<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">,</span> <span class="token keyword">private</span> context<span class="token operator">:</span> CanvasRenderingContext2D<span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">super</span><span class="token punctuation">(</span>position_x<span class="token punctuation">,</span> position_y<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">// existing code...</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token function">attack</span><span class="token punctuation">(</span>entity<span class="token operator">:</span> EntityWithHealth<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span>
</span><span class="code-line">
</span><span class="code-line">        entity<span class="token punctuation">.</span><span class="token function">takeDamage</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>attackPower<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">get</span> <span class="token function">attackPower</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token builtin">number</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">return</span> <span class="token number">1</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Ok, now <code>Robot</code> can attack <code>Player</code> - it is represented by <code>EntityWithHealth</code>, because we know that a <code>Player</code> <strong>is a</strong> <code>EntityWithHealth</code>.</p><p>Probably this will pay off when the player will be able to attack the robot too.</p><p>Let&#x27;s define <code>EntityWithHealth</code>:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">abstract</span> <span class="token keyword">class</span> <span class="token class-name">EntityWithHealth</span> <span class="token punctuation">{</span> <span class="token comment">// 👈 new code</span>
</span><span class="code-line">    <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token keyword">private</span> health<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token function">takeDamage</span><span class="token punctuation">(</span>damage<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">this</span><span class="token punctuation">.</span>health <span class="token operator">-=</span> damage<span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>health <span class="token operator">&lt;=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">die</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">class</span> <span class="token class-name">Player</span> <span class="token keyword">extends</span> <span class="token class-name">MovableEntity</span><span class="token punctuation">,</span> RenderableEntity<span class="token punctuation">,</span> EntityWithHealth <span class="token punctuation">{</span> <span class="token comment">// ⚠️ we simulate that TS supports multiple inheritance</span>
</span><span class="code-line">    <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token keyword">public</span> name<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">,</span> position_x<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">,</span> position_y<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">,</span> <span class="token keyword">private</span> context<span class="token operator">:</span> CanvasRenderingContext2D<span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">super</span><span class="token punctuation">(</span>position_x<span class="token punctuation">,</span> position_y<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">super</span><span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 👈 let&#x27;s give the player 100 health points</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Now the player can take damage and die (this will make the game stop).</p><p>Let&#x27;s review the architecture again:</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/domain-driven-design-gaming-and-entity-component-system-inheritance-2.png" class="max-h-[30rem]"/></div><div class="italic mx-24">The Hierarchy of entities and their relationships</div></div><p>Tom is happy with the changes, but he has one more request.</p><div class="flex flex-col "><div class="flex flex-col"><div class="flex justify-center items-center flex-col"><div class="flex max-sm:flex-col justify-between items-center"><img src="https://talesfrom.dev/static/images/business-man.png" class="max-h-[30rem]"/><div class="flex flex-col justify-between text-left"><span>Tom says:</span><span class="my-4 italic"><span class=""><span>Great, the game is getting better!</span></span><span class=""><span>But I have one more request.</span></span><span class=""><span>Some people reported that it would be cool to have more than one robot following the player.</span></span><div class="my-3"><span class="">Maybe we could make </span><span class="mr-2">two types of robots</span><span class="">: slower and faster?</span></div></span></div></div></div></div><div class="flex justify-around mt-10 lg:mx-32"><button class="bg-gray-600 border-gray-100 text-gray-400 p-2 rounded">Just talk</button><button class="bg-green-700 text-white border-2 p-2 rounded">Listening carefully</button></div></div><h3 id="more-robots-more-fun"><a href="#more-robots-more-fun" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>More robots, more fun</h3><p>Who&#x27;s the best software architect in the world?</p><p>As anticipated, more types of robots are coming.</p><p>Great that we did some speculative designing and prepared for that.</p><p>Let&#x27;s do some changes. But remember - we want to keep the code DRY and avoid code duplication.</p><p>We should probably create a base class for all robots.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">abstract</span> <span class="token keyword">class</span> <span class="token class-name">Robot</span> <span class="token keyword">extends</span> <span class="token class-name">MovableEntity</span><span class="token punctuation">,</span> RenderableEntity<span class="token punctuation">,</span> AttackingEntity <span class="token punctuation">{</span> <span class="token comment">// 👈 new code</span>
</span><span class="code-line">    <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token keyword">public</span> type<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">,</span> position_x<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">,</span> position_y<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">,</span> <span class="token keyword">private</span> context<span class="token operator">:</span> CanvasRenderingContext2D<span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">super</span><span class="token punctuation">(</span>position_x<span class="token punctuation">,</span> position_y<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">class</span> <span class="token class-name">SlowRobot</span> <span class="token keyword">extends</span> <span class="token class-name">Robot</span> <span class="token punctuation">{</span> <span class="token comment">// 👈 new code</span>
</span><span class="code-line">    <span class="token function">constructor</span><span class="token punctuation">(</span>type<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">,</span> position_x<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">,</span> position_y<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">,</span> context<span class="token operator">:</span> CanvasRenderingContext2D<span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">super</span><span class="token punctuation">(</span>type<span class="token punctuation">,</span> position_x<span class="token punctuation">,</span> position_y<span class="token punctuation">,</span> context<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">get</span> <span class="token function">movementSpeed</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">return</span> <span class="token number">1</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">get</span> <span class="token function">attackPower</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">return</span> <span class="token number">1</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">class</span> <span class="token class-name">FastRobot</span> <span class="token keyword">extends</span> <span class="token class-name">Robot</span> <span class="token punctuation">{</span> <span class="token comment">// 👈 new code</span>
</span><span class="code-line">    <span class="token function">constructor</span><span class="token punctuation">(</span>type<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">,</span> position_x<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">,</span> position_y<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">,</span> context<span class="token operator">:</span> CanvasRenderingContext2D<span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">super</span><span class="token punctuation">(</span>type<span class="token punctuation">,</span> position_x<span class="token punctuation">,</span> position_y<span class="token punctuation">,</span> context<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">get</span> <span class="token function">movementSpeed</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">return</span> <span class="token number">2</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">get</span> <span class="token function">attackPower</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">return</span> <span class="token number">1</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>We will make <code>Robot</code> an abstract class, so it cannot be instantiated directly.</p><p>Also, let&#x27;s make slower robot a bit stronger in attack power.</p><p>Faster robot will be able to move faster, but it will be weaker in attack power.</p><p>This should make the game more interesting.</p><p>Time to review the architecture again:</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/domain-driven-design-gaming-and-entity-component-system-inheritance-3.png" class="max-h-[30rem]"/></div><div class="italic mx-24">The Hierarchy of entities and their relationships</div></div><p>Let&#x27;s ask Tom about the feedback.</p><h3 id="we-need-more-real-life-behaviors"><a href="#we-need-more-real-life-behaviors" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>We need more real-life behaviors!</h3><div class="flex flex-col "><div class="flex flex-col"><div class="flex justify-center items-center flex-col"><div class="flex max-sm:flex-col justify-between items-center"><img src="https://talesfrom.dev/static/images/business-man.png" class="max-h-[30rem]"/><div class="flex flex-col justify-between text-left"><span>Tom says:</span><span class="my-4 italic"><span class=""><span>Woah, people love our game!</span></span><span class=""><span>But I have one more request.</span></span><div class="my-3"><span class="">Few gamers had a great idea - </span><span class="mr-2">robots</span><span class="">should </span><span class="mr-2">have fuel</span><span class="">that slowly </span><span class="mr-2">depletes as they move</span><span class="">.</span></div><div class="my-3"><span class="">And when they run </span><span class="mr-2">out of fuel</span><span class="">, they should </span><span class="mr-2">stop moving and attacking</span><span class="">.</span></div></span></div></div></div></div><div class="flex justify-around mt-10 lg:mx-32"><button class="bg-gray-600 border-gray-100 text-gray-400 p-2 rounded">Just talk</button><button class="bg-green-700 text-white border-2 p-2 rounded">Listening carefully</button></div></div><p>A-M-A-Z-I-N-G ideas!</p><p>Good that we have well-defined classes which clear responsibilities.</p><p><code>Robot</code> <strong>has a</strong> <code>fuel</code> and it can deplete when moving.</p><p>Let&#x27;s model it accordingly.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">abstract</span> <span class="token keyword">class</span> <span class="token class-name">Robot</span> <span class="token keyword">extends</span> <span class="token class-name">MovableEntity</span><span class="token punctuation">,</span> RenderableEntity<span class="token punctuation">,</span> AttackingEntity <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token keyword">public</span> type<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">,</span> position_x<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">,</span> position_y<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">,</span> <span class="token keyword">private</span> context<span class="token operator">:</span> CanvasRenderingContext2D<span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">super</span><span class="token punctuation">(</span>position_x<span class="token punctuation">,</span> position_y<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">this</span><span class="token punctuation">.</span>fuel <span class="token operator">=</span> <span class="token number">100</span><span class="token punctuation">;</span> <span class="token comment">// 👈 let&#x27;s give the robot 100 fuel points</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    
</span><span class="code-line">    <span class="token keyword">private</span> fuel<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token function">moveLeft</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>fuel <span class="token operator">&gt;</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">super</span><span class="token punctuation">.</span><span class="token function">moveLeft</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token keyword">this</span><span class="token punctuation">.</span>fuel <span class="token operator">-=</span> <span class="token number">1</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    
</span><span class="code-line">    <span class="token function">moveRight</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>fuel <span class="token operator">&gt;</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">super</span><span class="token punctuation">.</span><span class="token function">moveRight</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token keyword">this</span><span class="token punctuation">.</span>fuel <span class="token operator">-=</span> <span class="token number">1</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    
</span><span class="code-line">    <span class="token function">moveUp</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>fuel <span class="token operator">&gt;</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">super</span><span class="token punctuation">.</span><span class="token function">moveUp</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token keyword">this</span><span class="token punctuation">.</span>fuel <span class="token operator">-=</span> <span class="token number">1</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    
</span><span class="code-line">    <span class="token function">moveDown</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>fuel <span class="token operator">&gt;</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">super</span><span class="token punctuation">.</span><span class="token function">moveDown</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token keyword">this</span><span class="token punctuation">.</span>fuel <span class="token operator">-=</span> <span class="token number">1</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token function">attack</span><span class="token punctuation">(</span>entity<span class="token operator">:</span> EntityWithHealth<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>fuel <span class="token operator">&gt;</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">super</span><span class="token punctuation">.</span><span class="token function">attack</span><span class="token punctuation">(</span>entity<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">get</span> <span class="token function">movementSpeed</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>fuel <span class="token operator">&gt;</span> <span class="token number">0</span> <span class="token operator">?</span> <span class="token keyword">this</span><span class="token punctuation">.</span>_movementSpeed <span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">;</span> <span class="token comment">// 👈 no movement when out of fuel</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>I am glad we picked class-oriented design in this game.</p><p>It allows us to easily add new behaviors to the robots without changing the existing code.</p><p>This time the architecture remained the same.</p><p>Truly magnificent design!</p><h3 id="game-is-too-hard-lets-make-it-a-bit-more-entertaining"><a href="#game-is-too-hard-lets-make-it-a-bit-more-entertaining" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Game is too hard, let&#x27;s make it a bit more entertaining</h3><div class="flex flex-col "><div class="flex flex-col"><div class="flex justify-center items-center flex-col"><div class="flex max-sm:flex-col justify-between items-center"><img src="https://talesfrom.dev/static/images/business-man.png" class="max-h-[30rem]"/><div class="flex flex-col justify-between text-left"><span>Tom says:</span><span class="my-4 italic"><span class=""><span>People love our game, but they said that it&#x27;s too hard.</span></span><div class="my-3"><span class="">Let us add a </span><span class="mr-2">power-up</span><span class="">that the player will </span><span class="mr-2">have</span><span class="">, if they pick it from the floor.</span></div><div class="my-3"><span class="">It will </span><span class="mr-2">restore health</span><span class="">or </span><span class="mr-2">perform one-time de-fueling the attacking robot</span><span class="">.</span></div></span></div></div></div></div><div class="flex justify-around mt-10 lg:mx-32"><button class="bg-gray-600 border-gray-100 text-gray-400 p-2 rounded">Just talk</button><button class="bg-green-700 text-white border-2 p-2 rounded">Listening carefully</button></div></div><p>Hm, that&#x27;s very intersting. <code>Robot</code> might also get a power-up that will restore its fuel - some time in the future.</p><p>We need to add a <code>PowerUp</code> class that will need to update health of the player, that&#x27;s easy.</p><p>But when an attacking robot attacks the player, it will get its fuel depleted - where should we put this logic?</p><p>Where should we modify the robot&#x27;s fuel?</p><p>Should it happen in a <code>EntityWithHealth</code> class? No, it should not.</p><p>Then the <code>Robot</code> would know that <code>EntityWithHealth</code> has a <code>PowerUp</code>.</p><p>Maybe we should add a new class <code>EntityWithPowerUp</code>, that <code>EntityWithHealth</code> will inherit from?</p><p>Strange, it was supposed to get easier, not harder, when doing class-oriented design...</p><h3 id="retrospection"><a href="#retrospection" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Retrospection!</h3><p>What do you think about our design, dear Reader?</p><p>Of course, I was exaggerating all the time as people don&#x27;t use inheritance in the real world, right?</p><p>So far so good, one might say.</p><p>Do you see where it all goes?</p><p>Even if it is a simple game, we already created quite a nice entanglement of classes.</p><p>&quot;Damian, all the people in the industry know that inheritance is bad, so why are you writing this blogpost?&quot;, one might say.</p><p>&quot;Favor composition over inheritance, Damian!&quot;, some might urge me, seeing all this mess I&#x27;ve made.</p><p>Let&#x27;s repeat it together:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Favor objects composition over class inheritance</p></div></div></div><p>Yes, it totally makes sense! (I am not an LLM, I am not confirming it just because you thought so, dear Reader!)</p><p>Should we try to use objects composition instead of class inheritance and see how it goes?</p><h3 id="round-2-composition-over-inheritance"><a href="#round-2-composition-over-inheritance" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Round 2: composition over inheritance</h3><p>Let&#x27;s start with the same requirements and progress slowly.</p><p>So initially we have a <code>Player</code> and a <code>Robot</code>.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">interface</span> <span class="token class-name">ICanMove</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token function">moveLeft</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token function">moveRight</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token function">moveUp</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token function">moveDown</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line"><span class="token keyword">class</span> <span class="token class-name">Player</span> <span class="token keyword">implements</span> <span class="token class-name">ICanMove</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token keyword">public</span> name<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">,</span> <span class="token keyword">private</span> position<span class="token operator">:</span> Position<span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">// all the methods from `ICanMove` interface</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">class</span> <span class="token class-name">Robot</span> <span class="token keyword">implements</span> <span class="token class-name">ICanMove</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token keyword">public</span> type<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">,</span> <span class="token keyword">private</span> position<span class="token operator">:</span> Position<span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">// all the methods from `ICanMove` interface</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Pretty easy and straightforward.</p><p>Let&#x27;s add rendering capabilities.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">interface</span> <span class="token class-name">ICanBeRendered</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token function">render</span><span class="token punctuation">(</span>context<span class="token operator">:</span> CanvasRenderingContext2D<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line"><span class="token keyword">class</span> <span class="token class-name">Player</span> <span class="token keyword">implements</span> <span class="token class-name">ICanMove</span><span class="token punctuation">,</span> ICanBeRendered <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token keyword">public</span> name<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">,</span> <span class="token keyword">private</span> position<span class="token operator">:</span> Position<span class="token punctuation">,</span> <span class="token keyword">private</span> canvas<span class="token operator">:</span> CanvasRenderingContext2D<span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">// all the methods from `ICanMove` interface</span>
</span><span class="code-line">    <span class="token comment">// all the methods from `ICanBeRendered` interface</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">class</span> <span class="token class-name">Robot</span> <span class="token keyword">implements</span> <span class="token class-name">ICanMove</span><span class="token punctuation">,</span> ICanBeRendered <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token keyword">public</span> type<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">,</span> <span class="token keyword">private</span> position<span class="token operator">:</span> Position<span class="token punctuation">,</span> <span class="token keyword">private</span> canvas<span class="token operator">:</span> CanvasRenderingContext2D<span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">// all the methods from `ICanMove` interface</span>
</span><span class="code-line">    <span class="token comment">// all the methods from `ICanBeRendered` interface</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>We are getting on speed.</p><p>As long as our entities are not having interactions, it seems fine.</p><p>Of course the game is checking if they are not colliding, but we can handle it in a separate class.</p><p>What was next? Ah, attacking and health.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">interface</span> <span class="token class-name">ITakeDamage</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token function">takeDamage</span><span class="token punctuation">(</span>damage<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">class</span> <span class="token class-name">Player</span> <span class="token keyword">implements</span> <span class="token class-name">ICanMove</span><span class="token punctuation">,</span> ICanBeRendered<span class="token punctuation">,</span> ITakeDamage <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token function">constructor</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token keyword">public</span> name<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token keyword">private</span> position<span class="token operator">:</span> Position<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token keyword">private</span> canvas<span class="token operator">:</span> CanvasRenderingContext2D<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token keyword">private</span> health<span class="token operator">:</span> Health
</span><span class="code-line">    <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">// all the methods from `ICanMove` interface</span>
</span><span class="code-line">    <span class="token comment">// all the methods from `ICanBeRendered` interface</span>
</span><span class="code-line">    <span class="token comment">// all the methods from `ITakeDamage` interface</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">interface</span> <span class="token class-name">IAttack</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token function">attack</span><span class="token punctuation">(</span>entity<span class="token operator">:</span> ITakeDamage<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">class</span> <span class="token class-name">Robot</span> <span class="token keyword">implements</span> <span class="token class-name">ICanMove</span><span class="token punctuation">,</span> ICanBeRendered<span class="token punctuation">,</span> IAttack <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token function">constructor</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token keyword">public</span> type<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token keyword">private</span> position<span class="token operator">:</span> Position<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token keyword">private</span> canvas<span class="token operator">:</span> CanvasRenderingContext2D<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token keyword">private</span> attack<span class="token operator">:</span> Attack
</span><span class="code-line">    <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">// all the methods from `ICanMove` interface</span>
</span><span class="code-line">    <span class="token comment">// all the methods from `ICanBeRendered` interface</span>
</span><span class="code-line">    <span class="token comment">// all the methods from `IAttack` interface</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>We don&#x27;t even need to show the architecture, as it is pretty straightforward - there&#x27;s is a pure composition of interfaces.</p><p>But wait a second - what does <strong>the composition</strong> mean in this case?</p><p>Objects compose other objects and expose capabilities through well-defined <a href="https://talesfrom.dev/blog/the-ambiguity-of-interfaces">interfaces</a>.</p><p>Now adding a new types of robots can be done easily without changing the existing code, as we don&#x27;t play &quot;inheritance game&quot; (pun intended).</p><p>We learned by the hard way that inheritance leads to explosion of complexity, quite soon. (I hope you were able to simulate the pain of inheritance and painful evolution of inheritance structures, dear Reader).</p><p>Should we try to satisfy Tom&#x27;s requirements related to fuel and power-ups?</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">class</span> <span class="token class-name">Robot</span> <span class="token keyword">implements</span> <span class="token class-name">ICanMove</span><span class="token punctuation">,</span> ICanBeRendered<span class="token punctuation">,</span> IAttack <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token function">constructor</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token keyword">public</span> type<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token keyword">private</span> position<span class="token operator">:</span> Position<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token keyword">private</span> canvas<span class="token operator">:</span> CanvasRenderingContext2D<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token keyword">private</span> attack<span class="token operator">:</span> Attack<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token keyword">private</span> fuel<span class="token operator">:</span> Fuel <span class="token comment">// 👈 robot aggregates fuel so that we can deplete it</span>
</span><span class="code-line">    <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">// all the methods from `ICanMove` interface</span>
</span><span class="code-line">    <span class="token comment">// all the methods from `ICanBeRendered` interface</span>
</span><span class="code-line">    <span class="token comment">// all the methods from `IAttack` interface</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token class-name">moveLeft</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>fuel<span class="token punctuation">.</span><span class="token function">isDepleted</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 👈 here we check if there&#x27;s any fuel available</span>
</span><span class="code-line">            <span class="token keyword">return</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">        <span class="token keyword">this</span><span class="token punctuation">.</span>position<span class="token punctuation">.</span><span class="token function">moveLeft</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">this</span><span class="token punctuation">.</span>fuel<span class="token punctuation">.</span><span class="token function">deplete</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 👈 we deplete the fuel when moving</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">// other movement methods...</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Magic - we don&#x27;t need to change any interface, hence we don&#x27;t break the contract!</p><p>It&#x27;s clear that <code>Robot</code> <strong>has a</strong> <code>Fuel</code>, and we model it accordingly.</p><p>The power of composition, yay!</p><p>Now we can add a <code>PowerUp</code> concept that will be able to restore health of the player or de-fuel of the attacking robot, when player has this power-up.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">interface</span> <span class="token class-name">IHaveFuelDepletingPowerUp</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token function">usePowerUp</span><span class="token punctuation">(</span><span class="token function function-variable">callback</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token keyword">void</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span><span class="token punctuation">;</span> <span class="token comment">// 👈 we use a callback to perform the action</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line"><span class="token keyword">class</span> <span class="token class-name">Player</span> <span class="token keyword">implements</span> <span class="token class-name">ICanMove</span><span class="token punctuation">,</span> ICanBeRendered<span class="token punctuation">,</span> ITakeDamage<span class="token punctuation">,</span> IHaveFuelDepletingPowerUp <span class="token punctuation">{</span> <span class="token comment">// 👈 player aggregates power-ups</span>
</span><span class="code-line">    <span class="token function">constructor</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token keyword">public</span> name<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token keyword">private</span> position<span class="token operator">:</span> Position<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token keyword">private</span> canvas<span class="token operator">:</span> CanvasRenderingContext2D<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token keyword">private</span> health<span class="token operator">:</span> Health<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token keyword">private</span> powerUp<span class="token operator">:</span> PowerUp <span class="token comment">// 👈 player aggregates power-up</span>
</span><span class="code-line">    <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">// all the methods from `ICanMove` interface</span>
</span><span class="code-line">    <span class="token comment">// all the methods from `ICanBeRendered` interface</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token class-name">usePowerUp</span><span class="token punctuation">(</span><span class="token function function-variable">callback</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token keyword">void</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>fuelDepletingPowerUp<span class="token punctuation">.</span><span class="token function">isAvailable</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">this</span><span class="token punctuation">.</span>fuelDepletingPowerUp<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>callback<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 👈</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line"><span class="token keyword">class</span> <span class="token class-name">Robot</span> <span class="token keyword">implements</span> <span class="token class-name">ICanMove</span><span class="token punctuation">,</span> ICanBeRendered<span class="token punctuation">,</span> IAttack <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token function">constructor</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token keyword">public</span> type<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token keyword">private</span> position<span class="token operator">:</span> Position<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token keyword">private</span> canvas<span class="token operator">:</span> CanvasRenderingContext2D<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token keyword">private</span> attack<span class="token operator">:</span> Attack<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token keyword">private</span> fuel<span class="token operator">:</span> Fuel
</span><span class="code-line">    <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">// all the methods from `ICanMove` interface</span>
</span><span class="code-line">    <span class="token comment">// all the methods from `ICanBeRendered` interface</span>
</span><span class="code-line">    <span class="token comment">// all the methods from `IAttack` interface</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token class-name">attack</span><span class="token punctuation">(</span>entity<span class="token operator">:</span> ITakeDamage <span class="token operator">&amp;</span> IHaveFuelDepletingPowerUp<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span> <span class="token comment">// ⚠️ we needed to change the contract!</span>
</span><span class="code-line">        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>fuel<span class="token punctuation">.</span><span class="token function">isDepleted</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">return</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">        entity<span class="token punctuation">.</span><span class="token function">usePowerUp</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token keyword">this</span><span class="token punctuation">.</span>fuel<span class="token punctuation">.</span><span class="token function">deplete</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 👈 we use the power-up if available</span>
</span><span class="code-line">        entity<span class="token punctuation">.</span><span class="token function">takeDamage</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>attack<span class="token punctuation">.</span>power<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">this</span><span class="token punctuation">.</span>fuel<span class="token punctuation">.</span><span class="token function">deplete</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 👈 we deplete the fuel when attacking</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>It wasn&#x27;t that difficult, was it?</p><p>Unfortunately, we broke the contract of <code>IAttack</code> interface, so we would need to update all places where this interface is used.</p><p>But let&#x27;s make a side-quest and think about the future requirements - what if there will be an obstacle that could be destroyed by the robot?</p><p>In a way, <code>Robot</code> would be able to &quot;attack&quot; the obstacle, and the obstacle would be able to &quot;take damage&quot;.</p><p>Then this method of <code>IAttack</code>:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token comment">// we are using union (&amp;) of two interfaces so this entity provides both capabilities</span>
</span><span class="code-line"><span class="token function">attack</span><span class="token punctuation">(</span>entity<span class="token operator">:</span> ITakeDamage <span class="token operator">&amp;</span> IHaveFuelDepletingPowerUp<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span><span class="token punctuation">;</span>
</span></code></pre></div></div><p>would be a perfect fit for the <code>Obstacle</code> class, wouldn&#x27;t it?</p><p>Of course, obstacles do not have power-ups, but it&#x27;s not a problem as we could use <a href="https://en.wikipedia.org/wiki/Null_object_pattern">Null Object pattern</a>:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">class</span> <span class="token class-name">NullPowerUp</span> <span class="token keyword">implements</span> <span class="token class-name">IHaveFuelDepletingPowerUp</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token function">usePowerUp</span><span class="token punctuation">(</span><span class="token function function-variable">callback</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token keyword">void</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">// do nothing</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Obstacle would implement this interface and use <code>NullPowerUp</code> as a power-up, so it would not break the contract.</p><p>But imagine such a requirement - a player is able to cast a spell to make objects (not in the software sense, but &quot;obstacle&quot; sense) indestructible for a while.</p><p>We could compose it further and make an <code>Obstacle</code> object use more <code>PowerUp</code>s that would allow it to become indestructible.</p><h3 id="retrospection-1"><a href="#retrospection-1" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Retrospection!</h3><p>What do you think about our design, dear Reader?</p><p>Of course, we are playing with the design and mental models (ways of thinking) here, so there might be better ways to model this little reality.</p><p>We could compare it to class-oriented design that we used earlier.</p><p>In the inheritance-based round, we had a huge and continuously growing hierarchy of classes.</p><p>Locating responsibilities, navigating through the maze of intertwined classes, understanding what mutates what - horror.</p><p>In the objects-composition round, we have a flat structure of interfaces that are composed together to model entities.</p><p>Capabilities provided by each entitiy are clearly defined and exposed.</p><p>Interactions between entities happen but because we have keeping the structure as flat as possible, it&#x27;s easier to follow up on individual entities.</p><p>Also, &quot;the power of composition&quot; allows us to easily add new behaviors without changing the existing code.</p><p>In case of extending the entities without modifying them directly, we could use <a href="https://en.wikipedia.org/wiki/Decorator_pattern">Decorator pattern</a> to add new behaviors, switch behaviors in runtime using <a href="https://en.wikipedia.org/wiki/Strategy_pattern">Strategy pattern</a>, and so on.</p><p>But let&#x27;s come back to the presentation given by <a href="https://x.com/cmuratori">Casey Muratori</a>.</p><p><a href="https://x.com/cmuratori">Casey</a> in his presentation brought very important concept: <strong>compile-time hierarchies</strong>.</p><p>Many people immediately associate hierarchies with inheritance, which of course is true - we literally saw them growing in the inheritance-based round.</p><p>Casey did enormous effort to do the research of the origins of making &quot;the mistake&quot; - which isn&#x27;t the object-orientation itself, but creating those compile-time hierarchies.</p><p><a href="https://youtu.be/wo84LFzx5nI?si=-UbSLfoJIdArQ1sK&amp;t=398">One</a> (it is a quote) of his slides states the following:</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">Casey&#x27;s slide</div><div class="pb-2 px-3"><div class="break-words"><p>A compile-time hierarchy that matches the domain model.</p></div></div></div><p>In the object-composition round this is exactly what we are doing - we are creating &quot;a well-defined domain model&quot; - where <code>Player</code>, <code>Robot</code> and other concepts are clearly expressed.</p><p>We even can talk with Tom and exchange ideas without &quot;solutioning&quot; that &quot;Player is a Movable entity&quot;, for example.</p><p>The compile-time structure is pretty flat (in comparison to inheritance-based design), but the domain model classes grow in size as we add more capabilities to them.</p><p>Methods are getting longer, more ifs are happening here and there.</p><p>We basically created a &quot;God Class&quot; - a compile-time, absolute-based, reality-chasing models.</p><p>We tried to model the reality and express it in the code, but whoever tries to capture the reality in compile-time, will fail in re-design time and in the runtime later.</p><p>One, big lesson from the presentation, that one can take away is <strong>boundaries (encapsulation) are one of the most important aspects when designing software</strong></p><p>We should train ourselves in looking for boundaries reflecting the domain, we are trying to build software solutions for, but not materialize them as compile-time hierarchies.</p><p>Should we try to use Entity Component System (ECS) and try to model the domain of this game?</p><h3 id="round-3-entity-component-system-ecs"><a href="#round-3-entity-component-system-ecs" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Round 3: Entity Component System (ECS)</h3><p>Let&#x27;s quickly recap what Entity Component System (ECS) is.</p><p>ECS is a software architectural pattern that is used to model complex systems, especially in game development.</p><p><em>Entities</em> are concepts that are represented in the world: like <code>Player</code>, <code>Robot</code>, <code>Obstacle</code>, etc.</p><p>They are <strong>just</strong> identifiers.</p><p>Nothing more, nothing less.</p><p>Each of the concepts have related <em>components</em> - <code>Position</code>, <code>Speed</code>, <code>Health</code>, <code>Fuel</code>, <code>Attack</code>, etc.</p><p>These <em>components</em> are <strong>just</strong> data that represent a very specific perspective of the entity&#x27;s state.</p><p>Finally, <em>systems</em> are responsible for transforming relevant components of the entities, based on the specific use case, through time.</p><p>Let&#x27;s take a <em>system</em> representing <code>Movement</code> that will take <em>components</em>: <code>Position</code> and <code>Speed</code>, to update the entity&#x27;s location based on its velocity.</p><p>We could have a <em>system</em> representing <code>MechanicalMovement</code> that will take <em>components</em>: <code>Position</code>, <code>Speed</code>, and <code>Fuel</code>, to update the entity&#x27;s location based on its velocity, adjusting fuel consumption based on the speed and distance traveled.</p><p>We can compose <em>components</em> in <em>systems</em> to create complex behaviors.</p><p>This means we are not creating compile-time hierarchies, nor <strong>the domain model</strong> which would play a weak representation of the reality.</p><p>Previously, we didn&#x27;t mention it directly, but one of the &quot;assumed&quot; traits that should be given by class-oriented design was <strong>encapsulation</strong>.</p><p>Of course, we still need to modify code, adjust <em>components</em>, introduce <em>systems</em> (and evolve them), but boundaries are established differently.</p><p>But they are there.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/domain-driven-design-gaming-and-entity-component-system-casey-encapsulation-boundaries.png" class="max-h-[30rem]"/></div><div class="italic mx-24">Screenshot from Casey&#x27;s <a href="https://youtu.be/wo84LFzx5nI?si=mg3YlhiJwns2jsAG&amp;t=305">slide</a></div></div><p>The red lines are &quot;encapsulation boundaries&quot;. They are organized around <em>components</em>, not around <em>entities</em>.</p><p>And here&#x27;s Casey&#x27;s comment to the slide shown above:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>&quot;<strong>Encapsulation boundaries are really what we care about in software design</strong>. What we care about is where we make it difficult to access things and where we make it easy, right?&quot;</p></div></div></div><p>&quot;What you hide, you can change&quot;, and even though <em>components</em> are pure data structures in game development, ECS architecture allows composing requirements at runtime.</p><p>This flexibility is crucial for adapting game mechanics and behaviors dynamically.</p><p>Imagine that we finally want to add attacking capabilities to the player.</p><p>We would need to wire up <code>Player</code> <em>entity</em> (an identifier) with <code>Attack</code> <em>component</em> and existing <em>system</em> should be able to handle that seamlessly (or at least without big hiccups).</p><p>Ok, let&#x27;s jump to DDD world for a while.</p><h3 id="domain-driven-design-ddd-and-entity-component-system-ecs"><a href="#domain-driven-design-ddd-and-entity-component-system-ecs" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Domain-Driven Design (DDD) and Entity Component System (ECS)</h3><p>I hear you dear Reader - &quot;Damian, why the hell are you talking about DDD and ECS in the same tale?&quot;.</p><p>And that is a very good question!</p><p>In DDD we care a lot about the domain model, which tries to represent the areas of the business we are building software for.</p><p>Ubiquitous language, bounded contexts, domains, subdomains and so on - everything about tackling the complexity and managing it through time.</p><p>One can often see tutorials showing how to &quot;model a domain&quot; with so-called &quot;tactical patterns&quot; like aggregates, entities, value objects, and so on.</p><p>And we end up with concepts of &quot;Users&quot;, &quot;Products&quot;, &quot;Tours&quot;, &quot;Posts&quot;, and so on.</p><p>Should we take an example, dear Reader?</p><h3 id="are-you-interested-in-a-tour"><a href="#are-you-interested-in-a-tour" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Are you interested in a tour?</h3><p>You remember Tom, right?</p><p>He again approached us with a new idea.</p><div class="flex flex-col "><div class="flex flex-col"><div class="flex justify-center items-center flex-col"><div class="flex max-sm:flex-col justify-between items-center"><img src="https://talesfrom.dev/static/images/business-man.png" class="max-h-[30rem]"/><div class="flex flex-col justify-between text-left"><span>Tom says:</span><span class="my-4 italic"><span class=""><span>Hi, I have a new idea for a business. I was told by the team, that took over the game after you guys, that it&#x27;s a maintenance hell, but at least I earned tons of money.</span></span><div class="my-3"><span class="">I want to create a platform where </span><span class="mr-2">participants</span><span class="">can </span><span class="mr-2">book tours</span><span class="">and have </span><span class="mr-2">engaging, guided experiences</span><span class="">.</span></div><div class="my-3"><span class="">Each </span><span class="mr-2">tour has details like name, description, base price, start date, and so on.</span><span class="">. </span><span class="mr-2">Participants</span><span class="">can </span><span class="mr-2">reserve seats</span><span class="">.</span></div><div class="my-3"><span class="">What is a true differentiator is the unique experience we offer to our participants - they will never get lost as </span><span class="mr-2">we provide personalized guidance and support throughout their journey.</span><span class="">.</span></div><div class="my-3"><span class="">Each </span><span class="mr-2">participant will have a unique session in our mobile application</span><span class="">so that </span><span class="mr-2">they can easily track their itinerary and receive real-time updates.</span></div><div class="my-3"><span class="">They also </span><span class="mr-2">will be guided by an experienced guide all the time, throughout the tour.</span></div><span class=""><span>Can you help me with that?</span></span></span></div></div></div></div><div class="flex justify-around mt-10 lg:mx-32"><button class="bg-gray-600 border-gray-100 text-gray-400 p-2 rounded">Just talk</button><button class="bg-green-700 text-white border-2 p-2 rounded">Listening carefully</button></div></div><p>It is the first time we hear about this idea, but it sounds like a great business opportunity.</p><p>We should run <a href="https://www.eventstorming.com/">Event Storming</a> session with Tom to understand the domain better, but let&#x27;s try to model the domain with DDD approach and quickly verify our understanding with Tom.</p><p>Ok, let&#x27;s recap: a <code>Tour</code> <strong>has</strong> a <code>TourName</code>, <code>TourDescription</code>, <code>BasePrice</code>, <code>TourStartDate</code>, and <code>AvailableSeats</code>.</p><p>Also, a <code>Tour</code> <strong>has</strong> <code>Participants</code>, and each <code>Participant</code> <strong>has</strong> a <code>Session</code>.</p><p>And not forget that a <code>Tour</code> <strong>has</strong> a <code>Guide</code>. Probably <code>Guide</code> <strong>has</strong> <code>Name</code>, <code>Experience</code>, and <code>Rating</code>.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">class</span> <span class="token class-name">Tour</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token function">constructor</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token keyword">private</span> name<span class="token operator">:</span> TourName<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token keyword">private</span> description<span class="token operator">:</span> TourDescription<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token keyword">private</span> basePrice<span class="token operator">:</span> BasePrice<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token keyword">private</span> startDate<span class="token operator">:</span> TourStartDate<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token keyword">private</span> seats<span class="token operator">:</span> AvailableSeats<span class="token punctuation">,</span> 
</span><span class="code-line">        <span class="token keyword">private</span> participants<span class="token operator">:</span> Participants
</span><span class="code-line">    <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token function">reserveSeats</span><span class="token punctuation">(</span>reservation<span class="token operator">:</span> SeatReservation<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span>reservation<span class="token punctuation">.</span>isPaid<span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">            DomainError<span class="token punctuation">.</span><span class="token function">raise</span><span class="token punctuation">(</span><span class="token string">&quot;Reservation is not paid&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">        <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>seats<span class="token punctuation">.</span><span class="token function">canReserve</span><span class="token punctuation">(</span>reservation<span class="token punctuation">.</span>participants<span class="token punctuation">.</span>length<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">this</span><span class="token punctuation">.</span>seats<span class="token punctuation">.</span><span class="token function">reserve</span><span class="token punctuation">(</span>reservation<span class="token punctuation">.</span>participants<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>toSeat<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token keyword">this</span><span class="token punctuation">.</span>participants<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>reservation<span class="token punctuation">.</span>participants<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
</span><span class="code-line">            DomainError<span class="token punctuation">.</span><span class="token function">raise</span><span class="token punctuation">(</span><span class="token string">&quot;Not enough available seats&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token function">getAvailableSeats</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> AvailableSeats <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>seats<span class="token punctuation">.</span><span class="token function">toAvailableSeats</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token function">allocateGuide</span><span class="token punctuation">(</span>guide<span class="token operator">:</span> Guide<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">this</span><span class="token punctuation">.</span>guide <span class="token operator">=</span> guide<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token function">getGuide</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> Guide <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>guide<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token function">updateName</span><span class="token punctuation">(</span>newName<span class="token operator">:</span> TourName<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">this</span><span class="token punctuation">.</span>name <span class="token operator">=</span> newName<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token function">updateDescription</span><span class="token punctuation">(</span>newDescription<span class="token operator">:</span> TourDescription<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">this</span><span class="token punctuation">.</span>description <span class="token operator">=</span> newDescription<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">// and more, and more...</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Ok, initial round of modeling is done. In DDD it is very, very important to collaborate with domain experts, so let&#x27;s ask Tom about our understanding.</p><p>As you see dear Reader, we used Value Objects and Entities to express important concepts of the domain.</p><p>(here is the moment when we show the code to Tom)</p><div class="flex flex-col "><div class="flex flex-col"><div class="flex justify-center items-center flex-col"><div class="flex max-sm:flex-col justify-between items-center"><img src="https://talesfrom.dev/static/images/business-man.png" class="max-h-[30rem]"/><div class="flex flex-col justify-between text-left"><span>Tom says:</span><span class="my-4 italic"><span class=""><span>Wow, you are so fast!</span></span><span class=""><span>It looks great, this time you don&#x27;t talk to me about inheritance, interfaces and composition.</span></span><div class="my-3"><span class="">Please remember that when </span><span class="mr-2">a tour is started</span><span class="">we need to ensure that each </span><span class="mr-2">participant&#x27;s session is also started</span><span class="">and then each </span><span class="mr-2">participant&#x27;s position is going to be tracked</span><span class="">.</span></div><div class="my-3"><span class="">Also, </span><span class="mr-2">the guide has a calendar</span><span class="">so we need to check </span><span class="mr-2">the availability of the guide&#x27;s schedule.</span><span class="">.</span></div></span></div></div></div></div><div class="flex justify-around mt-10 lg:mx-32"><button class="bg-gray-600 border-gray-100 text-gray-400 p-2 rounded">Just talk</button><button class="bg-green-700 text-white border-2 p-2 rounded">Listening carefully</button></div></div><p>Wow, great that we had this conversation.</p><p>We forgot to add <code>Status</code> to <code>Tour</code> class - how the hell could we forget about it?!</p><p>Let&#x27;s adjust the code accordingly.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">class</span> <span class="token class-name">Tour</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// existing code...</span>
</span><span class="code-line">    <span class="token keyword">private</span> status<span class="token operator">:</span> TourStatus <span class="token operator">=</span> TourStatus<span class="token punctuation">.</span>Planned<span class="token punctuation">;</span> <span class="token comment">// 👈 initial status for a tour.</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>status <span class="token operator">!==</span> TourStatus<span class="token punctuation">.</span>Planned<span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">            DomainError<span class="token punctuation">.</span><span class="token function">raise</span><span class="token punctuation">(</span><span class="token string">&quot;Tour can only be started when it is planned&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">        <span class="token keyword">this</span><span class="token punctuation">.</span>status <span class="token operator">=</span> TourStatus<span class="token punctuation">.</span>InProgress<span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">this</span><span class="token punctuation">.</span>participants<span class="token punctuation">.</span><span class="token function">startSessions</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">this</span><span class="token punctuation">.</span>guide<span class="token punctuation">.</span><span class="token function">startSession</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token function">end</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>status <span class="token operator">!==</span> TourStatus<span class="token punctuation">.</span>InProgress<span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">            DomainError<span class="token punctuation">.</span><span class="token function">raise</span><span class="token punctuation">(</span><span class="token string">&quot;Tour can only be ended when it is in progress&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">        <span class="token keyword">this</span><span class="token punctuation">.</span>status <span class="token operator">=</span> TourStatus<span class="token punctuation">.</span>Completed<span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">this</span><span class="token punctuation">.</span>participants<span class="token punctuation">.</span><span class="token function">endSessions</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">this</span><span class="token punctuation">.</span>guide<span class="token punctuation">.</span><span class="token function">endSession</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token function">getStatus</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> TourStatus <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>status<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token function">allocateGuide</span><span class="token punctuation">(</span>guide<span class="token operator">:</span> Guide<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span> <span class="token comment">// 👈 we need to check if the guide is available</span>
</span><span class="code-line">        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>status <span class="token operator">!==</span> TourStatus<span class="token punctuation">.</span>Planned<span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">            DomainError<span class="token punctuation">.</span><span class="token function">raise</span><span class="token punctuation">(</span><span class="token string">&quot;Tour can only have a guide allocated when it is planned&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">        <span class="token keyword">if</span><span class="token punctuation">(</span>guide<span class="token punctuation">.</span><span class="token function">isAvailable</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>startDate<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">this</span><span class="token punctuation">.</span>guide <span class="token operator">=</span> guide<span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
</span><span class="code-line">            DomainError<span class="token punctuation">.</span><span class="token function">raise</span><span class="token punctuation">(</span><span class="token string">&quot;Guide is not available for the selected date&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">        <span class="token keyword">this</span><span class="token punctuation">.</span>guide <span class="token operator">=</span> guide<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Phew, that&#x27;s better.</p><p>What a nice domain model we have here.</p><p>It is clear and expressive, even Tom was able to read it.</p><p>This must be the holy grail of Domain-Driven Design!</p><h3 id="compile-time-domain-model-disaster"><a href="#compile-time-domain-model-disaster" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Compile-time domain model disaster</h3><p>Let&#x27;s take a while and admire domain modeling we just saw.</p><p>So DDD.</p><p>We again fall into the compile-time, absolute-based, and reality-chasing trap.</p><p>We hear <code>Tour</code> and we immediately think about <code>Tour</code> class.</p><p>Even though it nicely expresses the language of the domain, it is still a compile-time hierarchy.</p><p>Congratulations, we just established a &quot;God Class&quot;.</p><p>Such Noun-based, reality-chasing model attracts so many responsibilities, so many use cases, that it will soon become a nightmare to maintain (and evolve).</p><p>Let&#x27;s <a href="https://talesfrom.dev/blog/slow-down">slow down</a>, take a deep breath and think about various <em>components</em> of the <code>Tour</code> concept.</p><p>What are important <em>systems</em>, or use cases in this particular business?</p><p>Tour booking?</p><p>Tour navigating?</p><p>Tour name updating?</p><p>Allocating guide to a tour?</p><p>In each of those scenarios, we will only need some specific aspects of the tour.</p><p>We could use one of many heuristics for &quot;finding components&quot; and establishing good boundaries - like <a href="https://particular.net/blog/antirequirements">anti-requirements</a>.</p><p>Let&#x27;s ask ourselves a question: how probable is it that we would need to check the Tour&#x27;s name while allocating a guide?</p><p>Not very probable, right?</p><p>What about checking if seats are available while we are navigating the tour and we are tracking each participant&#x27;s position?</p><p>Not very probable either.</p><p>While exploring the results of applying <a href="https://particular.net/blog/antirequirements">anti-requirements</a> heuristic, we found out that when someone would try to allocate guide to a Tour and change the name of the Tour at the same time, then one of the operations will probably fail - or at least introduce an inconsistency in our system.</p><p>It seems that we can segregate some <em>components</em> that might be useful only in some specific use cases:</p><ul><li><code>TourDetails</code></li><li><code>SeatsAvailability</code></li><li><code>TourNavigationSessions</code></li><li><code>GuidesAvailability</code></li><li>etc.</li></ul><p>(note dear Reader it is just a suggestion, not a final list of components).</p><p>Imagine that there&#x27;s a <em>system</em> (something like &quot;a business process&quot;) that will be triggered when all reservations are paid.</p><p>Let&#x27;s call it <code>TourNavigationPreparation</code> <em>system</em> - we could also call it a <code>TourNavigationPreparationProcess</code>, if you wish, dear Reader.</p><p>Such <em>system</em> will need to:</p><ul><li>try allocating <code>Guide</code> <em>component</em> to the <code>Tour</code> <em>component</em></li><li>prepare <code>TourNavigationSessions</code> <em>components</em> for each <code>Participant</code> <em>component</em> and for the <code>Guide</code> <em>component</em></li><li>prepare <code>TourNavigating</code> <em>component</em> ensuring the list of <em>Checkpoints</em> <em>components</em> is available</li></ul><p>This is just <strong>one</strong> of many <em>systems</em> that could be used to prepare a tour for navigation.</p><p>Can you tell where does it lead us, dear Reader?</p><h3 id="where-is-tour-entity"><a href="#where-is-tour-entity" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Where is &quot;Tour&quot; entity?</h3><p><code>TourNavigationPreparation</code> <em>system</em> is a good example of a business process that might be quite complex.</p><p>It organizes various <em>components</em> (or capabilities, if you wish) into a meaningful sequence of steps.</p><p>Imagine if a <code>PlannedTour</code> required transporting participants to the starting point of the tour - in another city.</p><p>This means that we need to add a <code>ParticipantsTransport</code> <em>component</em> that will be used in the <code>TourNavigationPreparation</code> <em>system</em>.</p><p>Such step is relevant only in this particular use case, in a very specific moment of time.</p><p>&quot;Ok, but where is our Tour, Damian?&quot;, one might ask.</p><p>This is really funny.</p><p>Everywhere and nowhere.</p><p>There is no central place where <code>Tour</code> can be found.</p><p>It is composed in &quot;the runtime&quot;, throughout each process.</p><p>What is the most important is its identifier - <code>TourId</code>.</p><p>So in a way, there is <strong>no</strong> domain model.</p><p>No single one.</p><p>But there are various <strong>domain models</strong> - a model of seat availability, a model of tour details, a model of location tracking, a model of guide availability, and so on.</p><p>Alone, they might not be that powerful, until you compose them (their capabilities) and &quot;a new capability will emerge&quot; - <em>a system</em>.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>A system is greater than a sum of it components.</p></div></div></div><h3 id="did-you-say-encapsulation"><a href="#did-you-say-encapsulation" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Did you say &quot;encapsulation&quot;?</h3><p>Game development is unique domain as the performance is one of the biggest concerns one must take care into account, from day zero (at least that&#x27;s how I imagine it).</p><p><em>Components</em> in ECS are pure data structures, striving to be stored in a specific memory layout, so that when manipulated by <em>systems</em> it&#x27;s super efficient to bulk update data inside of the <em>component</em> boundary.</p><p>And that is one of possible reasons why in gamedev one wants to &quot;encapsulate&quot; <em>components</em> in such a way.</p><p>But because they are pure data structures, it&#x27;s a &quot;different encapsualtion&quot; than one might be typically think of - each <em>system</em> can manipulate <em>components</em> to achieve its designed purpose (for example: changing position <em>component</em> of a mechanical entities and adjust fuel <em>component</em>).</p><p>In object-oriented design (and not only), one might think of the encapsulation as a way of hiding the implementation details (e.g. how we calculate taxes, what data structures are used, etc.) so that it&#x27;s easier to deal with the changes later.</p><p>Let&#x27;s hide &quot;implementation details&quot; of previously shown slide from Casey&#x27;s presentation and put them inside of bubbles:</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/domain-driven-design-gaming-and-entity-component-system-strategic-ddd-1.png" class="max-h-[30rem]"/></div><div class="italic mx-24">Different way of visualizing Casey&#x27;s <a href="https://youtu.be/wo84LFzx5nI?si=mg3YlhiJwns2jsAG&amp;t=305">slide</a></div></div><p>Finally, arrows, boxes and circles - serious architecture diagram!</p><p>Let&#x27;s add some exemplary <em>systems</em>:</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/domain-driven-design-gaming-and-entity-component-system-strategic-ddd-2.png" class="max-h-[30rem]"/></div><div class="italic mx-24">Different way of visualizing Casey&#x27;s <a href="https://youtu.be/wo84LFzx5nI?si=mg3YlhiJwns2jsAG&amp;t=305">slide</a></div></div><p>Let&#x27;s imagine that we want to introduce some kind of &quot;special events&quot; that will change the gameplay in runtime.</p><p>Something like &quot;a day of tireless mechs&quot; - you get the point dear Reader.</p><p>In such &quot;a day&quot;, the fuel <em>component</em> is not depleting when any action is taken by any entities <em>having</em> a fuel <em>component</em>.</p><p>Where should such responsibility be assigned?</p><p>Ok, now it&#x27;s time to a blasphemy - I think we are missing a concept.</p><p>We could name it as &quot;a policy system&quot; - kind of a &quot;higher level&quot; <em>system</em> that is able to fine-tune &quot;lower level&quot; <em>systems</em>.</p><p>For brevity, let&#x27;s call such systems <em>policies</em>.</p><p>So &quot;a day of tireless mechs&quot; is a <em>policy</em>, let&#x27;s express it within a particular boundary - &quot;Game events&quot; <em>policy</em>:</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/domain-driven-design-gaming-and-entity-component-system-strategic-ddd-3.png" class="max-h-[30rem]"/></div><div class="italic mx-24">A diagram extended with <em>policies</em> - a higher level, blasphemous new type of <em>system</em></div></div><p>Of course, take it with a pinch of salt, dear Reader.</p><p>We are playing with ideas here, bring metaphors and try looking for patterns, analogies and synergies.</p><h3 id="did-anyone-say-levels"><a href="#did-anyone-say-levels" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Did anyone say &quot;levels&quot;?</h3><p>I am not sure about you, dear Reader, but it seems to me that we have some kind of a hierarchy, don&#x27;t you think?</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/domain-driven-design-gaming-and-entity-component-system-strategic-ddd-4.png" class="max-h-[30rem]"/></div><div class="italic mx-24">Different levels in our architecture</div></div><p>It looks familiar.</p><p>Of course, <em>components</em> in gamedev are pure data structures, <em>systems</em> are processing units that manipulate these components to achieve desired behaviors and outcomes.</p><p><em>Policies</em> we have just introduced (as a concept), but even if they are not existing exactly in such a form, conceptually there might be something that &quot;plays&quot; the role of a <em>fine-turning</em> actor.</p><p>How would that look in Domain-Driven Design?</p><p>Thankfully, there&#x27;s a concept called <a href="https://herbertograca.com/2016/06/13/ddd-16-large-scale-structure/">&quot;Large-scale structure&quot;</a>.</p><p>The referred blog post presents very interesting diagram:</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://herbertograca.com/wp-content/uploads/2016/06/domain_layers.png" class="max-h-[30rem]"/></div><div class="italic mx-24">A drawing presenting the details of &quot;Large-scale structure&quot;, <a href="https://herbertograca.com/2016/06/13/ddd-16-large-scale-structure/">source</a></div></div><p>As we can see, there are various &quot;responsibility layers&quot; with stated change rate or &quot;volatility&quot;. Each layer expresses certain &quot;knowledge boundary&quot; that describes how another &quot;knowledge boundary&quot; should behave.</p><p>One could say that this structure represents a hierarchy of &quot;knowledge boundaries&quot; that are organized around the domain.</p><p><em>Operations</em> level tells <em>Potentials</em> what should be achieved, in what sequence.</p><p><em>Policies</em> level tells <em>Operations</em> what are the rules that should be used, and so on, and so on.</p><p>Can you see an analogy to <em>components</em>, <em>systems</em> and <em>policies</em> in the context of Entity Component System (ECS)?</p><p>Of course, application of ECS is slightly different - as we described earlier with analyzing the meaning of &quot;encapsulation&quot; in the context of ECS.</p><p>But in principle, we want to organize the knowledge (and responsibilities), and establish boundaries differently, to achieve certain <a href="https://talesfrom.dev/blog/the-ambiguity-of-software-architecture">goals</a>.</p><h3 id="tourism-and-knowledge-levels"><a href="#tourism-and-knowledge-levels" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Tourism and knowledge levels</h3><p>Now let&#x27;s put gamedev aside and think of applying the explored knowledge (pun intended) to <code>TourNavigationPreparation</code> process, from <a href="https://talesfrom.dev/blog/the-ambiguity-the-curse-and-the-fallacy-of-domain-model#compile-time-domain-model-disaster">Compile-time domain model disaster</a> section.</p><p>As a recap, here is what such a process is intended to do:</p><ul><li>try allocating <code>Guide</code> <em>component</em> to the <code>Tour</code> <em>component</em></li><li>prepare <code>TourNavigationSessions</code> <em>components</em> for each <code>Participant</code> <em>component</em> and for the <code>Guide</code> <em>component</em></li><li>prepare <code>TourNavigating</code> <em>component</em> ensuring the list of <em>Checkpoints</em> <em>components</em> is available</li></ul><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/domain-driven-design-gaming-and-entity-component-system-strategic-ddd-5.png" class="max-h-[30rem]"/></div><div class="italic mx-24">One of many way of organizing &quot;Tour Navigation Preparation&quot; processs</div></div><p>As we are not in gamedev anymore, we want to each <em>component</em> protect its invariants (think: rules) and do not let their state be corrupted (think: inconsistent).</p><p>This means that whenever we try to &quot;allocate a <code>Guide</code> to a <code>Tour</code>&quot;, when there&#x27;s a <code>Guide</code> that is not available, it won&#x27;t let us to do that.</p><p>Such rules will be placed within a boundary of each <em>component</em> and will be enforced by the <em>component</em> itself (remember: we are not in gamedev realm anymore, we are playing with analogies here.)</p><p>One could say that we encapsulate those rules and information required to satisfy those rules inside a boundary of a specific <em>component</em>.</p><p>What if there will be a special fine-tuning required? We would probably introduce a &quot;TourNavigationPreparationPolicy&quot; <em>policy</em> that would be able to adjust the process, based on some conditions.</p><p>Also, it&#x27;s worth noting that <em>components</em> presented in the diagram should strive to be used in a specific processes or use cases.</p><p>&quot;Damian, what about coupling?&quot;, you might ask, dear Reader.</p><p>And this is a very good question, indeed!</p><h3 id="coupling-boundaries-and-encapsulation"><a href="#coupling-boundaries-and-encapsulation" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Coupling, boundaries and encapsulation</h3><p>Complexity does not disappear. (due to interactions between or elements/components - if you&#x27;re interested about reading more, please check <a href="https://talesfrom.dev/blog/composing-a-pie">Composing a PIE</a>)</p><p>We are mindful engineers and we know that &quot;loose coupling&quot; is just a buzzword, as coupling does not disappear, but moves and changes places.</p><p>As we explored &quot;Large-scale structure&quot;, some knowledge levels are more volatile, and some are more stable.</p><p>It might be that our business people want to experiment with different ways of organizing a tour navigation preparation process - based on the fact that we&#x27;re dealing with corporate or individual customers, if there are any special events (free meal during the day, etc.).</p><p>This means that this &quot;knowledge level&quot; might be a target of more frequent changes.</p><p>What about &quot;tracking location&quot;, &quot;guide availability&quot;, &quot;participant details&quot;, &quot;seats availability&quot;, and so on?</p><p>Of course it might still vary, but it seems that those concepts might be more stable, when it comes to rules and changing them.</p><p>In our tourism example, we encapsulated and separated what varies and what seems to be more stable (according to our understanding of the domain).</p><p>Our little <code>TourNavigationPreparation</code> process, which seems to be more volatile, depends on more stable components.</p><p>We could say that we intentionally designed their interactions in such a way so that we got something back - for instance, stable components remain stable.</p><p>Also, &quot;guide availability&quot; and &quot;tracking location&quot; capabilities does not know why they are used, they just provide their capabilities.</p><p>&quot;Higher level&quot; <em>operations</em> know the reasons - as in our little example with <code>TourNavigationPreparation</code> process.</p><p>Let&#x27;s take &quot;tracking location&quot; - it might be used to track real people location - guides, participants - but also for &quot;simulated zombies&quot; that are chasing our participants.</p><p>We could add a new process that would be able to introduce &quot;geo-gaming&quot; while participanting in a tour.</p><p>This is yet another nice result we got back from organizing knowledge boundaries in such a way.</p><p>The complexity of the process got &quot;reduced&quot; (in fact, moved) and encapsulated in underlying capability providers.</p><p>And that&#x27;s the power of <a href="https://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215">tackling the complexity in its heart</a>.</p><p>There&#x27;s yet another perspective - which is related to software development, teams and their interactions.</p><p>We want to organize our bounded contexts in such a way that people working on them could work as independently as possible (which does not mean in a complete isolation!).</p><p>Strategic Domain-Driven Design brings more &quot;tools&quot; when it comes to analyzing types of domains and by having those information - organizing boundaries in a certain way.</p><p>And here comes the Context Mapping activity - it might give us the details of the impact of changes, dependencies, and so on.</p><h3 id="from-domain-model-to-domain-models"><a href="#from-domain-model-to-domain-models" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>From domain model to domain models</h3><p>The idea of &quot;a domain model&quot; isn&#x27;t bad - hell, it&#x27;s crucial to manage the complexity!</p><p>But the idea of &quot;<strong>the</strong> domain model&quot; is a fallacy as it brings &quot;God classes&quot;, compile-time hierarchies, and absolute-based thinking.</p><p>This is the curse of not deepending ones understanding enough, and trying to capture the reality in a single model.</p><p>The intentions are great, but the results can bring mess and a lot of pain, as &quot;domain model&quot; is so ambiguious term.</p><p>We should strive to create smaller domain model<strong>s</strong> - each tackling a very <a href="https://talesfrom.dev/blog/context-segregation-principle">perspective</a> that might appear in a business domain we are create software solutions for.</p><p>Each of those domain models can have various <a href="https://talesfrom.dev/blog/modeling-maturity-levels">depth of implementation</a>, depending on needs we identify.</p><p>Domain models might be used in different moments of <a href="https://talesfrom.dev/blog/time-angle-and-depth-dimensions-in-software-design">time</a>, depending on the process or use case we are trying to cover.</p><p>As you saw, dear Reader, &quot;hierarchies&quot; did not disappear, but they got transformed and moved onto a different level.</p><p>Instead of &quot;compile-time hierarchies&quot;, one could say we got &quot;runtime hierarchies&quot;, that can be composed at our will, in a more &quot;dynamic&quot; way.</p><p>Of course, we might introduce changes that will cause a ripple effect and make it difficult to accomodate them easily - that&#x27;s inevitable aspect of software engineering and software design.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Complexity does not disappear, it just gets moved elswhere.</p></div></div></div><p>It was a long journey, dear Reader, but I hope you enjoyed it.</p><p>We explored compile-time hierarchies that can appear both in gamedev and business systems.</p><p>We tried to apply &quot;Entity Component System&quot; thinking to tackle the complexity of business problems we are all experiencing in a day to day work.</p><p>In business applications, <em>components</em> are not &quot;pure data structures&quot; as in gamedev, as they encapsulate capabilities and rules that are related to those capabilities.</p><p>Business applications can have <em>systems</em> that are stateful, tracking the progress of underlying processes or workflows.</p><p>Even though gamedev and business applications might seem different in terms of problems, I feel that conceptually they are using similar approaches for dealing with complexity: &quot;what you hide, you can change&quot;.</p><p>Next time dear Reader, when you hear about &quot;domain model&quot;, think about &quot;domain models&quot; instead.</p><p>Domain models that within their boundaries are able to encapsulate capabilities and rules, and can be composed together to let more complex behaviors emerge.</p><p>See you next time!</p>]]></content:encoded>
    <pubDate>Mon, 04 Aug 2025 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>design thinking</category><category>domain-driven design</category><category>language patterns</category><category>design patterns</category><category>object-oriented design</category><category>functional programming</category><category>software architecture</category><category>mental models</category><category>communication</category><category>knowledge working</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/time-angle-and-depth-dimensions-in-software-design</guid>
    <title>Time, angle and depth: dimensions in software design</title>
    <link>https://talesfrom.dev/blog/time-angle-and-depth-dimensions-in-software-design</link>
    <description>Can we use physical qualities while reasoning about systems?</description>
    <content:encoded><![CDATA[<div class="bg-slate-600 rounded-xl "><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Attention!</span></div><div class="pb-2 px-3"><div class="break-words"><p>This blogpost is based on the plot that happened in one of the previous posts: <a href="https://talesfrom.dev/blog/context-segregation-principle">Context Segregation Principle</a>.</p>
<p>I greatly encourage reading it in the first place.</p></div></div></div> <div class="bg-slate-600 rounded-xl mt-10"><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Attention!</span></div><div class="pb-2 px-3"><div class="break-words"><p>I hugely recommend reading <a href="https://www.amazon.com/Balancing-Coupling-Software-Design-Addison-Wesley-ebook/dp/B09RV3Z3TP">Balancing Coupling</a> by <a href="https://www.linkedin.com/in/vladikk/">Vlad Khononov</a> - there are another set of dimensions (and more!) that can be used while designing systems.</p></div></div></div><h3 id="its-all-different"><a href="#its-all-different" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>It&#x27;s all different?</h3><p>Imagine a person named <span class="mr-2 text-red-500">Sam</span>who is the sales person of a company selling floor panels.</p><p>After the events happening <a href="https://talesfrom.dev/blog/context-segregation-principle">earlier</a>, <span class="mr-2 text-red-500">Sam</span>reported to his <span class="mr-2 text-violet-500">Boss</span>that struggled with communication towards his &quot;colleagues&quot;: <span class="mr-2 text-green-500">Igor</span>the installer and <span class="mr-2 text-blue-500">William</span>the warehouse worker.</p><p>So <span class="mr-2 text-violet-500">Boss</span>decided to organize a joint meeting to discuss the situation.</p><p>&quot;Communication is important in our company.&quot;, said <span class="mr-2 text-violet-500">Boss</span>.</p><p>All arrived at HQ to participate.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><span class=""><span class="italic font-bold text-violet-500">Boss</span>: Ok bright people - I gathered you all here as <span class="mr-2 text-red-500">Sam</span>told me that you all had troubles with getting aligned. Is that true, <span class="mr-2 text-red-500">Sam</span>?</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-red-500">Sam</span>: Yes, you are almost right, <span class=" text-violet-500">Boss</span>. Basically those two ignorants know nothing about flooring industry. All they did was putting obstacles in achieving the goal you assigned to me.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-blue-500">William</span>: <span class=" text-violet-500">Boss</span>, it&#x27;s utter BS. He entered the warehouse and started demanding exclusive panels storing points which is where the real ignorance is - if someone has at least a tiny fraction of knowledge how warehousing works, he would know that it&#x27;s much more involved than just shouting &quot;I want this&quot;...</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-green-500">Igor</span>: And I was just trying to help him out with the installation, but he was so stubborn that he didn&#x27;t want to listen to my advice. I mean, I am the installer here, I know how to do it properly.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-red-500">Sam</span>: It wasn&#x27;t about installation, you dumbass. We weren&#x27;t supposed to install anything!</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-blue-500">William</span>: But it wasn&#x27;t about getting something from storage either! If no order reference is provided, I can&#x27;t fetch anything from the storage.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-red-500">Sam</span>: You misunderstood everything...</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-violet-500">Boss</span>: To be fair <span class="mr-2 text-red-500">Sam</span>, you missed it too - to me it was very straightforward - showing off with blackness of African blackwood panels would make us tons of money. It wasn&#x27;t about sales, warehousing or installation!</span></span></div><p><span class="mr-2 text-violet-500">Boss</span>again was speechless.</p><h3 id="speaking-without-understanding"><a href="#speaking-without-understanding" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Speaking without understanding</h3><p>All the representatives of each company function missed the point of another one - including <span class="mr-2 text-violet-500">Boss</span>&#x27;s point brought in front of <span class=" text-red-500">Sam</span>&#x27;s face.</p><p>Each of them was an expert in his area - selling, storing and installing.</p><p><span class="mr-2 text-violet-500">Boss</span>himself was expert in closing big deals, building relationships and making sure that the company is profitable.</p><p>Each capability is required to make the whole company work - you can&#x27;t install panels if no one actually bought them.</p><p>You can&#x27;t sell them if you don&#x27;t have them in stock.</p><p>&quot;Is there a way to see the whole picture?&quot;, <span class="mr-2 text-violet-500">Boss</span>asked himself.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><span class=""><span class="italic font-bold text-violet-500">Boss</span>: Seems like we think about flooring industry a little bit differently. We speak but without understanding each other.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-red-500">Sam</span>: Everything would be easier if those two ignorants...</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-violet-500">Boss</span>: <span class=" text-red-500">Sam</span>, please. Getting back to the point, in order to get a happy customer, each of us need to do his or her job best. My job is to build relationships and make big deals, <span class=" text-red-500">Sam</span>&#x27;s job is to sell the best experience, <span class="mr-2 text-blue-500">William</span>is responsible to ensure we have stuff in stock when needed and <span class="mr-2 text-green-500">Igor</span>brings the experience to life, hence making dreams come true.</span></span><span class="text-white"><span class=""><span class=" text-red-500">Sam</span>, <span class="mr-2 text-blue-500">William</span>and <span class=" text-green-500">Igor</span>: (nod)</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-violet-500">Boss</span>: <span class=" text-green-500">Igor</span>, do you sometimes need to return to warehouse because floor panels you got are incorrectly dispatched for installation?</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-green-500">Igor</span>: Yes, but not that often, fortunately.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-violet-500">Boss</span>: Why do you think it happens?</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-green-500">Igor</span>: Hm, can&#x27;t really say, but I guess it&#x27;s due to an error when applying some details onto the order?</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-blue-500">William</span>: If I could add something here - sometimes it&#x27;s dispatching problem, but sometimes warehouse gets incorrect order details.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-violet-500">Boss</span>: What does it mean, <span class=" text-blue-500">William</span>?</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-blue-500">William</span>: We are providing a given package, because a specific material was ordered from the manufacturing party.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-violet-500">Boss</span>: Who sends this order to you, <span class=" text-blue-500">William</span>?</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-blue-500">William</span>: Well, sales. Recently we got a non-trivial problem as someone requested for &quot;premium oak flooring with natural finish&quot; but then <span class="mr-2 text-green-500">Igor</span>reported that the customer was extremely angry as they actually needed &quot;engineered oak flooring with brushed texture&quot;. To be honest, I don&#x27;t really care as the main job of mine is to ensure stock levels and provide material on the request, based on an order reference.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-green-500">Igor</span>: It was even more complicated - the installation place was a high-moisture bathroom, so solid wood would have warped within weeks. I couldn&#x27;t let it happen to waste a fine piece of material not suited for a given installation conditions.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-red-500">Sam</span>: But the customer said &quot;premium oak&quot;! How was I supposed to know about moisture issues?</span></span></div><p><span class="mr-2 text-violet-500">Boss</span>took a deep breath and tried to calm down himself and the situation.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><span class=""><span class="italic font-bold text-violet-500">Boss</span>: Ok, stop. My intention wasn&#x27;t to start blame game but rather show ourselves that it might be that each of us deals with a fraction of a reality.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-red-500">Sam</span>: What is real is that those two ignor...</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-violet-500">Boss</span>: Let me finish! <span class="mr-2 text-blue-500">William</span>does not care about moisture issues as in his context, his dealing with totally different problems.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-blue-500">William</span>: Yes, that&#x27;s true. Recently, a newhire was damaging incoming packages as he didn&#x27;t know how to operate a forklift.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-violet-500">Boss</span>: Hm, ok. But do you face any problems with moisture?</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-blue-500">William</span>: Yup <span class="mr-2 text-violet-500">Boss</span>- sometimes the package is marked with a specific humidity requirements which means we need to store it in a very particular place inside of the warehouse. What&#x27;s more, sometimes there&#x27;s no room left there which means we need to dispatch some stuff to other warehouses to make space...</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-violet-500">Boss</span>: Wait, you&#x27;re talking about humidity requirements - is it the same as <span class="mr-2 text-green-500">Igor</span>mentioned before?</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-green-500">Igor</span>: Not really <span class=" text-violet-500">Boss</span>. At least, I think so. Those problems are different than I face later.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-violet-500">Boss</span>: &quot;Later&quot;?</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-green-500">Igor</span>: Installed floor panels operate in a different humidity conditions than when they are being inside of a warehouse. I can&#x27;t install floor panel if it&#x27;s damaged due to badly storing conditions. The situation is different when the customer uses the product in the wrong way.</span></span></div><p><span class="mr-2 text-violet-500">Boss</span>got an enlightenment.</p><p>As each of the participants was expert in his or her area, dealing with a very specific fraction of reality, in a particular moment of time.</p><p>Even if all &quot;saw&quot; a floor panel, while communicating with each other, they were talking about different aspects of it!</p><p>Each of those aspects was important but not always in the same moments of time.</p><p>So each expert used some aspects of a floor panel, when the time has come.</p><p>Typically, when one function handed the work off to another one.</p><p><span class="mr-2 text-violet-500">Boss</span>invited all parties to have dinner tonight.</p><p>Calming everyone down and making sure they understand each other, not as a company functions, but as human beings, should make everything smoother and better.</p><p>Also, <span class="mr-2 text-violet-500">Boss</span>decided that each of them should spend at least one week in another area, to understand what is the context that others are dealing with.</p><h3 id="abstractions"><a href="#abstractions" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Abstractions</h3><p><a href="https://talesfrom.dev/blog/the-ambiguity-of-abstraction/">&quot;An abstraction&quot;</a> is quite loaded and biased term in software world (hence it is a part of <a href="https://talesfrom.dev/blog?title=the+ambiguity">The ambiguity of</a> series).</p><p>How often we deal with abstractions, dear Reader?</p><p>Is it just &quot;what we craft&quot; in the code?</p><p>&quot;What are you talking about? What abstractions have to do with floor panels?!&quot;, one might ask.</p><p>As we saw in this tiny tale, all the characters were talking, but were they understanding each other?</p><p>In earlier tale, <a href="https://talesfrom.dev/blog/context-segregation-principle">Context Segregation Principle</a>, we explored the idea of decomposing &quot;reality&quot; into a set of contexts.</p><p>This can be depicted by that diagram:</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/context-segregation-princinple-language.png" class="max-h-[30rem]"/></div><div class="italic mx-24">different names, based on the context</div></div><p>Even though we, human beings, communicate with each other using words (like &quot;a floor panel&quot;), we rarely mean the same thing as we think of a specific aspect of this thing, rather than &quot;this thing&quot; as the absolute.</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">a process of abstraction</div><div class="pb-2 px-3"><div class="break-words"><p>Taking away the details</p></div></div></div><p>So we are &quot;taking away the details&quot; of this &quot;absolute thing&quot; in order to simplify our operations while dealing with the reality, which is full of inifinite details.</p><h3 id="abstractions---when"><a href="#abstractions---when" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Abstractions - when?</h3><p>Why are we &quot;taking away the details&quot;?</p><p>We do so to simplify our reasoning about something, <strong>now</strong>.</p><p>I mean, not &quot;now now&quot;, but in the given moment of time.</p><p>Or &quot;when it&#x27;s needed&quot;.</p><p>Ok, so then let&#x27;s follow up with another question: <strong>when</strong> are we &quot;taking away the details&quot;?</p><p>We do so when details do not matter, of course (kinda surprising answer, isn&#x27;t it dear Reader?).</p><p>One could say that we are looking at something from a specific angle (or perspective) as it is what matters in this particular context, in that particular moment.</p><p>We capture the essence of a specific aspect of something in order to reason about it a certain way and possibly use this knowledge while further designing a system/a process/interactions.</p><p>Let&#x27;s bring back the diagram from before:</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/context-segregation-princinple-language.png" class="max-h-[30rem]"/></div><div class="italic mx-24">different names, based on the context</div></div><p>As we experienced the tiny tale, dear Reader, &quot;in order to make the customer happy&quot; all the &quot;company functions&quot; needed to play their role in a sequence of steps.</p><p>A sequence of steps implicitly brings the dimension of <strong>time</strong>.</p><p>Can you tell what is missing in this picture, dear Reader?</p><p>We only see contexts in a static manner, without getting the information <strong>how</strong> and <strong>when</strong> do they interact.</p><p>Imagine that we are taking a big, illusionary and &quot;abstract&quot; (pun intended) scissors and we cut (1) it right on one of the boundaries. Then, we &quot;unfold&quot; (2) the &quot;wheel&quot; made of all abstract ideas:</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/time-angle-depth-cutting-unfolding.png" class="max-h-[30rem]"/></div><div class="italic mx-24">unfolding perspectives</div></div><p>I hope you are able to do this exercise and visualization in your mind, dear Reader.</p><p>If not, here&#x27;s a result of doing so:</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/time-angle-depth-unfolded-abstractions.png" class="max-h-[30rem]"/></div><div class="italic mx-24">Unfolded perspectives</div></div><p>Nothing really changed as we see abstractions (or perspectives, interchangeably) not in &quot;a motion&quot;.</p><p>Let&#x27;s add the time dimension:</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/time-angle-depth-unfolded-abstractions-with-time.png" class="max-h-[30rem]"/></div><div class="italic mx-24">Unfolded perspectives with time dimension</div></div><p>And now this is when the magic happens.</p><h3 id="temporal-modeling"><a href="#temporal-modeling" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Temporal modeling?</h3><p>Thanks to adding &quot;time dimension&quot;, we have the possibility to represent the interactions between various &quot;perspectives&quot; on the same &quot;thing&quot;.</p><p>So this opens a possibility for us to see &quot;things in motion&quot; - how abstract ideas interact with each other, when various contexts are involved.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/time-angle-depth-unfolded-hand-off-diagram.png" class="max-h-[30rem]"/></div><div class="italic mx-24">Contexts handing off the work between each other</div></div><p>It might look familiar to you, dear Reader.</p><p>&quot;Bravo, you just invented a sequence diagram!&quot;, one might say.</p><p>Or Event Storming, or BPMN diagram, or whatever we can call it.</p><p>What we just saw, resembles more &quot;handoff diagram&quot; introduced in <a href="https://a.co/d/1OAvSAj">Workflow Modeling</a> (at least that&#x27;s where I read it for the first time).</p><p>Thanks to &quot;time&quot; we can see (almost) complete picture - when and what are the interaction patterns between various <a href="https://talesfrom.dev/blog/context-segregation-principle">segregated contexts</a>.</p><p>Taking <em>perspective</em> and <em>time</em> dimensions we can make &quot;the absolute concepts&quot; (like <code>User</code>, <code>FloorPanel</code>, <code>GroupChat</code>, <code>Product</code>) ceasing to exist (at least mentally).</p><p>This little diagram we brought to life isn&#x27;t as detailed as many Event Storming and BPMN diagrams out in the wild - but it gives us the possibility to see the patterns and then start discussions.</p><p>It&#x27;s one of the levels - we can go deeper and inspect important facts happening, check if there are any important rules that need to be satisfied, and so on.</p><p>If something is looking superficial or trivial - change the perspective or change the level.</p><h3 id="what-about-depth"><a href="#what-about-depth" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What about depth?</h3><p>Yes, depth.</p><p>In <a href="https://talesfrom.dev/blog/modeling-maturity-levels">Modeling Maturity Levels</a> we explored the idea of &quot;depth&quot; in modeling - which gave us powerful tool to reason about how can we model one particular aspect of something.</p><p>But don&#x27;t get fooled, dear Reader.</p><p>We might uncover new perspectives (=abstractions) as we are transitioning between levels, e.g. while browsing <strong>Behaving</strong> level, we might discover that there&#x27;s another perspective that <strong>appears in a particular moment of time</strong> (which means - interaction).</p><p>If we represent &quot;a floor panel&quot; as a class, we might uncover that a method <code>Install</code> can&#x27;t happen if it wasn&#x27;t delivered first:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="code-highlight language-csharp"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">FloorPanel</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">void</span></span> <span class="token function">Install</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>Delivered<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">InvalidOperationException</span><span class="token punctuation">(</span><span class="token string">&quot;Can&#x27;t install a floor panel that wasn&#x27;t delivered yet.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">        <span class="token comment">// installation logic...</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Hence we might split a single abstraction into two - <code>InstallationMaterial</code> and <code>InventoryItem</code>, correlated by a single identifier.</p><p><code>InventoryItem</code> won&#x27;t ever have <code>Install</code> behavior, but <code>InstallationMaterial</code> will.</p><p>Such <a href="https://talesfrom.dev/blog/context-segregation-principle">contextual segregation</a> might make our sight so sharp that we will see that <code>InventoryItem</code> <strong>Becomes</strong> <code>InstallationMaterial</code> <strong>when</strong> it&#x27;s delivered.</p><p>Suddenly we start modeling concepts on the &quot;highest&quot; possible level - <strong>Becoming</strong> level. (but of course there is <a href="https://talesfrom.dev/blog/the-cost-of-modeling">The cost of modeling</a> effect).</p><p>And here we are getting a sequence of steps - a process.</p><p>So one could state that each dimension reinforces our designing and modeling as we are getting the feedback from this process.</p><p>In order to get those diagnostic signals while modeling, we need to <a href="https://talesfrom.dev/blog/slow-down">Slow down</a>.</p><h3 id="other-dimensions"><a href="#other-dimensions" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Other dimensions?</h3><p>Turns out that there are other dimensions that one can (and I believe should!) use while reasoning about systems, processes and modeling.</p><p>I am talking about ones presented in <a href="https://www.amazon.com/Balancing-Coupling-Software-Design-Addison-Wesley-ebook/dp/B09RV3Z3TP">Balancing Coupling</a> by <a href="https://www.linkedin.com/in/vladikk/">Vlad Khononov</a>.</p><p>To tease you a little bit dear Reader (hence hoping this will encourage you to buy and read the book), I will reveal one interesting tool (and useful in terms of changing the mental model) that Vlad introduces in his profound book.</p><p>Vlad brings to us the following &quot;equation&quot;:</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">PAIN dimensions</div><div class="pb-2 px-3"><div class="break-words"><p>PAIN = f(Strength, Volatility, Distance)</p>
<p>PAIN = Strength x Volatility x Distance</p></div></div></div><p>This formula describes &quot;the pain&quot; (or &quot;the cost incurred&quot;) one might experience while introducing a change in the system, hence maintaining the system.</p><p>Each &quot;part&quot; represents some aspect of the system:</p><ul><li><em>Strength</em> represents knowledge shared among two &quot;concepts&quot;</li><li><em>Volatility</em> represents how often two, coupled &quot;concepts&quot; change</li><li><em>Distance</em> represents how far apart those two &quot;concepts&quot; are in the system (file-wise, department-wise, etc.)</li></ul><p>&quot;Ok, why the hell you brought even more abstract terminology, Damian?&quot;, one might ask.</p><p>I was just wondering - how might &quot;PAIN dimensions&quot; relate to <em>time</em>, <em>angle</em> and <em>depth</em> dimensions?</p><p>At the time of writing, I feel that dimensions summed up in this blog post appear firstly in the continuum, as we need to have abstract concepts to work on, and then verify &quot;the pain&quot; related to changing them.</p><p>Time, angle and depth might help us with training our brain and eyes to &quot;see more&quot; while reasoning about &quot;the business reality&quot; - <a href="https://talesfrom.dev/blog/context-segregation-principle">segregate contexts</a>, <a href="https://talesfrom.dev/blog/modeling-maturity-levels">look through various levels</a>, observing how all those concepts and contexts interact over time.</p><p>Simultaneously, we can simulate changes (e.g. of the requirements) that will challenge summoned concepts&#x27; integration strength, volatility and distance.</p><p>Such simulations might help us verifying what maintenance pain/costs we might experience.</p><h3 id="is-it-useful"><a href="#is-it-useful" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Is it useful?</h3><p>&quot;Ok, but how can I use it while coding?&quot;, you might be wondering dear Reader.</p><p>Imagine that we are dealing with a web application and in order to ensure that the session is established, we need to have a user logged in which will be represented by obtaining an access token.</p><p>So we might be dealing with a given structure in application state:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">AppState</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
</span><span class="code-line">    user<span class="token operator">:</span> User <span class="token operator">|</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
</span><span class="code-line">    accessToken<span class="token operator">:</span> <span class="token builtin">string</span> <span class="token operator">|</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token comment">// ...and more!</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>So every time we want to do anything with the token, we must check if it is non-null.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">if</span><span class="token punctuation">(</span>state<span class="token punctuation">.</span>accessToken<span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// do something that requires the token to be present</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>But wait, we know that after certain time the token will be present so why the heck we need to check that the access token is there?</p><p>Maybe we are missing a perspective here that transformes itself into another one, e.g. <code>UnauthorizedAppState</code> and <code>AppState</code>?</p><p>Eventually, we might discover that we are dealing with <a href="https://talesfrom.dev/blog/fsm-functional-state-machines">state machines</a> and model essential aspects of such interaction accordingly (&quot;a fraction of reality&quot;).</p><p>Of course, it is a toy example, but I hope you get the point, dear Reader.</p><p>In my humble opinion we are capable of using those dimensions (time, angle and depth) while working with the code as long as we are able to &quot;receive the diagnostic signal&quot; sent by the software constructs we are working on.</p><p>Feedback and openness to it is the key here.</p><p>Based on such reasoning, one could state that time, angle and depth are ways to decompose the reality into a set of cohesive concepts and &quot;PAIN dimensions&quot; are there to validate if decomposition &quot;holds&quot; after &quot;we shake the model&quot;.</p><h3 id="time-angle-and-depth"><a href="#time-angle-and-depth" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Time, angle and depth</h3><p>It is so fascinating that many people across the world, in different times and places, came up with similar ideas - especially when it comes to using time in modeling.</p><p>It might constitute &quot;a proof&quot; that we are dealing with something universal, something fundamental that precedes everything we do and &quot;see&quot; (subjectively).</p><p>Some methods and approaches vary in the syntax, the nomenclature and the details, but the essence is the same - we must look for abstractions on various levels, constantly including the domain of time in order to design boundaries and assign responsibilities.</p><p>We must do so as that is the way we can deal with inevitable complexity of the reality we live in.</p><p>Next time, dear Reader, when you will be dealing with a problem, either in the code or while having a whiteboard session, remember about dimensions of software design.</p><p>Look at &quot;things&quot; from various perspectives and through various levels.</p><p>Check how they interact and possibly change over time.</p><p>Simulate changes and observe the cost (or pain) it incurrs.</p><p>Suggest at least three models so that you don&#x27;t be afraid of <a href="https://talesfrom.dev/blog/the-cost-of-modeling">The cost of modeling</a> as you will be able to <a href="https://www.amazon.com/Balancing-Coupling-Software-Design-Addison-Wesley-ebook/dp/B09RV3Z3TP">balance coupling</a>.</p><p>And remember - if you are facing an absolute-looking concept (like User, GroupChat, etc.), treat it as an alert, a signal to start asking questions, e.g.</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>When does this &quot;thing&quot; appear?</p>
<p>What workflow are we talking about?</p></div></div></div>]]></content:encoded>
    <pubDate>Sat, 12 Jul 2025 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>design thinking</category><category>domain-driven design</category><category>language patterns</category><category>design patterns</category><category>object-oriented design</category><category>functional programming</category><category>software architecture</category><category>mental models</category><category>communication</category><category>knowledge working</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/easy-will-make-you-dizzy</guid>
    <title>Easy will make you dizzy?</title>
    <link>https://talesfrom.dev/blog/easy-will-make-you-dizzy</link>
    <description>Are we losing something important while getting better tools?</description>
    <content:encoded><![CDATA[<h3 id="orm---oh-my-model"><a href="#orm---oh-my-model" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>ORM - Oh My Model</h3><p>Imagine that we are dealing with a project that requires writing migration scripts manually when database schema changes.</p><p>We try to keep backward compatibility to avoid downtime as much as we can, but sometimes it is not possible.</p><p>Each time we want to introduce a change, we need to carefully analyze the impact, understand the current schema and figure out the most appropriate new schema.</p><p>We don&#x27;t want to introduce big changes to minimize the risk of breaking something, so we spend time designing new data models.</p><p>Sometimes we would like to get data model fitting the problem domain, but it would require substantial changes so we decide to make a trade-off and use imperfect but pragmatic data model.</p><h3 id="omg-no-orm"><a href="#omg-no-orm" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>OMG, no ORM?</h3><p>Now imagine that we are using an ORM (Object-Relational Mapping) library that automatically generates migration scripts based on the changes in our data model.</p><p>Thanks to the ORM, we are delegating migration scripts generation to the tool.</p><p>When we designed the data model in an incorrect way, we can quickly and easily fix the weak design and get rid of its weaknesses.</p><p>We exchanged time-consuming, error-prone and manual process of writing migration scripts for a fast, autogenerated one.</p><p>We got this flexibility and speed, but are they for free?</p><h3 id="so-you-want-us-to-help-you-modeling-it"><a href="#so-you-want-us-to-help-you-modeling-it" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>So you want us to help you modeling it?</h3><p>Imagine that we are working on a project that supports B2C sales process and it is a multi-tenant, multi-step process.</p><p>We used collaborative methods (like Event Storming) to build a common and shared understanding of this process.</p><p>Thankfully we were able to apply Domain-Driven Design heuristics and we ended up with a set of bounded contexts.</p><p>We identified proper capabilities that need to be provided in order to satisfy the requirements.</p><p>Process and subject matter experts successfully confirmed and validated our understanding by looking at the acceptance tests we wrote together.</p><p>It took some time as many people were involved, as various perspectives and many experiences collided with each other.</p><h3 id="ah-so-you-want-to-model-it-yourself"><a href="#ah-so-you-want-to-model-it-yourself" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Ah, so you want to model it yourself?</h3><p>Now imagine that process and subject matter experts got introduced into a low-code platform for visualizing workflows and connecting systems together.</p><p>In the blink of an eye, they can create steps, define conditions, sink data and connect elements together.</p><p>Sometimes they struggle with &quot;the platform&quot; and that&#x27;s when &quot;IT nerds&quot; are called to help them out.</p><p>They are able to ship new sales workflows in a matter of days, sometimes even hours.</p><p>The organization exchanged time-consuming, error-prone and manual process of modeling for a fast, automated and visual one.</p><p>We got this flexibility and speed, but are they for free?</p><h3 id="what-should-be-the-new-scenario"><a href="#what-should-be-the-new-scenario" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What should be the new scenario?</h3><p>Another context - let&#x27;s think about a web application that allows users to register new support cases and support agents responding to them.</p><p>The whole team is working on it - we could say it is a cross-functional team as it includes product engineers, product designer, product owner and product architect.</p><p>Turns out that there&#x27;s a request from the customers buying this software from us - they would like to have another scenario supported, as there&#x27;s some pattern occuring when handling support cases.</p><p>The team gathers and analyzes the request, they discuss it and come up with a solution.</p><p>It takes some iterations in which they are able to refine the solution based on the feedback they are getting from pilot customers.</p><p>Turns out that the feature is a great success and they release it to other customers in the blink of an eye as they use feature flags.</p><h3 id="create-a-new-scenario-based-on-the-codebase-and-rules-i-give-you"><a href="#create-a-new-scenario-based-on-the-codebase-and-rules-i-give-you" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Create a new scenario based on the codebase and rules I give you&quot;</h3><p>Next time, the product owner is equipped with a modern tool - &quot;one of those AI assistants that can generate apps in seconds&quot;.</p><p>The product owner is able to describe the scenario in natural language and the AI assistant is able to generate a new scenario based on the existing codebase and rules.</p><p>It works almost like magic - there are some hiccups, but the product owner calls product engineers and product architect to figure out &quot;the technical stuff&quot; so that it all compiles and passes all tests.</p><p>Soon, yet another scenario is supported and the product owner is able to focus on the business value and market fit.</p><p>The team exchanged time-consuming, error-prone and manual process of sitting together and discussing the requirements for a fast, automated and AI-powered one.</p><p>We got this flexibility and speed, but are they for free?</p><h3 id="you-probably-missed-the-point"><a href="#you-probably-missed-the-point" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>You probably missed the point</h3><p>You might be thinking dear Reader that I went nuts and I an advocating for stopping using ORMs, low-code platforms and &quot;AI assistants&quot;.</p><p>Who doesn&#x27;t want to write data migration scripts manually?!</p><p>But if you could reflect a little while on those three little stories, do you think they share something?</p><p>There was a problem which got solved by introducing a tool that &quot;automates&quot; some of the work.</p><p>It comes with some new abstractions (here: abstract concepts people need to learn to use the tool and communicate effectively) but gives so much powers, isn&#x27;t it?</p><p>Each time we advanced capabilities by using the tool, we delegated some part of the work to it too.</p><p>What about the process of designing?</p><p>Did we lose something when those parts got delegated, or should we say, &quot;automated&quot;?</p><h3 id="easy-will-make-you-dizzy"><a href="#easy-will-make-you-dizzy" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Easy will make you dizzy?</h3><p>Turns out that we might misunderstand the problems we are dealing with (as we tried to discuss in <a href="https://talesfrom.dev/blog/the-ambiguity-of-problems/">The ambiguity of problems</a>).</p><p>They provide us very important signal - a diagnostic one, telling us that we might be doing something that is not so rational at this point.</p><p>When new tools are introduced, some of those &quot;signals&quot; are gone.</p><p>A classical trade-off - we get something in exchange for something else.</p><p>Here, in those stories, the easiness of iterating and delivery speed got returned in exchange of the getting feedback while designing - whether those were data models (database schema), bounded contexts supporting business processes or web applications and new scenarios.</p><p>It might be that the more design aspects we delegate &quot;to the tools&quot;, the less we might actually be able to design.</p><p>One might say: &quot;but we are designing on a totally different level now - no one is designing using assembly language, right?&quot;.</p><p>Definitely - I wouldn&#x27;t like to write assembly language for a web application either.</p><p>I am more warning ourselves, dear Reader, that using <a href="https://talesfrom.dev/blog/tools-make-fools/">Tools make fools?</a>.</p><p>If something is getting easier, it might be we are losing something - which eventually might turn out to be beneficial and positive for us, for the surroundings and for the world around us.</p><h3 id="the-world-of-ai"><a href="#the-world-of-ai" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The world of &quot;AI&quot;</h3><p>I can&#x27;t say I like the label &quot;AI&quot; when it comes to all the tools we are getting, especially when non-technical people are commeting on them.</p><p>I still consider them as &quot;tools&quot;, which makes it possible to use metaphor related to making fools out of ourselves.</p><p>Or giving us dizziness when we overdose &quot;AI fixes everything&quot; fumes.</p><p>The industry will transform itself into something different, no doubt on it.</p><p>But I am afraid that we might be losing something important while getting better tools - possibly our industry ancestors would have said similar when it comes to not using assembly language on daily basis, by everyone.</p><p>I strongly believe that designing as a skill will be even more important than ever.</p><p>Either we take ORMs, low-code platforms or &quot;AI assistants&quot;, for sure we got cheaper iterations and faster delivery - agile software development at its best, one could say.</p><p>I want to make it easier to deliver value to the customers by shipping high-quality software.</p><p>Easiness for &quot;code production&quot; does not always mean &quot;high-quality software&quot;, isn&#x27;t it?</p><p>Let&#x27;s recall what was the first sentence in the great book by Craig Larman, <a href="https://www.amazon.com/Applying-UML-Patterns-Introduction-Object-Oriented/dp/0131489062">Applying UML and Patterns</a>:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Programming is fun, but building high quality software is hard.</p></div></div></div><p>As &quot;typing was never the problem&quot;, optimizing code generation/production isn&#x27;t a problem either.</p><p>One could easily extrapolate and conclude:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Code (over)production is fun, but building high quality software is hard.</p></div></div></div><h3 id="its-not-code-production-thats-hard-its-designing-that-is-hard"><a href="#its-not-code-production-thats-hard-its-designing-that-is-hard" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>It&#x27;s not code production that&#x27;s hard, it&#x27;s designing that is hard</h3><p>Often, when people are not familiar with <a href="https://talesfrom.dev/blog/the-ambiguity-of-tdd">specifying behavior through tests</a> (also known as TDD - Test-Driven Development), they say that writing tests is hard.</p><p>It&#x27;s not that writing tests is hard, it&#x27;s designing that is hard.</p><p>Learn software design - at various levels - from data models, through domain models, to software architecture and user experience - and more!</p><p>To my current knowledge, it is an evergreen skill that will never go out of fashion.</p><p>And no, I am not taking solely about designing.</p><p>I am talking mostly about learning.</p>]]></content:encoded>
    <pubDate>Tue, 01 Jul 2025 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>design thinking</category><category>tools</category><category>domain-driven design</category><category>language patterns</category><category>design patterns</category><category>object-oriented design</category><category>functional programming</category><category>software architecture</category><category>mental models</category><category>communication</category><category>knowledge working</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/tools-make-fools</guid>
    <title>Tools make fools?</title>
    <link>https://talesfrom.dev/blog/tools-make-fools</link>
    <description>Are we doomed to become &quot;slaves&quot; of tools?</description>
    <content:encoded><![CDATA[<h3 id="another-great-event-storming-session"><a href="#another-great-event-storming-session" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Another great Event Storming session!</h3><p>You stand in front of a (digital) wall, full of stickies proudly expressing important facts happening throughout a specific place of the system you are working on.</p><p>Ah, all those orange stickies!</p><p>External systems, actors, commands - looks impressive.</p><p>You look around and it seems that you might be the only one so enthusiastic about the result.</p><p>Result.</p><p>What is the result?</p><p>Of course, each person probably desired to get something out of this &quot;meeting&quot;.</p><p>Is there an ultimate, universal result one should expect from this kind of activity?</p><p>Colorful stickies on the wall is probably just a symbol of it.</p><p>When we ask people who participated &quot;in the meeting&quot;, it turns out that not everyone got on the same page.</p><p>Some people didn&#x27;t understand the notation, some of the got bored about discussing workflow topics they already knew.</p><p>Subject matter experts didn&#x27;t get &quot;why we are doing so&quot; as everyone in the room know how the system is working.</p><p>But all the promises...</p><h3 id="microservices---this-time-we-will-make-it"><a href="#microservices---this-time-we-will-make-it" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Microservices - this time we will make it!</h3><p>Imagine that we got assigned to a challenging task - we&#x27;re going to modernize a part of our system so that it can better serve our customers and the business.</p><p>Thank God we watched couple of videos from prominent conferences, we attended some of them on site.</p><p>Kubernetes, observability, serverless, hexagonal architecture, Domain-Driven Design - oh my, so many things to apply in the new initiative!</p><p>We group a bunch of people, and we start to design the new system.</p><p>&quot;Modules&quot; emerge as if there were mushrooms after the rain - everything is decomposed into smaller pieces, each with its own responsibility.</p><p>When we looked upon an architectural sketch, all those independently deployable modules proudly stand out, each with its own color and purpose.</p><p>The future looks bright.</p><p>Each module gets its own repository, own CI/CD pipeline - and we are ready to go!</p><p>People start implementing the modules, and the first problems appear.</p><p>When it came to integration, it turned out that modules (and people) are not truly isolated.</p><p>Soon managers scheduled coordination meetings and our &quot;independent&quot; modules started to materialize dependent interations between each other.</p><p>But all those promises...</p><p>What result did we expect?</p><h3 id="you-need-to-be-more-agile"><a href="#you-need-to-be-more-agile" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>You need to be more Agile!</h3><p>Another sprint planning - unfortunately nothing was released to production in previous sprint, but we all hope this time it will be different.</p><p>The team is ready to pick items from overpromised backlog, scrum master is ready to dispatch the work to each developer.</p><p>Seventeen user stories are in progress, seems like it goes well - there is no minute wasted as all are busy.</p><p>Software engineers have some ideas how to improve the product by just adding small features that might make the whole experience better.</p><p>Well, backlog is full with predefined epics, user tasks, requirements, and so on.</p><p>Designs are provided by external UX people, architects do not contribute in designing the system other than giving &quot;design blueprints&quot; and making decisions.</p><p>The further with the Agile journey, the less agile the team is.</p><p>But all those promises...</p><p>What result did we expect?</p><h3 id="ai---no-more-devs-and-their-laziness"><a href="#ai---no-more-devs-and-their-laziness" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>AI - no more devs and their laziness!</h3><p>The Gods sent us the almighty AI!</p><p>Now all the problems we had with software development are going to disappear - we will have &quot;agents&quot; at the tips of our fingers (or tongue), systems will &quot;code&quot; themselves in a speed of light.</p><p>Or speed of thought.</p><p>We order, &quot;agents&quot; do.</p><p>&quot;It&#x27;s another level of abstraction, you don&#x27;t need to look inside. It&#x27;s a black box.&quot;, many say.</p><p>Soon, a flock of unexperienced developers start using AI to produce code, even with tests!</p><p>Ha, in your face, &quot;lazy&quot; senior devs!</p><p>We can produce a lot of code and add features faster than ever!</p><p>Soon, it turns out that no one really understands the code that was &quot;produced&quot;.</p><p>Bugs breed bugs, which then breed more bugs - people inside of the organization forge a new concept - &quot;Cockroach-Driven Development&quot;.</p><p>New waves of &quot;bugs&quot; are produced in a speed of light, or thought, if you wish.</p><p>Senior developers are not equipped with a proper tools to analyze, understand and re-design parts of the system.</p><p>More AI is employed/utilized to heal the situation.</p><p>Architects draw diagrams but they are a mere beliefs how things should work but actually aren&#x27;t.</p><p>Cockroaches, cockroaches everywhere.</p><p>But all those promises...</p><h3 id="tools"><a href="#tools" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Tools?</h3><p>Human beings are tool-making animals.</p><p>As tools are made, they are made to be consumed.</p><p>Hence, we are tool-consuming creatures too.</p><p>We use them to survive, to make our lives easier, to make our work less effort-requiring.</p><p>But behind every tool, there&#x27;s a philosophy, a way of thinking.</p><p>A problem that forced (or encouraged?) people to create a tool so that their work become easier.</p><p>This problem manifested itself in a specific context, in which systems (socio-technical constructs) operated.</p><p>IT is pretty young industry, still explores and looks for stable approaches for producing value using software systems.</p><p>Repeatable processes that bring predictability and stability when it comes to getting results.</p><p>Same results.</p><p>Every time the tool is used.</p><p>Fortunately or unfortunately, tools we use are not like power drills or similar - even though the metaphor seems to hold for most of the time.</p><p>Designing, building and supporting products/systems is a complex task, which requires a lot of thinking, understanding and <strong>empathy</strong>.</p><p>All of that is a social endeavour, which requires outstanding effort invested in making everyone aware of the context, the problem, the concepts &quot;living&quot; in the problem area.</p><p>As we discussed some time ago in <a href="https://talesfrom.dev/blog/systems-by-with-for-people">Systems: by, with, for people</a>, turns out that all we do involves human beings.</p><p>This aspect cannot be neglected and what&#x27;s more - it needs emphasis each time we design stuff.</p><p>Not only visually but also &quot;internally&quot; - when we name variables, design boundaries around modules or document how to run utility tools.</p><h3 id="fooled-by-tools"><a href="#fooled-by-tools" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Fooled by tools?</h3><p>&quot;Just use Event Storming&quot;, &quot;Ports &amp; Adapters is all you need&quot;, &quot;F# is the language that solves all the problems&quot; (actually, many of the problems, but I am biased 😉) - have you heard such bold statements, dear Reader?</p><p>How often are we lured into this valley in which adopting a tool will make all problems magically disappear?</p><p>Tools are &quot;just&quot; manifestation of a solution to a problem, appearing in a specific context.</p><p>Does my context seem similar to the context in which authors of a proposed tools were operating in?</p><p>What if it&#x27;s different?</p><p>Just pouring &quot;daily standups&quot; or &quot;AI&quot; into our work won&#x27;t &quot;magically work&quot; - for sure they might postpone the disaster or &quot;fireworks&quot;.</p><p>I truly believe that one needs to understand the principles, the philosophy, the contextual ideas and concepts behind a given &quot;tool&quot; - whether it&#x27;s about Agile, microservices, AI or Event Storming.</p><p>In many cases it&#x27;s about human beings - making them more comfortable, less loaded (cognitiviely) or similar.</p><p>It&#x27;s of course easy to say &quot;don&#x27;t get fooled by tools&quot; and walk over - but how to achieve so?</p><p>We can use yet another tool - a question:</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>What &#x27;good&#x27; will be created after we employ X?</p></div></div></div><p>It is another form of an opportunistic question - &quot;What does it give to me?&quot;.</p><p>It puts a frame that whatever gets created, must be organic and positive, when it comes to outcome.</p><p>Looks beyond the tools, looking at the new concepts it introduces to the language we use on daily basis, should give us deeper meaning on why we should utilize them.</p><p>Ports &amp; Adapters - why one wants to use it and what outcomes it promises to bring?</p><p>Agile - why people came up with this tools and what we expect to get back from it?</p><p>Aggregates, in Domain-Driven Design sense - what was the context for this tools be used?</p><h3 id="first-principles"><a href="#first-principles" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>First principles</h3><p>At the moment of writing, AI tools appear sooner that I type the letters, channeling thoughts from my mind.</p><p>They all promise bringing efficiency, easiness and impressive results.</p><p>It&#x27;s not I am bashing or neglecting incoming changes - I am welcoming them, knowing what is truly important (to me, at the time of writing).</p><p>Understanding first principles, getting fundamentals right, as there are universal and evergreen concepts each software professional need to know in order to create systems that maintain producing value over time.</p><p>That&#x27;s actually I am fascinated by words, by concepts and by language we all use - as it&#x27;s about certain abstractions we&#x27;ve brought to this world, to make our lives/work easier.</p><p>Wait, does it mean that abstractions are <em>tools</em>?!</p><p>One could think in that kind of way - I really recommend understanding &quot;our&quot; (= knowledge workers) tools - abstract concepts brought by generations - either they were crafted in 70s or 2000s.</p><p>&quot;Are you crazy Damian? Nowadays most of the stuff is outdated!&quot;, one might easily say.</p><p>Well, I am not denying that, but it&#x27;s really similar (to me, now, in this context) to ADRs (Architecture Decision Records) - we typically want to have them not for the options we chose, but to understand which options we discarded.</p><p>It might look familiar as wise words state:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Whoever does not know and respect history is doomed to repeated it.</p></div></div></div><p>I don&#x27;t know about you dear Reader, but to me it seems that it&#x27;s worth <em>studying</em> the past, to become smarter for the future.</p><h3 id="studying"><a href="#studying" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Studying?</h3><p>Yes, studying.</p><p>Learning a concept is one thing, but learning and re-learning it might eventually lead to new insights - every iteration is different, even if it might look the same.</p><p>Concepts remain the same, but we change ourselves.</p><p>Our sight gets sharper and more precise.</p><p>Our thoughts become clearer.</p><p>As we walk down the path for seeking greater understanding.</p><p>And please don&#x27;t get me wrong, dear Reader - I am not advocating for living in the academic/ivory tower, without getting our hands dirty.</p><p>Getting dirty is a part of studying process.</p><p>Inevitable one, I would dare to say.</p><p>But just &quot;jumping&quot; into the action, without &quot;training&quot; ourselves in seeing the concepts in action, might not bring the right experience.</p><p>Kind of following &quot;what I can&#x27;t name, I can&#x27;t use consciously&quot;.</p><h3 id="whats-next"><a href="#whats-next" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What&#x27;s next?</h3><p>It&#x27;s easy to drown in the world full of abstract complexities, brought by other people or ourselves.</p><p>Most of the tools were created to work as aid to re-occuring problems.</p><p>By understanding the context, we might pick the tools consciously and not be angry that a square peg does not match a circle hole.</p><p>Next time dear Reader, when you are going to use a tool (even if it&#x27;s 100th time this year), ask yourself:</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>What problem does it promise to solve?</p></div></div></div>]]></content:encoded>
    <pubDate>Mon, 09 Jun 2025 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>language patterns</category><category>communication</category><category>collaboration</category><category>shared understanding</category><category>software teaming</category><category>working together</category><category>tooling</category><category>domain-driven design</category><category>software architecture</category><category>software design</category><category>pragmatism</category><category>philosophy</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/wtf-are-you-talking-about-acronyms-jargon-and-abbreviations</guid>
    <title>WTF are you talking about? Acronyms, jargon and abbreviations</title>
    <link>https://talesfrom.dev/blog/wtf-are-you-talking-about-acronyms-jargon-and-abbreviations</link>
    <description>How to make collaboration harder?</description>
    <content:encoded><![CDATA[<div class="bg-slate-600 rounded-xl mb-10"><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Attention!</span></div><div class="pb-2 px-3"><div class="break-words"><p>This article is based on multiple conversations I had with a fellow craftsman, a friend of mine - <a href="https://twitter.com/PrzemekWolnik">Przemek Wolnik</a></p>
<p>Kudos to Przemek!</p></div></div></div><h3 id="the-meeting"><a href="#the-meeting" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The meeting</h3><p>Imagine that you walk into a meeting room (or join a video call, which might be much more probable these days), and you see that the presenter is already showing his slidedeck.</p><p>You sip your coffee or tea, and you start to listen.</p><p>Even though presenting person has a very nice voice, uses enganging plots and figures, but something is not right.</p><p>The feeling of confusion is growing proportionally to the number of acronyms used in the presentation.</p><p>BDB.</p><p>WUZ.</p><p>MIRPCO.</p><p>SOLID.</p><p>TDD.</p><p>PLP.</p><p>All people seem to understand what the presenter is talking about, but you are lost.</p><p>Someone asks a question about the BDB and the discussion starts.</p><p>Suddenly a third person joins the discussion about BDB and asks about the connection between BDB and WUZ.</p><p>The conversation gets a little heated, and you feel that you are not part of it.</p><p>People are nodding, confirming they are on the same page, but you are not.</p><p>Later in the kitchen, you ask a colleague about the BDB acronym, and he explains that it stands for &quot;Big Data Builder&quot;.</p><p>Strange, probably some internal tool that you don&#x27;t know about.</p><p>The confusion comes as you don&#x27;t know if you should know about it - meaning, ask more questions.</p><h3 id="wtf"><a href="#wtf" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>WTF?</h3><p>What do you think, dear Reader? Does it sound familiar?</p><p>Can you recall a situation when you were sitting in a meeting in which &quot;the business people&quot; seemed to discuss topics that you had no clue about?</p><p>And on the other hand, have you ever presented anything to people from different &quot;domain&quot; and used tons of jargon, without asking if all is understood?</p><p>It&#x27;s quite typical to make people feel lost and feel lost yourself - and meetings were supposed to make everyone on be the same page, isn&#x27;t it?</p><p>Using acronyms has its own purpose and usefulness, but it can also be a source of confusion and miscommunication.</p><p>Why do we use acronyms?</p><p>To make the communication smoother, more efficient and faster, right?</p><p>But there is an assumption - that all people know what the acronym stands for.</p><p>Same goes with jargon, abbreviations and other language patterns that are used in the communication - typically they work well inside of a particular bubble, in which people are familiar with them.</p><p>And what about communicating across the bubbles?</p><p>Exiting the knowledge boundary in which we typically work and operate, in order to communicate ideas, concepts and information, is enormously important.</p><p>Solving problems is often (I wanted to say &quot;always&quot;, but it&#x27;s dangerous assumption) a consequence of collaboration.</p><h3 id="making-collaboration-harder"><a href="#making-collaboration-harder" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Making collaboration harder</h3><p>Ready to make others&#x27; lives more difficult?</p><p><strong>Use acronyms without asking if everyone knows what they mean.</strong> This will help you lose your audience, create confusion and make other people feel dumb.</p><p><strong>Use jargon assuming everyone knows what you are talking about.</strong> Such approach enables creating the right silo in which you can operate and look as an expert in matter.</p><p><strong>When talking about ideas and abstract concepts, do not visualize them or explain them using examples.</strong> Thanks to that, the cognitive load of others will skyrocker and they will get lost in the maze of abstractions.</p><p><strong>Use the right tone indicating that all the people in the room should know what you are talking about.</strong> Many of the attendees will feel ashamed and you will get less questions which basically makes your life easier.</p><p>Easy, isn&#x27;t it?</p><p>Of course dear Reader, I am not suggesting you to do any of the above.</p><p>&quot;Just sayin&#x27;&quot;.</p><h3 id="buckle-up-theres-no-time"><a href="#buckle-up-theres-no-time" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Buckle up, there&#x27;s no time!</h3><p>One might easily say that explaining things over and over again is a waste of time, &quot;as people should know it already&quot;.</p><p>Spending 10 minutes explaining all required lingo for sure costs time, but what do we get back in return?</p><p>People won&#x27;t build assumptions.</p><p>Assumptions that are one of the biggest sources of failures, bugs, problems and misunderstandings.</p><p>So we prevent possible collaboration &quot;catastrophes&quot; just by spending a little bit more time on building up common understanding.</p><p>Communicating &quot;models&quot; that we might &quot;have&quot; in our minds, so that we can actually work together as we &quot;see things in the same way&quot;.</p><p>Considering not all people are on the same page, can we really conclude we work together?</p><p>I mean, physically it looks like we do, but a lot of the work is done on the symbolic, abstract level, which is not visible to the naked eye.</p><p>Wouldn&#x27;t it be a decent idea to <a href="https://talesfrom.dev/blog/slow-down">slow down</a> a little bit, in order to speed up later - thanks to the overmind we create when we work together (you mind find it interesting to read <a href="https://talesfrom.dev/blog/the-ambiguity-of-team-work">The ambiguity of team work</a> as well).</p><p>That is also one of the core ideas communicated through DDD (Domain-Driven Design) Strategic Design - Ubiquitous Language.</p><p>Let the model represents the language we use.</p><p>Let us use the same language when talking about the problem.</p><h3 id="making-collaboration-easier"><a href="#making-collaboration-easier" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Making collaboration easier</h3><p>So how to make collaboration easier?</p><p><strong>Assume that acronyms might be not understood by everyone.</strong> If you can, visualize them or briefly explain them.</p><p><strong>Ensure that all questions are welcomed by saying that people should ask whenever they feel lost.</strong> This will help you to create a safe environment in which people can ask questions without feeling ashamed.</p><p><strong>When talking about ideas and abstract concepts, visualize them or/and explain them using examples.</strong> Not everyone is capable of grasping abstract ideas easily and examples might be really helpful.</p><p><strong>Make your voice feel welcoming and respectful.</strong> You might not be aware of it, but your tone might indicate that you are not open to questions and discussions.</p><p>Tough, isn&#x27;t it?</p><p>Of course dear Reader, I am suggesting you to do all of the above (depending on the context, of course!).</p><p>&quot;Just sayin&#x27;&quot;.</p><h3 id="saboteurs"><a href="#saboteurs" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Saboteurs?</h3><p>Note dear Reader that all of the tips from the previous section assume people in general have positive intentions.</p><p>Of course, as the world is wide and full of different people, there are also those who might not have the best intentions.</p><p>Some of the human beings might try exploit openness, transparency and willingness to help others.</p><p>It is hard to prevent such behaviours.</p><p>But based on my experience, most of the people are willing to help and collaborate.</p><p>Light defeats darkness.</p><p>Love defeats hate.</p><h3 id="dont-talk-about-invisible-things"><a href="#dont-talk-about-invisible-things" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Don&#x27;t talk about invisible things</h3><p>One of the core principles to have in mind when designing systems is that we design them <a href="https://talesfrom.dev/blog/systems-by-with-for-people">by/with/for people</a>.</p><p>Almost on every step and level of abstraction, there is a human being that is involved in the process of growing the system.</p><p>This means we need to put empathy in the first place.</p><p>Next time dear Reader, when designing a presentation or showing anything to other people, at the beginning of the meeting, say it aloud in the calm way:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>The main goal is to build common understanding. I might use some acronyms and jargon, so please stop me if you don&#x27;t understand something. I will be happy to explain it to you.</p></div></div></div>]]></content:encoded>
    <pubDate>Sat, 31 May 2025 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>language patterns</category><category>communication</category><category>collaboration</category><category>shared understanding</category><category>software teaming</category><category>working together</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/composing-a-pie</guid>
    <title>Composing a PIE</title>
    <link>https://talesfrom.dev/blog/composing-a-pie</link>
    <description>Is there a universal way of composing things?</description>
    <content:encoded><![CDATA[<h3 id="have-you-ordered-a-burger"><a href="#have-you-ordered-a-burger" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Have you ordered a burger?&quot;</h3><p>Imagine that there&#x27;s a person, who owns a foodtruck, and sells the best burgers in town.</p><p>The secret is how they prepare burgers and how they prepare sauce, invented by the founder.</p><p>The main purpose is to let the owner to grill the meat and keep the sauce secret always available.</p><p>To do so, the owner decided to hire a person that will be responsible for taking orders and deliverying burgers when they are ready.</p><p>Another role in the process is responsible for ensuring buns are ready, ensuring other ingredients are available (like lettuce, tomato, etc) and finally assembling the burger.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/composing-a-pie-foodtruck.png" class="max-h-[24rem]"/></div><div class="italic mx-24">Foodtruck crew collaborating to bring the best burgers</div></div><p>There are many interactions between each role to serve the customer.</p><p>A customer initiaties the dialog by ordering a burger (1), the person responsible for taking orders passes (2) the relevant details to the owner that knows all the secrets behind the best experience, which then passes (3) the work to the role that assemblies the final product. Then the product is passed (4) to the person responsible for taking orders, who then delivers (5) the burger to the customer.</p><p>The purpose is easily achieved - serving the best burger experience to the customer by organizing the collaboration in such a way that the owner focuses on the secret sauce and secret way of grilling the meat.</p><p>But change, change never changes...</p><h3 id="too-many-orders"><a href="#too-many-orders" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Too many orders!&quot;</h3><p>Too many orders are coming in, and the role responsible for assembling the final product is a bit overwhelmed.</p><p>All takes much more time, brings more cognitive load - customer experience is not as good as it used to be.</p><p>The owner is not happy about that which also impacts creating secret sauce and grilling the meat.</p><p>The decision is made - a former role responsible for both ensuring all other ingredients are available and assembling the final product is split into two roles.</p><p>This of course, impacts the whole process and the way the roles interact with each other.</p><p>This work is done in order to support the new purpose - serving more orders, decreasing the cognitive load and making the owner happy again.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/composing-a-pie-foodtruck-split.png" class="max-h-[24rem]"/></div><div class="italic mx-24">The way of organizing the work to support newly emerged goals</div></div><p>Now, after the way of organizing the work is changed, goals were easily achieved!</p><p>Initiating (1) and finalizing (5) interactions remained stable and unchanged - but the customer is not aware of that - which of course is a good thing.</p><p>Contrary to that, the role responsible for taking orders passes the details (2) in parallel to the owner and to the role responsible for ensuring all ingredients are available. When both roles finish their work, they pass (3) the results to the role responsible for assembling the final product. Then the final product - burger - is passed (4) to the person responsible for communication with the customer.</p><p>Concluding, roles and interactions got organized to support purposes defined by the owner of the foodtruck.</p><p>&quot;New&quot; (communication) structure emerged as there were new conditions that the foodtruck crew started facing.</p><h3 id="have-you-ordered-a-processing"><a href="#have-you-ordered-a-processing" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Have you ordered a processing?&quot;</h3><p>Now, imagine that we are doing data processing by using a few, distributed services.</p><p>The organization of work got hidden behind the API Gateway in order to have ability to change how the results are produced.</p><p>Ah, finally microservices! (please tell me you know I am joking, dear Reader!)</p><p>They have a bunch of interactions (2, 3, 4) between each other - each service is responsible for a specific part of the process. The communication (1) is initiated by a consumer with the API Gateway and the result is delivered (5) through it too.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/composing-a-pie-services.png" class="max-h-[24rem]"/></div><div class="italic mx-24">A consumer interacting with a module, hiding the details.</div></div><p>Service B interacts with service C in a sequential manner, as the service C requires the byproduct of service B to do its work.</p><p>But change, change never changes...</p><h3 id="too-many-responsibilities"><a href="#too-many-responsibilities" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Too many responsibilities!&quot;</h3><p>Service C is quite overwhelmed with the amount of work it has to do.</p><p>CPU, RAM and other resources are not enough to handle the load.</p><p>But the biggest problem is that the services C changes too often, which impacts the whole process.</p><p>There are multiple reasons for it to change, which makes the whole value delivery chain a bit fragile.</p><p>A new goal emerged - we need to reduce the cognitive load of service C, so it can focus on its main purpose and be more stable.</p><p>This of course makes maintenance easier too.</p><p>The decision is made - a part of responsibilities of service C will be moved to a new service D - which will be responsible for a specific part of the process.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/composing-a-pie-services-split.png" class="max-h-[24rem]"/></div><div class="italic mx-24">The way of organizing the work to support newly emerged goals</div></div><p>Introduction of service D changes the process but the consumer is not aware of that. Initiating (1) and finalizing (5) interactions remain stable and unchanged.</p><p>Then service A dispatches (2) the work to services B and services C. After they both finish their work, they pass (3) the results to service D, which then passes back (4) the final result to the service A.</p><p>As new expectations emerged, the way we organized interactions between services changed to support them.</p><p>Great that we designed at least some boundaries!</p><h3 id="have-you-ordered-a-computation"><a href="#have-you-ordered-a-computation" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Have you ordered a computation?&quot;</h3><p>Let&#x27;s take another example, this time with object-oriented design.</p><p>There is an interface that a consumer uses to interact with a module. There&#x27;s an object A that implements one of the capabilities promised by &quot;the interface&quot;. This capability has a specific contract that the object A has to fulfill in order to accept the request (1) and provide the result (5).</p><p>Internally, object A interacts (2) with object B, which then interacts (3) with object C to do its work. When object C finishes its work, it passes (4) the result back to object B, which then passes it back to object A.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/composing-a-pie-objects.png" class="max-h-[24rem]"/></div><div class="italic mx-24">A consumer interacting with a module, hiding the details.</div></div><p>Everything works great so far.</p><p>The purpose is easily achieved - the consumer gets what was promised by the capability provided by the object A.</p><p>But change, change never changes...</p><h3 id="too-many-responsibilities-1"><a href="#too-many-responsibilities-1" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Too many responsibilities!&quot;</h3><p>Object C is quite overwhelmed with the amount of work it has to do.</p><p>Turns out that the it&#x27;s quite hard and complex to understand the details of the object C, which makes the maintenance a little bit harder.</p><p>Also, this causes tests to be hard to write, hard to read and hard to evolve.</p><p>A new goal emerged - we need to reduce &quot;the complexity&quot; of object C, so it can focus on its main purpose and be more stable.</p><p>This will reduce the &quot;cognitive load&quot; of designers, maintainers and engineers too.</p><p>The decision is made - a part of responsibilities of object C will be moved to a new object D - which will be responsible for a specific part of the process.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/composing-a-pie-objects-split.png" class="max-h-[24rem]"/></div><div class="italic mx-24">The way of organizing the work to support newly emerged goals</div></div><p>Now, object A dispatches (2) the work to objects B and C. After they both finish their work, they pass (3) the results to object D, which then passes back (4) the final result to the object A.</p><p>The contract remained the same and all consumers didn&#x27;t see a difference.</p><p>Good that we had boundaries!</p><h3 id="a-pattern"><a href="#a-pattern" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>A pattern?</h3><p>You might be wondering, dear Reader, what the hell I want to express through those examples? (I really hope you do wonder, dear Reader!)</p><p>Turns out that there is a common plane for all of those tiny scenarios - even though it might not be that obvious at first glance.</p><p>In each of them, we experienced initial purpose(s) and evolution through time.</p><p>The evolution made the organization (of work, of interactions) to be changed to support those new goals.</p><p>This was the driving force that required the structure (of communication) to be adjusted.</p><p>Also, without boundaries, it would be enormously difficult to do any re-organization as consumers/customers would be affected by the change.</p><p>Of course, this isn&#x27;t always possible to not break the contract, but as we saw, in those examples, we were able to observe so.</p><p>So a bunch of <strong>&quot;elements&quot;</strong> (roles, services, objects) <strong>interacted</strong> with each other to achieve a <strong>purpose</strong> &quot;greater&quot; than themvelves.</p><p>Then, a new, desired capability emerged, deliverying the value, defined by the goal.</p><h3 id="pie"><a href="#pie" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>PIE?</h3><p>One could say that everything starts with a <strong>purpose</strong>.</p><p>It defines the scope, the boundary in which we are going to operate, trying to find the way of acheving it (the &quot;how&quot;).</p><p>When it is specified, we can think of the <strong>interactions</strong> that appear to be on the boundaries of &quot;an organization&quot;.</p><p>And let &quot;an organization&quot; be a set of roles that human play, a set of services or a web of objects - &quot;it does not matter&quot;.</p><p>&quot;It does not matter&quot; means that a context exists in which all of them might be thought of as &quot;same&quot;.</p><p>One can easily raise the level of abstraction and think of roles/services/objects as <strong>elements</strong>.</p><p>&quot;A piece of reductionist&quot;, you might say, dear Reader.</p><p>Yes, indeed.</p><p>But at the same time, &quot;all models are wrong (=imperfect), but some are useful&quot;, as the great saying from George Box goes.</p><p>This gives us certain model to use while thinking!</p><p>Then, composing <strong>interactions</strong> between <strong>elements</strong> enables the expected behavior (the expected capability) to emerge to achieve the <strong>purpose</strong>.</p><p><strong>P</strong>urpose, <strong>I</strong>nteractions, <strong>E</strong>lements.</p><p>PIE.</p><h3 id="composing-a-pie"><a href="#composing-a-pie" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Composing a PIE</h3><p>There are recurring tides when people bash object-oriented programming that is ineffective, full of boilerplate and leads to a lot of complexity.</p><p>Which might be true, when one focuses on the structure, on the elements themselves.</p><p>As we already discussed in <a href="https://talesfrom.dev/blog/the-ambiguity-of-objects">The ambiguity of objects</a>, there might be a great misunderstanding of the tools we are using.</p><p>This leads to brittleness, complexity and other problems.</p><p>In fact, we could think of our job to design interactions first.</p><p>Interactions driven by the purpose we want to achieve (you might be interested in <a href="https://talesfrom.dev/blog/the-ambiguity-of-software-architecture">The ambiguity of software architecture</a> post too).</p><p>Eventually, &quot;elements&quot; (also known as components, modules, etc.) will be required to deliver needed capabilities to achieve the purpose.</p><p>But it all starts with the purpose.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>A system&#x27;s capability to fulfill its <strong>P</strong>urpose emerges from <strong>I</strong>nteractions between <strong>E</strong>lements.</p></div></div></div><p>Even though we are abstracting away the details, we use reductionist approach, it might still be useful.</p><p>As we saw, thinking in PIE terms appears on various levels: organizing the work of human beings, organizing the communication between services or designing how objects collaborate with each other.</p><p>One could easily point at one of the greatest books on software design (in my humble opinion), <a href="https://www.amazon.com/Balancing-Coupling-Software-Design-Addison-Wesley-ebook/dp/B09RV3Z3TP">Balancing Coupling</a> by <a href="https://vladikk.com/">Vlad Khononov</a> where a concept of &quot;Fractal Design&quot; is mentioned.</p><p>This is exactly what I am trying to express here - the same principles apply on different levels of abstraction.</p><p>And by incorporating &quot;PIE&quot; thinking, we can consciously design our systems - not focusing too much on the structure (for sure not at the beginning of the designing process!).</p><p>There is a great maxim, which originated in architecture (not software!) and industrial design, that goes like this:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Form follows function.</p></div></div></div><p>Which means that the structure of a system should follow the purpose it is designed for.</p><p>The communication structure (form) between elements should follow the purpose (function) of the system.</p><p>As designers, we don&#x27;t know what elements will play required roles in the system, but we must understand the purpose and interactions that will be required to achieve it.</p><p>When I say &quot;interactions&quot;, it might mean &quot;capabilities provided by certain roles&quot;.</p><p>Those capabilities might be located in a monolith, in a set of distributed services - it is not specified at this point.</p><p>How we would organize it all, vastly depends on a variety of forces, appearing in the context we are operating in.</p><p>&quot;Ah, you like talking about abstract stuff Damian, ain&#x27;t you?&quot;, you might say, dear Reader.</p><p>But it all boils down to focusing on the behavior and specifying it firstly, from he Outside-In (consumer) perspective.</p><p>We can specify the behavior through Event Storming notation, through Open API Specification or through tests (you might find <a href="https://talesfrom.dev/blog/the-ambiguity-of-tdd">The ambiguity of TDD</a> interesting).</p><p>By looking from the usage, from the consumer&#x27;s perspective, we can define specify contracts (&quot;shape&quot;) and protocols (the way of interacting with it).</p><p>So depending on the abstraction level we are designing, it can be an object&#x27;s method, an actors&#x27; message handler, a service&#x27;s entrypoint (e.g. HTTP endpoint), etc.</p><p>But what is it all about?</p><h3 id="change-change-never-changes"><a href="#change-change-never-changes" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Change, change never changes</h3><p>Do you want to be a great architect?</p><p>Think about the purpose first - &quot;what is the main problem we want to solve right now?&quot;.</p><p>Knowing what, you can think of how to achieve it.</p><p>What capabilities would need to be there to achieve the desired goal?</p><p>Also, it&#x27;s not a coincidence that <strong>P</strong>urpose in &quot;PIE model&quot; is the first letter.</p><p>Its job is to remind us all the time that the purpose (answers to <strong>what?</strong> and <strong>why?</strong>) must be clearly defined, or at least understood, before we start jumping into the solution (answers to <strong>how?</strong>).</p><p>Then we have <strong>I</strong>nteraction on the second place, which should remind us that the communication structure (protocols) between elements always follow the purpose.</p><p>Finally, we have <strong>E</strong>lements, which will take part in the interactions and provide required capabilities.</p><p>Those elements might be human beings, services, actors, objects, enterprises, teams, and so on.</p><p>As you might probably noticed, dear Reader, one inevitable fact that appeared in each example was the change.</p><p>The change that was triggered by the redefinition of the purpose or totally new purposes appearing.</p><p>To be able to respond to a change (responding to a change? You might be interested in <a href="https://talesfrom.dev/blog/fragile">(Fr)Agile</a>), we need to have boundaries.</p><p>Boundaries that encapsulate the details of interactions between elements so that we can reshape the structure of communication without breaking the contract (at least trying to avoid it).</p><p>Thanks to boundaries, we can evolve our systems - whether they are collaborating humans, interacting distributed services or actors/objects sending messages to each other.</p><p>Next time dear Reader, when you will be designing a part of a system, think about the purpose first and remember that:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>What you hide, you can change.</p></div></div></div>]]></content:encoded>
    <pubDate>Sat, 24 May 2025 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>software design</category><category>software architecture</category><category>interaction-oriented design</category><category>actor model</category><category>object-oriented design</category><category>interfaces</category><category>interface-oriented design</category><category>patterns</category><category>language patterns</category><category>domain-driven design</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/functions-objects-actors-deliverying-results</guid>
    <title>Functions, objects, actors: deliverying results</title>
    <link>https://talesfrom.dev/blog/functions-objects-actors-deliverying-results</link>
    <description>Is there a single way of yielding results?</description>
    <content:encoded><![CDATA[<div class="bg-slate-600 rounded-xl mt-10"><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Kudos! 🙏🏻</span></div><div class="pb-2 px-3"><div class="break-words"><p>This tale wouldn&#x27;t be here if I didn&#x27;t have conversations with <a href="https://twitter.com/GGalezowski">Grzegorz Galezowski</a>.</p>
<p>Thanks <a href="https://twitter.com/GGalezowski">Grzegorz Galezowski</a> for your patience, your knowledge and sharing your experience with me!</p>
<p>This blog post is full of reflections after reading the <a href="https://x.com/GGalezowski/status/1907118665276756131">discussion</a> between Grzegorz and <a href="https://x.com/ploeh">Mark Seeman</a></p></div></div></div> <div class="bg-slate-600 rounded-xl mt-10"><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>The goal</span></div><div class="pb-2 px-3"><div class="break-words"><p>The intent of this blog post is to show that there are multiple ways of yielding results in our systems.</p>
<p><a href="https://twitter.com/GGalezowski">Grzegorz</a> presented very interesting <a href="https://github.com/grzesiek-galezowski/TrainingExamples/blob/master/CSharp/WeatherAppLogicSeparation/Application/SubscribeCommand.cs">approach</a> on using Command design pattern - I totally recommend exploring it!</p></div></div></div><h3 id="an-assignment"><a href="#an-assignment" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>An assignment</h3><p>Imagine that we were challenged with implementing a simple use case in our system - an intent to assign a worker to a specific assignment.</p><p>Initially, we know that this use case is going to be realized using HTTP API, which means that our ASP.NET Core Minimal API handler or Controller&#x27;s action method will be the entrypoint to our application.</p><p>The knowledge we are going to apply is the following:</p><ol><li>A consumer requests assigning someone to an assignment with given identifier.</li><li>The system is going to fetch the first available worker.</li><li>A specific assignment is loaded.</li><li>The worker is assigned.</li><li>The assignment result is returned to the consumer.</li></ol><p>Straightforward, right?</p><p>(you might be wondering what do I meanby &quot;the knowledge we are going to apply&quot; - you might be interested in <a href="https://talesfrom.dev/blog/the-ambiguity-of-application">The ambiguity of application</a>)</p><p>We defined inputs (the assignment identifier), the processing steps (2-4) and the output (the assignment result).</p><p>Let&#x27;s try to implement it using one of the most common approaches - command handler returning a result.</p><h3 id="command-handler-returning-a-result"><a href="#command-handler-returning-a-result" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Command handler returning a result</h3><p>Let&#x27;s start from the outside-in perspective - so the entrypoint to our system - an HTTP Minimal API handler - anonymous lambda.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line">app<span class="token punctuation">.</span><span class="token function">MapPost</span><span class="token punctuation">(</span><span class="token string">&quot;/assignments/{assignmentId:guid}/assign&quot;</span><span class="token punctuation">,</span> <span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token class-name">Guid</span> assignmentId<span class="token punctuation">,</span> <span class="token class-name">IDispatchCommands</span> dispatcher<span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> result <span class="token operator">=</span> <span class="token keyword">await</span> dispatcher<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Dispatch</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>AssignWorkerCommand<span class="token punctuation">,</span> AssignmentResult<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name constructor-invocation">AssignWorkerCommand</span><span class="token punctuation">(</span>assignmentId<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">return</span> result<span class="token punctuation">.</span><span class="token function">Match</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// ❌ bzzz, compile-time error - what should we supposed to match?</span>
</span><span class="code-line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre></div></div><p>In our initial behavior specification (specification? you might be interested in <a href="https://talesfrom.dev/blog/the-ambiguity-of-tdd">The ambiguity of &quot;TDD&quot;</a>) we covered the happy path. We have not describe what results do we expect when things go wrong.</p><p>Let&#x27;s say our process experts told us that we have three failure scenarios:</p><ul><li>there is no workers available</li><li>assignment has already assigned worker</li><li>a worker is not qualified to do a given assignment</li></ul><p>So we can represent this knowledge in the code:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line">app<span class="token punctuation">.</span><span class="token function">MapPost</span><span class="token punctuation">(</span><span class="token string">&quot;/assignments/{assignmentId:guid}/assign&quot;</span><span class="token punctuation">,</span> <span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token class-name">Guid</span> assignmentId<span class="token punctuation">,</span> <span class="token class-name">IDispatchCommands</span> dispatcher<span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> result <span class="token operator">=</span> <span class="token keyword">await</span> dispatcher<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Dispatch</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>AssignWorkerCommand<span class="token punctuation">,</span> AssignmentResult<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name constructor-invocation">AssignWorkerCommand</span><span class="token punctuation">(</span>assignmentId<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">return</span> result<span class="token punctuation">.</span><span class="token function">Match</span><span class="token punctuation">(</span> <span class="token comment">// ❌ bzzz, compile-time error - don&#x27;t we need to implement it?</span>
</span><span class="code-line">        successfullyAssigned<span class="token punctuation">:</span> assignmentResult <span class="token operator">=&gt;</span> Results<span class="token punctuation">.</span><span class="token function">Ok</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token punctuation">{</span> assignedWorkerId <span class="token operator">=</span> assignmentResult<span class="token punctuation">.</span>WorkerId <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token punctuation named-parameter">noWorkersAvailable</span><span class="token punctuation">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> Results<span class="token punctuation">.</span><span class="token function">UnprocessableEntity</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token punctuation">{</span> message <span class="token operator">=</span> <span class="token string">&quot;No workers available&quot;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token punctuation named-parameter">alreadyAssigned</span><span class="token punctuation">:</span> assignmentResult <span class="token operator">=&gt;</span> Results<span class="token punctuation">.</span><span class="token function">Conflict</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token punctuation">{</span> message <span class="token operator">=</span> <span class="token string">&quot;Assignment already has assigned worker&quot;</span><span class="token punctuation">,</span> error <span class="token operator">=</span> <span class="token string">&quot;assignments:assigning:no-workers-available&quot;</span><span class="token punctuation">,</span> alreadyWorkerId <span class="token operator">=</span> assignmentResult<span class="token punctuation">.</span>WorkerId <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token punctuation named-parameter">notQualified</span><span class="token punctuation">:</span> assignmentResult <span class="token operator">=&gt;</span> Results<span class="token punctuation">.</span><span class="token function">UnprocessableEntity</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token punctuation">{</span> message <span class="token operator">=</span> <span class="token string">&quot;Worker is not qualified to do this assignment&quot;</span><span class="token punctuation">,</span> error <span class="token operator">=</span> <span class="token string">&quot;assignments:assigning:worker-not-qualified&quot;</span><span class="token punctuation">,</span> unqualifiedWorkerId <span class="token operator">=</span> assignmentResult<span class="token punctuation">.</span>WorkerId <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token punctuation named-parameter">otherError</span><span class="token punctuation">:</span> message <span class="token operator">=&gt;</span> Results<span class="token punctuation">.</span><span class="token function">UnprocessableEntity</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token punctuation">{</span> message <span class="token operator">=</span> message<span class="token punctuation">;</span> error <span class="token operator">=</span> <span class="token string">&quot;assignments:assigning:other-error&quot;</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre></div></div><p>We are engineers, so we know there the default set of errors to handle - &quot;other errors&quot; - ones we don&#x27;t know how to deal with.</p><p>Let&#x27;s put a error bag for these.</p><p>Our HTTP interaction handler uses the returned result from processing.</p><p>Of course, nothing yet was implemented, so let&#x27;s move on!</p><h3 id="lets-return-a-processing-result"><a href="#lets-return-a-processing-result" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Let&#x27;s return a processing result!</h3><p>Let&#x27;s define inputs and outputs:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token comment">// the input - the command as data</span>
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">record</span> <span class="token class-name">AssignWorkerCommand</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> AssignmentId<span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">ICommand</span></span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token comment">// the output - the value object as the result of processing</span>
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">abstract</span> <span class="token keyword">record</span> <span class="token class-name">AssignmentResult</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">abstract</span> <span class="token class-name return-type">TResult</span> <span class="token generic-method"><span class="token function">Match</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>TReturn<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token class-name">Func<span class="token punctuation">&lt;</span>AssignmentResult<span class="token punctuation">,</span> TReturn<span class="token punctuation">&gt;</span></span> successfullyAssigned<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">Func<span class="token punctuation">&lt;</span>TReturn<span class="token punctuation">&gt;</span></span> noWorkersAvailable<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">Func<span class="token punctuation">&lt;</span>AssignmentResult<span class="token punctuation">,</span> TReturn<span class="token punctuation">&gt;</span></span> alreadyAssigned<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">Func<span class="token punctuation">&lt;</span>AssignmentResult<span class="token punctuation">,</span> TReturn<span class="token punctuation">&gt;</span></span> notQualified<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">Func<span class="token punctuation">&lt;</span><span class="token keyword">string</span><span class="token punctuation">,</span> TReturn<span class="token punctuation">&gt;</span></span> otherError    
</span><span class="code-line">    <span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">sealed</span> <span class="token keyword">record</span> <span class="token class-name">SuccessfullyAssigned</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> WorkerId<span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">AssignmentResult</span></span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">public</span> <span class="token keyword">override</span> <span class="token class-name return-type">TResult</span> <span class="token generic-method"><span class="token function">Match</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>TReturn<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span>
</span><span class="code-line">            <span class="token class-name">Func<span class="token punctuation">&lt;</span>AssignmentResult<span class="token punctuation">,</span> TReturn<span class="token punctuation">&gt;</span></span> successfullyAssigned<span class="token punctuation">,</span>
</span><span class="code-line">            <span class="token class-name">Func<span class="token punctuation">&lt;</span>TReturn<span class="token punctuation">&gt;</span></span> noWorkersAvailable<span class="token punctuation">,</span>
</span><span class="code-line">            <span class="token class-name">Func<span class="token punctuation">&lt;</span>AssignmentResult<span class="token punctuation">,</span> TReturn<span class="token punctuation">&gt;</span></span> alreadyAssigned<span class="token punctuation">,</span>
</span><span class="code-line">            <span class="token class-name">Func<span class="token punctuation">&lt;</span>AssignmentResult<span class="token punctuation">,</span> TReturn<span class="token punctuation">&gt;</span></span> notQualified<span class="token punctuation">,</span>
</span><span class="code-line">            <span class="token class-name">Func<span class="token punctuation">&lt;</span><span class="token keyword">string</span><span class="token punctuation">,</span> TReturn<span class="token punctuation">&gt;</span></span> otherError
</span><span class="code-line">        <span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">return</span> <span class="token function">successfullyAssigned</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">sealed</span> <span class="token keyword">record</span> <span class="token class-name">NoWorkersAvailable</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">AssignmentResult</span></span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">public</span> <span class="token keyword">override</span> <span class="token class-name return-type">TResult</span> <span class="token generic-method"><span class="token function">Match</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>TReturn<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span>
</span><span class="code-line">            <span class="token class-name">Func<span class="token punctuation">&lt;</span>AssignmentResult<span class="token punctuation">,</span> TReturn<span class="token punctuation">&gt;</span></span> successfullyAssigned<span class="token punctuation">,</span>
</span><span class="code-line">            <span class="token class-name">Func<span class="token punctuation">&lt;</span>TReturn<span class="token punctuation">&gt;</span></span> noWorkersAvailable<span class="token punctuation">,</span>
</span><span class="code-line">            <span class="token class-name">Func<span class="token punctuation">&lt;</span>AssignmentResult<span class="token punctuation">,</span> TReturn<span class="token punctuation">&gt;</span></span> alreadyAssigned<span class="token punctuation">,</span>
</span><span class="code-line">            <span class="token class-name">Func<span class="token punctuation">&lt;</span>AssignmentResult<span class="token punctuation">,</span> TReturn<span class="token punctuation">&gt;</span></span> notQualified<span class="token punctuation">,</span>
</span><span class="code-line">            <span class="token class-name">Func<span class="token punctuation">&lt;</span><span class="token keyword">string</span><span class="token punctuation">,</span> TReturn<span class="token punctuation">&gt;</span></span> otherError    
</span><span class="code-line">        <span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">return</span> <span class="token function">noWorkersAvailable</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">sealed</span> <span class="token keyword">record</span> <span class="token class-name">AlreadyAssigned</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> WorkerId<span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">AssignmentResult</span></span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">public</span> <span class="token keyword">override</span> <span class="token class-name return-type">TResult</span> <span class="token generic-method"><span class="token function">Match</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>TReturn<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span>
</span><span class="code-line">            <span class="token class-name">Func<span class="token punctuation">&lt;</span>AssignmentResult<span class="token punctuation">,</span> TReturn<span class="token punctuation">&gt;</span></span> successfullyAssigned<span class="token punctuation">,</span>
</span><span class="code-line">            <span class="token class-name">Func<span class="token punctuation">&lt;</span>TReturn<span class="token punctuation">&gt;</span></span> noWorkersAvailable<span class="token punctuation">,</span>
</span><span class="code-line">            <span class="token class-name">Func<span class="token punctuation">&lt;</span>AssignmentResult<span class="token punctuation">,</span> TReturn<span class="token punctuation">&gt;</span></span> alreadyAssigned<span class="token punctuation">,</span>
</span><span class="code-line">            <span class="token class-name">Func<span class="token punctuation">&lt;</span>AssignmentResult<span class="token punctuation">,</span> TReturn<span class="token punctuation">&gt;</span></span> notQualified<span class="token punctuation">,</span>
</span><span class="code-line">            <span class="token class-name">Func<span class="token punctuation">&lt;</span><span class="token keyword">string</span><span class="token punctuation">,</span> TReturn<span class="token punctuation">&gt;</span></span> otherError
</span><span class="code-line">        <span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">return</span> <span class="token function">alreadyAssigned</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">sealed</span> <span class="token keyword">record</span> <span class="token class-name">WorkerNotQualified</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> WorkerId<span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">AssignmentResult</span></span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">public</span> <span class="token keyword">override</span> <span class="token class-name return-type">TResult</span> <span class="token generic-method"><span class="token function">Match</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>TReturn<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span>
</span><span class="code-line">            <span class="token class-name">Func<span class="token punctuation">&lt;</span>AssignmentResult<span class="token punctuation">,</span> TReturn<span class="token punctuation">&gt;</span></span> successfullyAssigned<span class="token punctuation">,</span>
</span><span class="code-line">            <span class="token class-name">Func<span class="token punctuation">&lt;</span>TReturn<span class="token punctuation">&gt;</span></span> noWorkersAvailable<span class="token punctuation">,</span>
</span><span class="code-line">            <span class="token class-name">Func<span class="token punctuation">&lt;</span>AssignmentResult<span class="token punctuation">,</span> TReturn<span class="token punctuation">&gt;</span></span> alreadyAssigned<span class="token punctuation">,</span>
</span><span class="code-line">            <span class="token class-name">Func<span class="token punctuation">&lt;</span>AssignmentResult<span class="token punctuation">,</span> TReturn<span class="token punctuation">&gt;</span></span> notQualified<span class="token punctuation">,</span>
</span><span class="code-line">            <span class="token class-name">Func<span class="token punctuation">&lt;</span><span class="token keyword">string</span><span class="token punctuation">,</span> TReturn<span class="token punctuation">&gt;</span></span> otherError
</span><span class="code-line">        <span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">return</span> <span class="token function">notQualified</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">sealed</span> <span class="token keyword">record</span> <span class="token class-name">OtherError</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> errorMessage<span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">AssignmentResult</span></span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">public</span> <span class="token keyword">override</span> <span class="token class-name return-type">TResult</span> <span class="token generic-method"><span class="token function">Match</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>TReturn<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span>
</span><span class="code-line">            <span class="token class-name">Func<span class="token punctuation">&lt;</span>AssignmentResult<span class="token punctuation">,</span> TReturn<span class="token punctuation">&gt;</span></span> successfullyAssigned<span class="token punctuation">,</span>
</span><span class="code-line">            <span class="token class-name">Func<span class="token punctuation">&lt;</span>TReturn<span class="token punctuation">&gt;</span></span> noWorkersAvailable<span class="token punctuation">,</span>
</span><span class="code-line">            <span class="token class-name">Func<span class="token punctuation">&lt;</span>AssignmentResult<span class="token punctuation">,</span> TReturn<span class="token punctuation">&gt;</span></span> alreadyAssigned<span class="token punctuation">,</span>
</span><span class="code-line">            <span class="token class-name">Func<span class="token punctuation">&lt;</span>AssignmentResult<span class="token punctuation">,</span> TReturn<span class="token punctuation">&gt;</span></span> notQualified<span class="token punctuation">,</span>
</span><span class="code-line">            <span class="token class-name">Func<span class="token punctuation">&lt;</span><span class="token keyword">string</span><span class="token punctuation">,</span> TReturn<span class="token punctuation">&gt;</span></span> otherError
</span><span class="code-line">        <span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">return</span> <span class="token function">otherError</span><span class="token punctuation">(</span>errorMessage<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Ok, it got a bit verbose, but we have a clear structure of our processing result.</p><p>We expressed a common, abstract concept for &quot;assignment result&quot; and we have a concrete implementations of it, covering variability of cases.</p><p>I hear you dear Reader: &quot;omg, so much boilerplate&quot; and it&#x27;s true, not denying it.</p><p>We could of course use <a href="https://www.nuget.org/packages/OneOf">OneOf</a> nuget package for discriminated unions, but let&#x27;s imagine we decided to go with dependency-free approach that is built in the language we use.</p><h3 id="processing-knowledge-application"><a href="#processing-knowledge-application" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Processing knowledge application</h3><p>Now it&#x27;s time to build command handler - an application of the process steps we got familiar with.</p><p>One of them was: &quot;2. The system is going to fetch the first available worker.&quot;</p><p>We don&#x27;t care <strong>how</strong> this capability is going to be delivered, we focus on <strong>what</strong> instead - to do so we defined the responsibility: (responsibility? you might be interested in <a href="https://talesfrom.dev/blog/the-ambiguity-of-interfaces">The ambiguity of interfaces</a>)</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">IProvideWorker</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>Maybe<span class="token punctuation">&lt;</span>Worker<span class="token punctuation">&gt;</span><span class="token punctuation">&gt;</span></span> <span class="token function">ProvideWorker</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Our command processor requires capabilities for loading and saving assignments, so let&#x27;s express them bound to a specific role:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">IAssignmentRepository</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>Maybe<span class="token punctuation">&lt;</span>Assignment<span class="token punctuation">&gt;</span><span class="token punctuation">&gt;</span></span> <span class="token function">Load</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> assignmentId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">Task</span> <span class="token function">Save</span><span class="token punctuation">(</span><span class="token class-name">Assignment</span> assignment<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Equipped with those capabilities, we are ready to represent our understanding using code:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">record</span> <span class="token class-name">AssignWorkerCommandHandler</span><span class="token punctuation">(</span><span class="token class-name">IProvideWorker</span> workerProvider<span class="token punctuation">,</span> <span class="token class-name">IAssignmentRepository</span> assignmentRepository<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">ICommandHandler<span class="token punctuation">&lt;</span>AssignWorkerCommand<span class="token punctuation">,</span> AssignmentResult<span class="token punctuation">&gt;</span></span></span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>AssignmentResult<span class="token punctuation">&gt;</span></span> <span class="token function">Handle</span><span class="token punctuation">(</span><span class="token class-name">AssignWorkerCommand</span> command<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">try</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token class-name"><span class="token keyword">var</span></span> worker <span class="token operator">=</span> <span class="token keyword">await</span> workerProvider<span class="token punctuation">.</span><span class="token function">ProvideWorker</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span>worker<span class="token punctuation">.</span>HasValue<span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token punctuation">{</span>
</span><span class="code-line">                <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">AssignmentResult<span class="token punctuation">.</span>NoWorkersAvailable</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token punctuation">}</span>
</span><span class="code-line">            <span class="token class-name"><span class="token keyword">var</span></span> assignment <span class="token operator">=</span> <span class="token keyword">await</span> assignmentRepository<span class="token punctuation">.</span><span class="token function">Load</span><span class="token punctuation">(</span>command<span class="token punctuation">.</span>AssignmentId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span>assignment<span class="token punctuation">.</span>HasValue<span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token punctuation">{</span>
</span><span class="code-line">                <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">AssignmentResult<span class="token punctuation">.</span>OtherError</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;No assignment with id </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token language-csharp expression">command<span class="token punctuation">.</span>AssignmentId</span><span class="token punctuation">}</span></span><span class="token string"> is available.&quot;</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">            assignment<span class="token punctuation">.</span><span class="token function">Assign</span><span class="token punctuation">(</span>worker<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">            <span class="token keyword">await</span> assignmentRepository<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>assignment<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">            <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">AssignmentResult<span class="token punctuation">.</span>SuccessfullyAssigned</span><span class="token punctuation">(</span>worker<span class="token punctuation">.</span>Id<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">        <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">WorkerAlreadyAssigned</span> ex<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">AssignmentResult<span class="token punctuation">.</span>WorkerAlreadyAssigned</span><span class="token punctuation">(</span>worker<span class="token punctuation">.</span>Id<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">        <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">WorkerNotQualifiedForAssignment</span> ex<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">AssignmentResult<span class="token punctuation">.</span>WorkerNotQualified</span><span class="token punctuation">(</span>worker<span class="token punctuation">.</span>Id<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">        <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Exception</span> ex<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">AssignmentResult<span class="token punctuation">.</span>OtherError</span><span class="token punctuation">(</span>ex<span class="token punctuation">.</span>Message<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>(not sure if you noticed, dear Reader, but I used a defensive, &quot;functional&quot; way of using <code>Maybe</code> type - if you are interested in this topic, please check <a href="https://talesfrom.dev/blog/map-dont-ask">Map, don&#x27;t ask</a>)</p><p>Phew, that was a bit exhaustive, but we managed to reach our goal!</p><p>We check our behavior specifications, also known as tests - it&#x27;s all green ✅ (we have tests, right?)</p><p>We are using C#, object-oriented language, so this &quot;object&quot; (ok, I know, it&#x27;s a record, but bear with me) does all the processing.</p><p>One observation might be that it&#x27;s violating CQRS as it <em>returns</em> something, and we all know that it&#x27;s either state changing <strong>or</strong> answering about state, never both, right?.</p><p>But is it really an answer? Or maybe <em>an acknowledgement</em>?</p><p>So our little &quot;object&quot; provides processing result, a value related to state of the processing, not the state of the system.</p><p>And how this processing result is consumed? As it is returned from the command handler <code>Handle</code> method, the command handler does not give a damn how it&#x27;s used.</p><p>For command handler, it&#x27;s transparent, context-free.</p><p>Let&#x27;s look closely on the signature of the method:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>AssignmentResult<span class="token punctuation">&gt;</span></span> <span class="token function">Handle</span><span class="token punctuation">(</span><span class="token class-name">AssignWorkerCommand</span> command<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre></div></div><p>As you might recall dear Reader, we explored similar scenario in <a href="https://talesfrom.dev/blog/i-interface#responsibilitity-means-function">I, interface</a>, where we changed the sequence of how inputs and outputs appear in the signature, creating a function:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="code-highlight language-fsharp"><span class="code-line"><span class="token keyword">let</span> Handle <span class="token operator">=</span> AssignWorkerCommand <span class="token operator">=</span><span class="token operator">&gt;</span> Task<span class="token operator">&lt;</span>AssignmentResult<span class="token operator">&gt;</span>
</span></code></pre></div></div><p>This is how a function signature could look like in F#.</p><p>One could say that our command handler with its <code>Handle</code> method resembles a function - it accepts inputs, it <strong>uses</strong> capabilities provided by other objects, it returns a processing result as an output.</p><p>This is one of the most common approaches to handling commands - kind of a functional-style.</p><p>The way functions deliver &quot;answers&quot; is by returning a value.</p><p>What about objects?</p><h3 id="telling-a-result"><a href="#telling-a-result" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Telling&quot; a result</h3><p>One of the core aspects of object-orientation (which is a misnomer on its own; if you are interested in that topic - explore <a href="https://talesfrom.dev/blog/the-ambiguity-of-objects">The ambiguity of objects</a>) is sending and receiving messages.</p><p>Pointing at great, wise words by <a href="https://www.sandimetz.com">Sandi Metz</a>:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>You don&#x27;t send messages because you have objects, you have objects because you send messages.</p></div></div></div><p>Let&#x27;s ask ourselves - is <code>AssignWorkerCommandHandler</code> sending messages?</p><p>In a way, yes - it <strong>asks</strong> other objects to provide answers and based on those answers it <strong>decides</strong> what to do next.</p><p>It also receives messages - actually one message - <code>AssignWorkerCommand</code> message.</p><p>Turns out that message-passing collaborators, which can be another name for &quot;objects&quot;, could be more fond of telling others what to do, rather than returning anything.</p><p>Message-passing is the key component here.</p><p>And this is exactly what <a href="https://twitter.com/GGalezowski">Grzegorz</a> presented with his <a href="https://github.com/grzesiek-galezowski/TrainingExamples/blob/master/CSharp/WeatherAppLogicSeparation/Application/SubscribeCommand.cs">solution</a>.</p><p>It&#x27;s a pure &quot;Tell, Don&#x27;t Ask&quot; approach for designing <strong>interactions</strong> between objects - which means that in order to deliver processing results, objects need other objects to fullfil such responsibility.</p><p>If we look closely, one of the responsibilties our command handler has is deliverying &quot;an acknowledgement&quot;, processing outcome.</p><p><strong>What</strong> remains the same - deliverying results, <strong>how</strong> might vary.</p><p>One of the possibilities is returning the result so that downstream consumers can decide what to do.</p><p>Another one is closely related to &quot;reporting results back&quot; by a specialized role - &quot;a result collector&quot; (if you want to understand more about roles, please check <a href="https://talesfrom.dev/blog/the-ambiguity-of-objects">The ambiguity of objects</a> and <a href="https://talesfrom.dev/blog/the-ambiguity-of-interfaces">The ambiguity of intefaces</a>).</p><p>Shall we try using &quot;Tell, Don&#x27;t Ask&quot; in this little problem space?</p><p>We need to change our command handler <code>Handle</code> signature, from this:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>AssignmentResult<span class="token punctuation">&gt;</span></span> <span class="token function">Handle</span><span class="token punctuation">(</span><span class="token class-name">AssignWorkerCommand</span> command<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre></div></div><p>to that:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token class-name return-type">Task</span> <span class="token function">Handle</span><span class="token punctuation">(</span><span class="token class-name">AssignWorkerCommand</span> command<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre></div></div><p>&quot;But where is the result?!&quot;, an avid Reader might be wondering.</p><p>It will come, no worries.</p><p>Responsibilities does not disappear, they are just assigned to other roles.</p><p>Now let&#x27;s move to our HTTP interaction handler:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line">app<span class="token punctuation">.</span><span class="token function">MapPost</span><span class="token punctuation">(</span><span class="token string">&quot;/assignments/{assignmentId:guid}/assign&quot;</span><span class="token punctuation">,</span>
</span><span class="code-line"><span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token class-name">Guid</span> assignmentId<span class="token punctuation">,</span> <span class="token class-name">ICreateCommandHandler</span> commandHandlerFactory<span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> resultCollector <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">WorkerAssignmentResult</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> commandHandler <span class="token operator">=</span> commandHandlerFactory<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Create</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>AssignWorkerCommandHandler<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span>resultCollector<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">await</span> commandHandler<span class="token punctuation">.</span><span class="token function">Handle</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name constructor-invocation">AssignWorkerCommand</span><span class="token punctuation">(</span>assignmentId<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">return</span> resultCollector<span class="token punctuation">.</span><span class="token function">Match</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token punctuation named-parameter">successfullyAssigned</span><span class="token punctuation">:</span> assignmentResult <span class="token operator">=&gt;</span> Results<span class="token punctuation">.</span><span class="token function">Ok</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token punctuation">{</span> assignedWorkerId <span class="token operator">=</span> assignmentResult<span class="token punctuation">.</span>WorkerId <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token punctuation named-parameter">noWorkersAvailable</span><span class="token punctuation">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> Results<span class="token punctuation">.</span><span class="token function">UnprocessableEntity</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token punctuation">{</span> message <span class="token operator">=</span> <span class="token string">&quot;No workers available&quot;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token punctuation named-parameter">alreadyAssigned</span><span class="token punctuation">:</span> assignmentResult <span class="token operator">=&gt;</span> Results<span class="token punctuation">.</span><span class="token function">Conflict</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token punctuation">{</span> message <span class="token operator">=</span> <span class="token string">&quot;Assignment already has assigned worker&quot;</span><span class="token punctuation">,</span> error <span class="token operator">=</span> <span class="token string">&quot;assignments:assigning:no-workers-available&quot;</span><span class="token punctuation">,</span> alreadyWorkerId <span class="token operator">=</span> assignmentResult<span class="token punctuation">.</span>WorkerId <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token punctuation named-parameter">notQualified</span><span class="token punctuation">:</span> assignmentResult <span class="token operator">=&gt;</span> Results<span class="token punctuation">.</span><span class="token function">UnprocessableEntity</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token punctuation">{</span> message <span class="token operator">=</span> <span class="token string">&quot;Worker is not qualified to do this assignment&quot;</span><span class="token punctuation">,</span> error <span class="token operator">=</span> <span class="token string">&quot;assignments:assigning:worker-not-qualified&quot;</span><span class="token punctuation">,</span> unqualifiedWorkerId <span class="token operator">=</span> assignmentResult<span class="token punctuation">.</span>WorkerId <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token punctuation named-parameter">otherError</span><span class="token punctuation">:</span> message <span class="token operator">=&gt;</span> Results<span class="token punctuation">.</span><span class="token function">UnprocessableEntity</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token punctuation">{</span> message <span class="token operator">=</span> message<span class="token punctuation">;</span> error <span class="token operator">=</span> <span class="token string">&quot;assignments:assigning:other-error&quot;</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre></div></div><p>Note dear Reader that it is one of the possible implementations and it varies from what Grzegorz suggested.</p><p>Ok, let&#x27;s get back to our command handler!</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">record</span> <span class="token class-name">AssignWorkerCommandHandler</span>
</span><span class="code-line">    <span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token class-name">IProvideWorker</span> workerProvider<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">IAssignmentRepository</span> assignmentRepository<span class="token punctuation">,</span>
</span><span class="code-line">        ICollectAssignmentResult resultCollector <span class="token comment">// 👈 new collaborator!</span>
</span><span class="code-line">    <span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">:</span> ICommandHandler<span class="token operator">&lt;</span>AssignWorkerCommand<span class="token punctuation">,</span> AssignmentResult<span class="token operator">&gt;</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">Handle</span><span class="token punctuation">(</span><span class="token class-name">AssignWorkerCommand</span> command<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">try</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token class-name"><span class="token keyword">var</span></span> worker <span class="token operator">=</span> <span class="token keyword">await</span> workerProvider<span class="token punctuation">.</span><span class="token function">ProvideWorker</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span>worker<span class="token punctuation">.</span>HasValue<span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token punctuation">{</span>
</span><span class="code-line">                <span class="token comment">//👇🏻 same place but different way of achieving reporting result back!</span>
</span><span class="code-line">                resultCollector<span class="token punctuation">.</span><span class="token function">noWorkersAvailable</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">                <span class="token keyword">return</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token punctuation">}</span>
</span><span class="code-line">            <span class="token class-name"><span class="token keyword">var</span></span> assignment <span class="token operator">=</span> <span class="token keyword">await</span> assignmentRepository<span class="token punctuation">.</span><span class="token function">Load</span><span class="token punctuation">(</span>command<span class="token punctuation">.</span>AssignmentId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span>assignment<span class="token punctuation">.</span>HasValue<span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token punctuation">{</span>
</span><span class="code-line">                <span class="token comment">//👇🏻 same place but different way of achieving reporting result back!</span>
</span><span class="code-line">                resultCollector<span class="token punctuation">.</span><span class="token function">otherError</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;No assignment with id </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token language-csharp expression">command<span class="token punctuation">.</span>AssignmentId</span><span class="token punctuation">}</span></span><span class="token string"> is available.&quot;</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">                <span class="token keyword">return</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">            assignment<span class="token punctuation">.</span><span class="token function">Assign</span><span class="token punctuation">(</span>worker<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">            <span class="token keyword">await</span> assignmentRepository<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>assignment<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">            <span class="token comment">//👇🏻 same place but different way of achieving reporting result back!</span>
</span><span class="code-line">            resultCollector<span class="token punctuation">.</span><span class="token function">successfullyAssigned</span><span class="token punctuation">(</span>worker<span class="token punctuation">.</span>Id<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token keyword">return</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">        <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">WorkerAlreadyAssigned</span> ex<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token comment">//👇🏻 same place but different way of achieving reporting result back!</span>
</span><span class="code-line">            resultCollector<span class="token punctuation">.</span><span class="token function">workerAlreadyAssigned</span><span class="token punctuation">(</span>worker<span class="token punctuation">.</span>Id<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token keyword">return</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">        <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">WorkerNotQualifiedForAssignment</span> ex<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token comment">//👇🏻 same place but different way of achieving reporting result back!</span>
</span><span class="code-line">            resultCollector<span class="token punctuation">.</span><span class="token function">workerNotQualified</span><span class="token punctuation">(</span>worker<span class="token punctuation">.</span>Id<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token keyword">return</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">        <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Exception</span> ex<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token comment">//👇🏻 same place but different way of achieving reporting result back!</span>
</span><span class="code-line">            resultCollector<span class="token punctuation">.</span><span class="token function">otherError</span><span class="token punctuation">(</span>ex<span class="token punctuation">.</span>Message<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token keyword">return</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>This implementation of results collector is capable of being told what to do (a specific reporting) and provide answers when someone asks (using <code>Match</code> method).</p><p>So in a way it behaves both as an object (receiving messages) and a value object (that can be &quot;mapped&quot; into something else).</p><p>Now, command handler tells to <code>resultCollector</code>, being responsible for collecting a result from assignment processing, what to report.</p><p><code>AssignWorkerCommandHandler</code> knows what happens when, and a someone who plays a role (that is able to report things back) will make it happen.</p><p>We saw <code>WorkerAssignmentResult</code> in action, so let&#x27;s see how does he fullfil his responsibilities:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">ICollectAssignmentResult</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">void</span></span> <span class="token function">noWorkersAvailable</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">void</span></span> <span class="token function">successfullyAssigned</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> workerId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">void</span></span> <span class="token function">workerAlreadyAssigned</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> workerId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">void</span></span> <span class="token function">workerNotQualified</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> workerId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">void</span></span> <span class="token function">otherError</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> message<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">WorkerAssignmentResult</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">ICollectAssignmentResult</span></span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">private</span> <span class="token class-name">AssignmentResult</span> _result<span class="token punctuation">;</span> <span class="token comment">// 👈 we reuse the value object we have already brought earlier</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">void</span></span> <span class="token function">noWorkersAvailable</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        result <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">AssignmentResult<span class="token punctuation">.</span>NoWorkersAvailable</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">void</span></span> <span class="token function">successfullyAssigned</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> workerId<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        result <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">AssignmentResult<span class="token punctuation">.</span>SuccessfullyAssigned</span><span class="token punctuation">(</span>workerId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">void</span></span> <span class="token function">workerAlreadyAssigned</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> workerId<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        result <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">AssignmentResult<span class="token punctuation">.</span>WorkerAlreadyAssigned</span><span class="token punctuation">(</span>workerId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">void</span></span> <span class="token function">workerNotQualified</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> workerId<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        result <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">AssignmentResult<span class="token punctuation">.</span>WorkerNotQualified</span><span class="token punctuation">(</span>workerId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">void</span></span> <span class="token function">otherError</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> message<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        result <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">AssignmentResult<span class="token punctuation">.</span>OtherError</span><span class="token punctuation">(</span>message<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">return</span> <span class="token class-name return-type">TResult</span> <span class="token generic-method"><span class="token function">Match</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>TReturn<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span>
</span><span class="code-line">            <span class="token class-name">Func<span class="token punctuation">&lt;</span>AssignmentResult<span class="token punctuation">,</span> TReturn<span class="token punctuation">&gt;</span></span> successfullyAssigned<span class="token punctuation">,</span>
</span><span class="code-line">            <span class="token class-name">Func<span class="token punctuation">&lt;</span>TReturn<span class="token punctuation">&gt;</span></span> noWorkersAvailable<span class="token punctuation">,</span>
</span><span class="code-line">            <span class="token class-name">Func<span class="token punctuation">&lt;</span>AssignmentResult<span class="token punctuation">,</span> TReturn<span class="token punctuation">&gt;</span></span> alreadyAssigned<span class="token punctuation">,</span>
</span><span class="code-line">            <span class="token class-name">Func<span class="token punctuation">&lt;</span>AssignmentResult<span class="token punctuation">,</span> TReturn<span class="token punctuation">&gt;</span></span> notQualified<span class="token punctuation">,</span>
</span><span class="code-line">            <span class="token class-name">Func<span class="token punctuation">&lt;</span><span class="token keyword">string</span><span class="token punctuation">,</span> TReturn<span class="token punctuation">&gt;</span></span> otherError
</span><span class="code-line">        <span class="token punctuation">)</span> <span class="token operator">=&gt;</span> _result<span class="token punctuation">.</span><span class="token function">Match</span><span class="token punctuation">(</span>
</span><span class="code-line">            successfullyAssigned<span class="token punctuation">,</span>
</span><span class="code-line">            noWorkersAvailable<span class="token punctuation">,</span>
</span><span class="code-line">            alreadyAssigned<span class="token punctuation">,</span>
</span><span class="code-line">            notQualified<span class="token punctuation">,</span>
</span><span class="code-line">            otherError
</span><span class="code-line">        <span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>For the <code>AssignWorkerCommandHandler</code> it is transparent and unknown who satisfies &quot;reporting capability&quot;.</p><p>It could be a dedicated object (<code>WorkerAssignmentResult</code>), a controller (as in <a href="https://github.com/grzesiek-galezowski/TrainingExamples/blob/master/CSharp/WeatherAppLogicSeparation/WeatherAppLogicSeparation/Controllers/WeatherForecastController.cs">Grzegorz&#x27;s solution</a>), or any other object that is able to respond to a call (response-ability, right?).</p><p>We&#x27;ve made a &quot;little shortcut&quot; and reused <code>AssignmentResult</code> value object from previous example, but still - wouldn&#x27;t it be neat to have it?</p><p>Getting back to our command handler - it is a truly message-passing collaborator - it plays a major role in interactions with other objects.</p><p>If again look closely into <code>Handle</code> signature - it changed.</p><p>From types perspective, we don&#x27;t have <code>AssignWorkerCommand =&gt; Task&lt;AssignmentResult&gt;</code>, but <code>AssignWorkerCommand =&gt; Task</code> instead!</p><p>Which initially might seem counterintuitive and against the natural way of thinking that people have, in which we tend to expect things to &quot;flow&quot; from top, to bottom, from left to right.</p><p>And here we throw things into void?</p><p>Do you know, dear Reader, what is the best way of checking the quality of our designs?</p><p>By introducing a change and see what is left when things are collapsing.</p><h3 id="1-change-change-never-changes---functional-command-handler"><a href="#1-change-change-never-changes---functional-command-handler" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>#1 Change, change never changes - &quot;functional&quot; command handler</h3><p>Imagine that we were challenged to implement logging for each not-so-happy-scenario in assigning worker use case.</p><p>How does this affect our &quot;functional&quot; command handler?</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">record</span> <span class="token class-name">AssignWorkerCommandHandler</span><span class="token punctuation">(</span>
</span><span class="code-line">    <span class="token class-name">ILogger<span class="token punctuation">&lt;</span>AssignWorkerCommandHandler<span class="token punctuation">&gt;</span></span> logger<span class="token punctuation">,</span> <span class="token comment">// 👈 new collaborator!</span>
</span><span class="code-line">    <span class="token class-name">IProvideWorker</span> workerProvider<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">IAssignmentRepository</span> assignmentRepository
</span><span class="code-line"><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">:</span> ICommandHandler<span class="token operator">&lt;</span>AssignWorkerCommand<span class="token punctuation">,</span> AssignmentResult<span class="token operator">&gt;</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>AssignmentResult<span class="token punctuation">&gt;</span></span> <span class="token function">Handle</span><span class="token punctuation">(</span><span class="token class-name">AssignWorkerCommand</span> command<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">try</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token class-name"><span class="token keyword">var</span></span> worker <span class="token operator">=</span> <span class="token keyword">await</span> workerProvider<span class="token punctuation">.</span><span class="token function">ProvideWorker</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span>worker<span class="token punctuation">.</span>HasValue<span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token punctuation">{</span>
</span><span class="code-line">                <span class="token comment">//👇🏻 same place as before for adding new behavior</span>
</span><span class="code-line">                logger<span class="token punctuation">.</span><span class="token function">LogError</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;No workers available when trynig to assign workers for assignment </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token language-csharp expression">command<span class="token punctuation">.</span>AssignmentId</span><span class="token punctuation">}</span></span><span class="token string">&quot;</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">                <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">AssignmentResult<span class="token punctuation">.</span>NoWorkersAvailable</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token punctuation">}</span>
</span><span class="code-line">            <span class="token class-name"><span class="token keyword">var</span></span> assignment <span class="token operator">=</span> <span class="token keyword">await</span> assignmentRepository<span class="token punctuation">.</span><span class="token function">Load</span><span class="token punctuation">(</span>command<span class="token punctuation">.</span>AssignmentId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span>assignment<span class="token punctuation">.</span>HasValue<span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token punctuation">{</span>
</span><span class="code-line">                <span class="token comment">//👇🏻 same place as before for adding new behavior</span>
</span><span class="code-line">                logger<span class="token punctuation">.</span><span class="token function">LogError</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;No assignment with id </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token language-csharp expression">command<span class="token punctuation">.</span>AssignmentId</span><span class="token punctuation">}</span></span><span class="token string">&quot;</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">                <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">AssignmentResult<span class="token punctuation">.</span>OtherError</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;No assignment with id </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token language-csharp expression">command<span class="token punctuation">.</span>AssignmentId</span><span class="token punctuation">}</span></span><span class="token string"> is available.&quot;</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">            assignment<span class="token punctuation">.</span><span class="token function">Assign</span><span class="token punctuation">(</span>worker<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">            <span class="token keyword">await</span> assignmentRepository<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>assignment<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">            <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">AssignmentResult<span class="token punctuation">.</span>SuccessfullyAssigned</span><span class="token punctuation">(</span>worker<span class="token punctuation">.</span>Id<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">        <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">WorkerAlreadyAssigned</span> ex<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token comment">//👇🏻 same place as before for adding new behavior</span>
</span><span class="code-line">            logger<span class="token punctuation">.</span><span class="token function">LogError</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;Worker already assigned to assignment </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token language-csharp expression">command<span class="token punctuation">.</span>AssignmentId</span><span class="token punctuation">}</span></span><span class="token string">&quot;</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">AssignmentResult<span class="token punctuation">.</span>WorkerAlreadyAssigned</span><span class="token punctuation">(</span>worker<span class="token punctuation">.</span>Id<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">        <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">WorkerNotQualifiedForAssignment</span> ex<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token comment">//👇🏻 same place as before for adding new behavior</span>
</span><span class="code-line">            logger<span class="token punctuation">.</span><span class="token function">LogError</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;Worker not qualified for assigning to assignment </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token language-csharp expression">command<span class="token punctuation">.</span>AssignmentId</span><span class="token punctuation">}</span></span><span class="token string">&quot;</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">AssignmentResult<span class="token punctuation">.</span>WorkerNotQualified</span><span class="token punctuation">(</span>worker<span class="token punctuation">.</span>Id<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">        <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Exception</span> ex<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token comment">//👇🏻 same place as before for adding new behavior</span>
</span><span class="code-line">            logger<span class="token punctuation">.</span><span class="token function">LogError</span><span class="token punctuation">(</span>ex<span class="token punctuation">,</span> <span class="token interpolation-string"><span class="token string">$&quot;Other error happened when assigning worker to assignment </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token language-csharp expression">command<span class="token punctuation">.</span>AssignmentId</span><span class="token punctuation">}</span></span><span class="token string">&quot;</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">AssignmentResult<span class="token punctuation">.</span>OtherError</span><span class="token punctuation">(</span>ex<span class="token punctuation">.</span>Message<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>As a result, we also need to adjust a bunch of tests, as we changed not only the <code>Handle</code> method, but also a constructor.</p><p>&quot;You could add this logging to controller, dumbass&quot; - one might think.</p><p>Of course, we could assign the responsibilty for reporting logs to controller. Then we could report only failure scenarios there.</p><p>No doubts there.</p><p>But still we would need to add logging to only failure branches of the match, isn&#x27;t it?</p><p>Ok, let&#x27;s move on.</p><p>How will message-passing, collaborative command handler handle that requirement?</p><h3 id="1-change-change-never-changes---message-passing-collaborative-command-handler"><a href="#1-change-change-never-changes---message-passing-collaborative-command-handler" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>#1 Change, change never changes - message-passing, collaborative command handler</h3><p>Of course it vastly depends on the implementation - but in fact it might not change at all!</p><p>We need to adjust one of its collaborators - someone who plays a role having the responsibility for collecting assigning results - <code>ICollectAssignmentResult</code>.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">WorkerAssignmentResult</span><span class="token punctuation">(</span>
</span><span class="code-line">    ILogger<span class="token operator">&lt;</span>AssignWorkerCommandHandler<span class="token operator">&gt;</span> logger
</span><span class="code-line">    <span class="token class-name">Guid</span> assignmentId<span class="token punctuation">,</span>
</span><span class="code-line"><span class="token punctuation">)</span> <span class="token punctuation">:</span> ICollectAssignmentResult
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">private</span> <span class="token class-name">AssignmentResult</span> _result<span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">void</span></span> <span class="token function">noWorkersAvailable</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">//👇🏻 same place as before for adding new behavior</span>
</span><span class="code-line">        logger<span class="token punctuation">.</span><span class="token function">LogError</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;No workers available when trynig to assign workers for assignment </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token language-csharp expression">command<span class="token punctuation">.</span>AssignmentId</span><span class="token punctuation">}</span></span><span class="token string">&quot;</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        result <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">AssignmentResult<span class="token punctuation">.</span>NoWorkersAvailable</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">void</span></span> <span class="token function">successfullyAssigned</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> workerId<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">// no need to log here!</span>
</span><span class="code-line">        result <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">AssignmentResult<span class="token punctuation">.</span>SuccessfullyAssigned</span><span class="token punctuation">(</span>workerId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">void</span></span> <span class="token function">workerAlreadyAssigned</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> workerId<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">//👇🏻 same place as before for adding new behavior</span>
</span><span class="code-line">        logger<span class="token punctuation">.</span><span class="token function">LogError</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;Worker already assigned to assignment </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token language-csharp expression">assignmentId</span><span class="token punctuation">}</span></span><span class="token string">&quot;</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        result <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">AssignmentResult<span class="token punctuation">.</span>WorkerAlreadyAssigned</span><span class="token punctuation">(</span>workerId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">void</span></span> <span class="token function">workerNotQualified</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> workerId<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">//👇🏻 same place as before for adding new behavior</span>
</span><span class="code-line">        logger<span class="token punctuation">.</span><span class="token function">LogError</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;Worker not qualified for assigning to assignment </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token language-csharp expression">assignmentId</span><span class="token punctuation">}</span></span><span class="token string">&quot;</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        result <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">AssignmentResult<span class="token punctuation">.</span>WorkerNotQualified</span><span class="token punctuation">(</span>workerId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">void</span></span> <span class="token function">otherError</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> message<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">//👇🏻 same place as before for adding new behavior</span>
</span><span class="code-line">        logger<span class="token punctuation">.</span><span class="token function">LogError</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;Other error happened when assigning worker to assignment </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token language-csharp expression">assignmentId</span><span class="token punctuation">}</span></span><span class="token string">. Message: </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token language-csharp expression">message</span><span class="token punctuation">}</span></span><span class="token string">&quot;</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        result <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">AssignmentResult<span class="token punctuation">.</span>OtherError</span><span class="token punctuation">(</span>message<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">// `Match` method did not change</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>This causes a ripple during the HTTP interaction handling, let&#x27;s fix that:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line">app<span class="token punctuation">.</span><span class="token function">MapPost</span><span class="token punctuation">(</span><span class="token string">&quot;/assignments/{assignmentId:guid}/assign&quot;</span><span class="token punctuation">,</span>
</span><span class="code-line"><span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token class-name">ILogger<span class="token punctuation">&lt;</span>AssignWorkerCommandHandler<span class="token punctuation">&gt;</span></span> commandHandlingLogger<span class="token punctuation">,</span> <span class="token class-name">Guid</span> assignmentId<span class="token punctuation">,</span> <span class="token class-name">ICreateCommandHandler</span> commandHandlerFactory<span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> resultCollector <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">WorkerAssignmentResult</span><span class="token punctuation">(</span>commandHandlingLogger<span class="token punctuation">,</span> assignmentId<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 👈 we had compile-time error here, it was an easy fix.</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> commandHandler <span class="token operator">=</span> commandHandlerFactory<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Create</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>AssignWorkerCommandHandler<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span>resultCollector<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">await</span> commandHandler<span class="token punctuation">.</span><span class="token function">Handle</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name constructor-invocation">AssignWorkerCommand</span><span class="token punctuation">(</span>assignmentId<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">return</span> resultCollector<span class="token punctuation">.</span><span class="token function">Match</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token punctuation named-parameter">successfullyAssigned</span><span class="token punctuation">:</span> assignmentResult <span class="token operator">=&gt;</span> Results<span class="token punctuation">.</span><span class="token function">Ok</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token punctuation">{</span> assignedWorkerId <span class="token operator">=</span> assignmentResult<span class="token punctuation">.</span>WorkerId <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token punctuation named-parameter">noWorkersAvailable</span><span class="token punctuation">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> Results<span class="token punctuation">.</span><span class="token function">UnprocessableEntity</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token punctuation">{</span> message <span class="token operator">=</span> <span class="token string">&quot;No workers available&quot;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token punctuation named-parameter">alreadyAssigned</span><span class="token punctuation">:</span> assignmentResult <span class="token operator">=&gt;</span> Results<span class="token punctuation">.</span><span class="token function">Conflict</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token punctuation">{</span> message <span class="token operator">=</span> <span class="token string">&quot;Assignment already has assigned worker&quot;</span><span class="token punctuation">,</span> error <span class="token operator">=</span> <span class="token string">&quot;assignments:assigning:no-workers-available&quot;</span><span class="token punctuation">,</span> alreadyWorkerId <span class="token operator">=</span> assignmentResult<span class="token punctuation">.</span>WorkerId <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token punctuation named-parameter">notQualified</span><span class="token punctuation">:</span> assignmentResult <span class="token operator">=&gt;</span> Results<span class="token punctuation">.</span><span class="token function">UnprocessableEntity</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token punctuation">{</span> message <span class="token operator">=</span> <span class="token string">&quot;Worker is not qualified to do this assignment&quot;</span><span class="token punctuation">,</span> error <span class="token operator">=</span> <span class="token string">&quot;assignments:assigning:worker-not-qualified&quot;</span><span class="token punctuation">,</span> unqualifiedWorkerId <span class="token operator">=</span> assignmentResult<span class="token punctuation">.</span>WorkerId <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token punctuation named-parameter">otherError</span><span class="token punctuation">:</span> message <span class="token operator">=&gt;</span> Results<span class="token punctuation">.</span><span class="token function">UnprocessableEntity</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token punctuation">{</span> message <span class="token operator">=</span> message<span class="token punctuation">;</span> error <span class="token operator">=</span> <span class="token string">&quot;assignments:assigning:other-error&quot;</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre></div></div><p>As you probably noticed dear Reader - there is no magic, we need to touch some elements of our design.</p><p>This also might require adjusting some of the behavior specifications (tests), but on the different level.</p><p>Question is what we already alter - &quot;logging&quot; is pretty frequently happening capability, so it might have been added from the day one.</p><p>Although, one of the the reasons behind &quot;logging&quot; might be &quot;reporting results&quot;, and in this scenario it was a breeze to be added in collaboration-based solution.</p><p>Functional-based solution got a bit &quot;cluttered&quot; with logging.</p><p>Some people are used to such appearances, so it does not seem &quot;strange&quot;.</p><h3 id="from-objects-to-actors"><a href="#from-objects-to-actors" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>From objects to actors</h3><p>By clearly segregating responsibilities for processing and for collecting results, we achieved some interesting qualities.</p><p>When we moved from &quot;functional&quot; to &quot;message-passing collaborator&quot;, our command handler become something different.</p><p>It was still able to deliver the same capabilities, although it required help from others, so true power emerged from the collaboration, not objects acting alone.</p><p>Composing behaviors around reporting capability was already baked in, due to objects interacting with each other.</p><p>Don&#x27;t get me wrong, dear Reader, I am not bashing or complaining on functional programming, as I am really into it.</p><p>Turns out that our <code>AssignWorkerCommandHandler</code> started looking more as an actor, rather than &quot;a function&quot;.</p><p>Look what a simple act of changing how processing results are reported changed the nature of the handler.</p><p>It did processing and sent messages to others.</p><p>As we explored in <a href="https://talesfrom.dev/blog/the-ambiguity-of-object">The ambiguity of objects</a>:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Transformations and message passing are two sides of the same coin.</p></div></div></div><p>Some might comment that it got too boilerplate-y, less terse and less readable.</p><p>Well, maybe.</p><p>There are systems built on top of the actor-model and prove their reliability, robustness and abilities to respond to a change in a swift fashion.</p><p>Initially, it might feel strange to &quot;report back&quot; results, instead of returning them.</p><p>It&#x27;s a matter of getting accustomed to it.</p><p>But look on the bright sight - what qualities such design gives us back?</p><p>Imagine what superpowers you might get when you truly embrace actor-model, e.g. by using <a href="https://getakka.net">Akka.NET</a>.</p><h3 id="bonus-2-change-change-never-changes-notifying-about-successful-processing"><a href="#bonus-2-change-change-never-changes-notifying-about-successful-processing" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Bonus: #2 Change, change never changes: notifying about successful processing</h3><p>As a bonus, imagine that there is another requirement to incorporate into our system: whenever a worker got successfully assigned, we should notify interested parties.</p><p>It should be done by sending a message by utilizing a queue.</p><p>If you were constrainted to use a message-passing collaborators approach - how would you design it, dear Reader?</p>]]></content:encoded>
    <pubDate>Mon, 21 Apr 2025 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>cqrs</category><category>modeling</category><category>software design</category><category>domain modeling</category><category>actor-model</category><category>functional programming</category><category>design patterns</category><category>software engineering</category><category>object-oriented design</category><category>patterns</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/evolve-dont-hack</guid>
    <title>Evolve, don&#39;t hack</title>
    <link>https://talesfrom.dev/blog/evolve-dont-hack</link>
    <description>Where is the difference between evolving and hacking?</description>
    <content:encoded><![CDATA[<h3 id="1-bugs-strike-back"><a href="#1-bugs-strike-back" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>#1 Bugs strike back!</h3><p>Yet another day, yet another bug.</p><p>Turned out that one of the algorithms didn&#x27;t work properly.</p><p>The whole algorithm was related to something that, in my opinion, is the most &quot;DDD&quot;-ed one could get - graphs.</p><p>The potential fix was scoped to this little method:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token class-name return-type">IEnumerable<span class="token punctuation">&lt;</span>Node<span class="token punctuation">&gt;</span></span> <span class="token function">ImportantTraversalAlgorithm</span><span class="token punctuation">(</span><span class="token class-name">Node</span> node<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// details of the algorithm</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>(I skipped the details due to NDA)</p><p>What now?</p><p>Probably, the best way is to understand the outside-in perspective and the needs of the consumer.</p><p>Alone?</p><p>Hell no!</p><p>By gathering the brilliant minds around, in the software teaming spirit, we figured out that we are missing very important aspect in the traversal steps.</p><p>The step should stop immediately when finding a &quot;special&quot; node - <code>GroupingNode</code> - that was what we were really looking for.</p><p>Just so you know - it wasn&#x27;t &quot;ten minutes tinkering&quot;.</p><p>We informally went through Example Mapping-ish process, when we laid out the need, the rules and examples.</p><p><strong>Together</strong>. (you might be interested in <a href="https://talesfrom.dev/blog/the-ambiguity-of-team-work">The ambiguity of team work</a>)</p><p>Writing &quot;code&quot; was merely an act of execution.</p><h3 id="1-model"><a href="#1-model" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>#1 Model</h3><p>Ok, what did I know?</p><p>The problem - missing termination condition - finding a <code>GroupingNode</code>.</p><p>Let&#x27;s try to express it as a question: <em>has <code>GroupingNode</code> been found?</em></p><p>Ok, what is the simplest model that is able to answer this question?</p><p>Possibly it is something that can state:</p><ul><li>yes (<code>GroupingNode</code> has found)</li><li>no (<code>GroupingNode</code> has not been found)</li></ul><p>Which means we are dealing with a simple <code>boolean</code> model!</p><p>So the intuition might tell us that we need to start with &quot;a clear state&quot; (<code>1. initialize as no GroupingNode found</code>):</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token class-name return-type">IEnumerable<span class="token punctuation">&lt;</span>Node<span class="token punctuation">&gt;</span></span> <span class="token function">ImportantTraversalAlgorithm</span><span class="token punctuation">(</span><span class="token class-name">Node</span> node<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// existing initialization</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">bool</span></span> hasFoundGroupingNode <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span> <span class="token comment">// 👈 1. initialize as no GroupingNode found</span>
</span><span class="code-line">    <span class="token comment">// details of the algorithm</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Next step would be to use our model that is able to answer the main question (<code>2. model answering the question</code>):</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token class-name return-type">IEnumerable<span class="token punctuation">&lt;</span>Node<span class="token punctuation">&gt;</span></span> <span class="token function">ImportantTraversalAlgorithm</span><span class="token punctuation">(</span><span class="token class-name">Node</span> node<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// existing initialization</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">bool</span></span> hasFoundGroupingNode <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span> <span class="token comment">// 👈 1. initialize as no GroupingNode found</span>
</span><span class="code-line">    <span class="token comment">// details of the algorithm</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">if</span><span class="token punctuation">(</span>hasFoundGroupingNode<span class="token punctuation">)</span> <span class="token comment">// 👈 2. model answering the question</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">return</span> Traversal<span class="token punctuation">.</span>Stop<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">// rest of the details</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>And then we are almost there - the last piece is to identify a node that plays the role of a <code>GroupingNode</code> (<code>3. identify a GroupingNode</code>):</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token class-name return-type">IEnumerable<span class="token punctuation">&lt;</span>Node<span class="token punctuation">&gt;</span></span> <span class="token function">ImportantTraversalAlgorithm</span><span class="token punctuation">(</span><span class="token class-name">Node</span> node<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// existing initialization</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">bool</span></span> hasFoundGroupingNode <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span> <span class="token comment">// 👈 1. initialize as no GroupingNode found</span>
</span><span class="code-line">    <span class="token comment">// details of the algorithm</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">if</span><span class="token punctuation">(</span>hasFoundGroupingNode<span class="token punctuation">)</span> <span class="token comment">// 👈 2. model answering the question</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">return</span> Traversal<span class="token punctuation">.</span>Stop<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">// rest of the details</span>
</span><span class="code-line">    <span class="token keyword">if</span><span class="token punctuation">(</span>currentNode <span class="token keyword">is</span> <span class="token class-name">GroupingNode</span> _<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        hasFoundGroupingNode <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span> <span class="token comment">// 👈 3. identify a GroupingNode</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token comment">// rest of the details</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>9 lines in total.</p><p>Phew, that was a real blast.</p><p>Verification - all good!</p><h3 id="2-bugs-strike-back"><a href="#2-bugs-strike-back" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>#2 Bugs strike back</h3><p>You can&#x27;t predict the future, ain&#x27;t you dear Reader?</p><p>Me neither.</p><p>Turned out that there are some scenarios when it&#x27;s not sufficient to only identify a <code>GroupingNode</code>, but also to check if a currently processed node is grouped by an already found <code>GroupingNode</code>.</p><p>&quot;But it wasn&#x27;t specified in the user story&quot;, one could vishously shout.</p><p>Well, believe me or not, no amount of specification can give more feedback than shipping stuff. (if you want to understand more, please check <a href="https://talesfrom.dev/blog/fragile">(Fr)Agile</a>).</p><p>Let&#x27;s get back to our misaligned behavior.</p><p>It seems that our current solution needs some additional effort.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token class-name return-type">IEnumerable<span class="token punctuation">&lt;</span>Node<span class="token punctuation">&gt;</span></span> <span class="token function">ImportantTraversalAlgorithm</span><span class="token punctuation">(</span><span class="token class-name">Node</span> node<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// existing initialization</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">bool</span></span> hasFoundGroupingNode <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span> <span class="token comment">// 👈 1. initialize as no GroupingNode found</span>
</span><span class="code-line">    <span class="token comment">// details of the algorithm</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">if</span><span class="token punctuation">(</span>hasFoundGroupingNode<span class="token punctuation">)</span> <span class="token comment">// 👈 2. model answering the question</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">return</span> Traversal<span class="token punctuation">.</span>Stop<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">// rest of the details</span>
</span><span class="code-line">    <span class="token keyword">if</span><span class="token punctuation">(</span>currentNode <span class="token keyword">is</span> <span class="token class-name">GroupingNode</span> _<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">// 🤔 is this model sufficient?</span>
</span><span class="code-line">        hasFoundGroupingNode <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span> <span class="token comment">// 👈 3. identify a GroupingNode</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token comment">// rest of the details</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Let&#x27;s revisit the main question - did it change?</p><p>Well, yes but no.</p><p>Additionally to identifying a <code>GroupingNode</code> we also need to check if a currently processed node is grouped by it.</p><p>We could extend this question:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="code-highlight language-diff"><span class="code-line deleted"><span class="token deleted deleted-sign"><span class="token deleted prefix">-</span><span class="token line"> Has a GroupingNode been found?
</span></span></span><span class="code-line inserted"><span class="token deleted deleted-sign"><span class="token line"></span></span><span class="token inserted inserted-sign"><span class="token inserted prefix">+</span><span class="token line"> Has a GroupingNode been found for a given node?
</span></span></span></code></pre></div></div><p>Which basically means that our current model is not capable of providing a right answer.</p><p><code>bool</code> model is not sufficient!</p><h3 id="2-model"><a href="#2-model" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>#2 Model</h3><p>What would be the easiest possible model that would be capable of giving more advanced answer?</p><p>A tuple?</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token class-name return-type">IEnumerable<span class="token punctuation">&lt;</span>Node<span class="token punctuation">&gt;</span></span> <span class="token function">ImportantTraversalAlgorithm</span><span class="token punctuation">(</span><span class="token class-name">Node</span> node<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// existing initialization</span>
</span><span class="code-line">    <span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">bool</span></span> hasFoundGroupingNode<span class="token punctuation">,</span> <span class="token class-name">GroupingNode<span class="token punctuation">?</span></span> groupingNode<span class="token punctuation">)</span> groupingNodeRule <span class="token operator">=</span>
</span><span class="code-line">        <span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 👈 1. initialize as no GroupingNode found</span>
</span><span class="code-line">    <span class="token comment">// details of the algorithm</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">// 👇 we already changed the existing behavior</span>
</span><span class="code-line">    <span class="token keyword">if</span><span class="token punctuation">(</span>groupingNodeRule<span class="token punctuation">.</span>hasFoundGroupingNode <span class="token operator">&amp;&amp;</span> groupingNodeRule<span class="token punctuation">.</span>groupingNode<span class="token punctuation">.</span><span class="token function">Groups</span><span class="token punctuation">(</span>currentNode<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// 👈 2. model answering the question</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">return</span> Traversal<span class="token punctuation">.</span>Stop<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">// rest of the details</span>
</span><span class="code-line">    <span class="token keyword">if</span><span class="token punctuation">(</span>currentNode <span class="token keyword">is</span> <span class="token class-name">GroupingNode</span> groupingNode<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        groupingNodeRule  <span class="token operator">=</span> 
</span><span class="code-line">            <span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">,</span> groupingNode<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 👈 3. identify a GroupingNode</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token comment">// rest of the details</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>It&#x27;s easy, but is it simple? (you might be wondering what I am talking about - please feel invited to read <a href="https://talesfrom.dev/blog/simple-isnt-easy">Simple isn&#x27;t easy</a>)</p><p>In fact, we could employ even &quot;simpler&quot; solution - a nullable <code>GroupingNode</code>!</p><p>By dropping <code>bool</code> we make the model smaller and decision could be based on existence.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token class-name return-type">IEnumerable<span class="token punctuation">&lt;</span>Node<span class="token punctuation">&gt;</span></span> <span class="token function">ImportantTraversalAlgorithm</span><span class="token punctuation">(</span><span class="token class-name">Node</span> node<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// existing initialization</span>
</span><span class="code-line">    <span class="token class-name">GroupingNode<span class="token punctuation">?</span></span> groupingNode <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span> <span class="token comment">// 👈 1. initialize as no GroupingNode found</span>
</span><span class="code-line">    <span class="token comment">// details of the algorithm</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">if</span><span class="token punctuation">(</span>groupingNode<span class="token punctuation">.</span>HasValue <span class="token operator">&amp;&amp;</span> groupingNode<span class="token punctuation">.</span>Value<span class="token punctuation">.</span><span class="token function">Groups</span><span class="token punctuation">(</span>currentNode<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// 👈 2. model answering the question</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">return</span> Traversal<span class="token punctuation">.</span>Stop<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">// rest of the details</span>
</span><span class="code-line">    <span class="token keyword">if</span><span class="token punctuation">(</span>currentNode <span class="token keyword">is</span> <span class="token class-name">GroupingNode</span> _groupingNode<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        groupingNode <span class="token operator">=</span> _groupingNode<span class="token punctuation">;</span> <span class="token comment">// 👈 3. identify a GroupingNode</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token comment">// rest of the details</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>That&#x27;s actually a really minimalistic solution, isn&#x27;t it dear Reader?</p><p>It&#x27;s quite typical to initialize <strong>variables</strong> as <code>null</code> at the beginning of a method, right? (because they are varying, right?)</p><p>I know the solution is working.</p><p>Although there&#x27;s something hidden in the statement &quot;the solution is working&quot;.</p><p>You know what is it, dear Reader?</p><p><strong>For me, now</strong>.</p><p><a href="https://talesfrom.dev/blog/easy-becomes-complex">Easy becomes complex</a> so it might be that in three weeks (or days?) I will completely forget what does the <code>null</code> mean.</p><p>Of course it means &quot;missingness&quot;, right? (you might be interested in reading <a href="https://talesfrom.dev/blog/rethinking-missingness">Rethinking &quot;missingness&quot;</a>)</p><p>Maybe we should <a href="https://talesfrom.dev/blog/slow-down">slow down</a> and rethink the problem again, and rethink representing it with &quot;the code&quot;?</p><h3 id="3-model"><a href="#3-model" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>#3 Model</h3><p>If we look closely onto the termination condition:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">if</span><span class="token punctuation">(</span>groupingNode<span class="token punctuation">.</span>HasValue <span class="token operator">&amp;&amp;</span> groupingNode<span class="token punctuation">.</span>Value<span class="token punctuation">.</span><span class="token function">Groups</span><span class="token punctuation">(</span>currentNode<span class="token punctuation">)</span><span class="token punctuation">)</span>
</span></code></pre></div></div><p>It might seem fine but before we didn&#x27;t need &quot;and&quot; (<code>&amp;&amp;</code>).</p><p>Now the problem changed and the solution should follow - structure-wise we evolved a simple <code>bool</code> into a nullable <code>GroupingNode</code>.</p><p>But is it a right structure?</p><p>A simple nullable type does not offer us clear understanding as it does not <strong>communicate</strong> with the correct language.</p><p>We don&#x27;t think in terms of <code>null</code> GroupingNode and non-null <code>GroupingNode</code> grouping a node, isn&#x27;t it?</p><p>It feels as if we are missing a concept being represented with the code (a concept? you might be interested in <a href="https://talesfrom.dev/blog/concept-maps">Concept Maps</a>)</p><p>Ok, shall we try to represent this abstract idea that lives in the problem area?</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token comment">// 👇 abstract idea </span>
</span><span class="code-line"><span class="token keyword">private</span> <span class="token keyword">abstract</span> <span class="token keyword">record</span> <span class="token class-name">IdentifiedGroupingNode</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">abstract</span> <span class="token class-name return-type"><span class="token keyword">bool</span></span> <span class="token function">IsIdentifiedFor</span><span class="token punctuation">(</span><span class="token class-name">Node</span> node<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>This abstract idea is our model that is capable of answering a main question, expressing the problem.</p><p>It expresses <strong>WHAT</strong>, without telling <strong>HOW</strong>.</p><p>What we know is that currently there are two scenarios able to bring the answer:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">private</span> <span class="token keyword">abstract</span> <span class="token keyword">record</span> <span class="token class-name">IdentifiedGroupingNode</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">abstract</span> <span class="token class-name return-type"><span class="token keyword">bool</span></span> <span class="token function">IsIdentifiedFor</span><span class="token punctuation">(</span><span class="token class-name">Node</span> node<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name return-type">IdentifiedGroupingNode</span> NotFound <span class="token operator">=&gt;</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">NoGroupingNodeFound</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name return-type">IdentifiedGroupingNode</span> Found <span class="token operator">=&gt;</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">GroupingNodeFound</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">// 👇 represents &quot;false&quot;</span>
</span><span class="code-line">    <span class="token keyword">private</span> <span class="token keyword">sealed</span> <span class="token keyword">record</span> <span class="token class-name">NoGroupingNodeFound</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">IdentifiedGroupingNode</span></span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">public</span> <span class="token keyword">override</span> <span class="token class-name return-type"><span class="token keyword">bool</span></span> <span class="token function">IsIdentifiedFor</span><span class="token punctuation">(</span><span class="token class-name">Node</span> node<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">// 👇 represents &quot;true&quot;</span>
</span><span class="code-line">    <span class="token keyword">private</span> <span class="token keyword">sealed</span> <span class="token keyword">record</span> <span class="token class-name">GroupingNodeFound</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">IdentifiedGroupingNode</span></span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">public</span> <span class="token keyword">override</span> <span class="token class-name return-type"><span class="token keyword">bool</span></span> <span class="token function">IsIdentifiedFor</span><span class="token punctuation">(</span><span class="token class-name">Node</span> node<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Ok, it looks scary as hell.</p><p>We got a <code>bool</code>, now we have a beast.</p><p>Look how big it is!</p><p>But how can it be used?</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token class-name return-type">IEnumerable<span class="token punctuation">&lt;</span>Node<span class="token punctuation">&gt;</span></span> <span class="token function">ImportantTraversalAlgorithm</span><span class="token punctuation">(</span><span class="token class-name">Node</span> node<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// existing initialization</span>
</span><span class="code-line">    <span class="token class-name">IdentifiedGroupingNode</span> groupingNode <span class="token operator">=</span>
</span><span class="code-line">        IdentifiedGroupingNode<span class="token punctuation">.</span>NotFound<span class="token punctuation">;</span> <span class="token comment">// 👈 1. initialize as no GroupingNode found</span>
</span><span class="code-line">    <span class="token comment">// details of the algorithm</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">if</span><span class="token punctuation">(</span>groupingNode<span class="token punctuation">.</span><span class="token function">IsIdentifiedFor</span><span class="token punctuation">(</span>currentNode<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// 👈 2. model answering the question</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">return</span> Traversal<span class="token punctuation">.</span>Stop<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">// rest of the details</span>
</span><span class="code-line">    <span class="token keyword">if</span><span class="token punctuation">(</span>currentNode <span class="token keyword">is</span> <span class="token class-name">GroupingNode</span> _<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        groupingNode <span class="token operator">=</span> IdentifiedGroupingNode<span class="token punctuation">.</span>Found<span class="token punctuation">;</span> <span class="token comment">// 👈 3. identify a GroupingNode</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token comment">// rest of the details</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>That is kind of surprising, isn&#x27;t it?</p><p>What&#x27;s more, we didn&#x27;t change the algorithm yet.</p><p>We firstly evolved the model.</p><p>&quot;Again&quot;.</p><p>Now probably it&#x27;s time to evolve the behavior to fix the bug we were originally assigned to.</p><p>But one can notice that the decision how to answer the question is no longer available in the <code>ImportantTraversalAlgorithm</code> method.</p><p>It is not longer responsible for that.</p><p>The responsibility to provide the answer was moved to a designated &quot;structure&quot;:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">private</span> <span class="token keyword">abstract</span> <span class="token keyword">record</span> <span class="token class-name">IdentifiedGroupingNode</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">abstract</span> <span class="token class-name return-type"><span class="token keyword">bool</span></span> <span class="token function">IsIdentifiedFor</span><span class="token punctuation">(</span><span class="token class-name">Node</span> node<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name return-type">IdentifiedGroupingNode</span> NotFound <span class="token operator">=&gt;</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">NoGroupingNodeFound</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name return-type">IdentifiedGroupingNode</span> <span class="token function">Found</span><span class="token punctuation">(</span><span class="token class-name">GroupingNode</span> groupingNode<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> 
</span><span class="code-line">        <span class="token keyword">new</span> <span class="token class-name constructor-invocation">GroupingNodeFound</span><span class="token punctuation">(</span>groupingNode<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">private</span> <span class="token keyword">sealed</span> <span class="token keyword">record</span> <span class="token class-name">NoGroupingNodeFound</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">IdentifiedGroupingNode</span></span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">public</span> <span class="token keyword">override</span> <span class="token class-name return-type"><span class="token keyword">bool</span></span> <span class="token function">IsIdentifiedFor</span><span class="token punctuation">(</span><span class="token class-name">Node</span> node<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">// 👇 now our model requires additional information to be able to answer the question</span>
</span><span class="code-line">    <span class="token keyword">private</span> <span class="token keyword">sealed</span> <span class="token keyword">record</span> <span class="token class-name">GroupingNodeFound</span><span class="token punctuation">(</span><span class="token class-name">GroupingNode</span> GroupingNode<span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">IdentifiedGroupingNode</span></span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">public</span> <span class="token keyword">override</span> <span class="token class-name return-type"><span class="token keyword">bool</span></span> <span class="token function">IsIdentifiedFor</span><span class="token punctuation">(</span><span class="token class-name">Node</span> node<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> 
</span><span class="code-line">            GroupingNode<span class="token punctuation">.</span><span class="token function">Groups</span><span class="token punctuation">(</span>node<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>And this little change causes a compilation error which we happily fix:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token class-name return-type">IEnumerable<span class="token punctuation">&lt;</span>Node<span class="token punctuation">&gt;</span></span> <span class="token function">ImportantTraversalAlgorithm</span><span class="token punctuation">(</span><span class="token class-name">Node</span> node<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// existing initialization</span>
</span><span class="code-line">    <span class="token class-name">IdentifiedGroupingNode</span> groupingNode <span class="token operator">=</span>
</span><span class="code-line">        IdentifiedGroupingNode<span class="token punctuation">.</span>NotFound<span class="token punctuation">;</span> <span class="token comment">// 👈 1. initialize as no GroupingNode found</span>
</span><span class="code-line">    <span class="token comment">// details of the algorithm</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">if</span><span class="token punctuation">(</span>groupingNode<span class="token punctuation">.</span><span class="token function">IsIdentifiedFor</span><span class="token punctuation">(</span>currentNode<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// 👈 2. model answering the question</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">return</span> Traversal<span class="token punctuation">.</span>Stop<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">// rest of the details</span>
</span><span class="code-line">    <span class="token keyword">if</span><span class="token punctuation">(</span>currentNode <span class="token keyword">is</span> <span class="token class-name">GroupingNode</span> _groupingNode<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        groupingNode <span class="token operator">=</span> IdentifiedGroupingNode<span class="token punctuation">.</span><span class="token function">Found</span><span class="token punctuation">(</span>_groupingNode<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 👈 3. identify a GroupingNode</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token comment">// rest of the details</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>We did checks and it turned out that everything is working as expected.</p><p>What&#x27;s interesting, we also started talking about identified grouping node in a slightly different way.</p><p>Do you know why?</p><h3 id="models-evolve-dont-hack"><a href="#models-evolve-dont-hack" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Models: evolve, don&#x27;t hack</h3><p>You might be thinking dear Reader: &quot;wow Damian, you turned a simple bool into a object-oriented pile of c..lasses&quot;.</p><p>Actually, records, but yes - I hear you, dear Reader.</p><p>We experienced an evolution from a simple <code>bool</code> into a larger structure.</p><p>Some might whipser: &quot;mother of god, was it worth it?&quot;</p><p><a href="https://talesfrom.dev/blog/i-dont-know">I don&#x27;t know</a> - the time will reveal the truth.</p><p>However, I would ask another question - why didn&#x27;t we start with a larger structure from the early beginning?</p><p>We could use it as the <a href="https://talesfrom.dev/blog/evolve-dont-hack#1-model">#1 Model</a> and then even less changes will be needed.</p><p>&quot;KISS, YAGNI&quot; - I hear immediately in the back of my head. (is everything alright? do you hear voices too?)</p><p>And in fact - we didn&#x27;t need such structure from the first moments.</p><p>But as the reality challenged our model, it turned out it is not enough.</p><p>Up to that time, it was Just Enough Model™.</p><h3 id="hacking"><a href="#hacking" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Hacking?</h3><p>I would consider the <a href="https://talesfrom.dev/blog/evolve-dont-hack#2-model">#2 Model</a> a hack, a workaround, and not a right solution.</p><p>Not because I &quot;love complexity&quot; (as some KISS-lovers might state), but because it did not provide a right place to accomodate further changes.</p><p>The problem manifested once, might eventually manifest itself.</p><p>Is it a speculation? Yes, of course.</p><p>A little bit of speculation on that level is justifiable.</p><p><a href="https://www.linkedin.com/feed/update/urn:li:activity:7300483997862649857/">&quot;Working in the absence of knowledge is the job&quot;</a>.</p><p>Why &quot;Hacking&quot;? Because it works <strong>for me, now</strong>.</p><p>When another person comes, he or she might &quot;just want to fix the bug&quot; and move on.</p><p>Will it work for other person (including future me), in the future?</p><p><code>ImportantTraversalAlgorithm</code> will grow.</p><p>It will get more and more responsibilities.</p><p>More &quot;logic&quot; will land in its hands until it will collapse under its weight (you might be interested in <a href="https://talesfrom.dev/blog/a-solid-grasp-of-responsibility">A solid grasp of responsibility</a>).</p><p>Did all the 2000LOC+ friends happen over a single sprint?</p><h3 id="evolving"><a href="#evolving" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Evolving?</h3><p>&quot;But now it&#x27;s hidden from the sight and it&#x27;s not explicit how does it work!&quot;, some might shout (in their heads).</p><p>Is the current model &quot;easy&quot;? No.</p><p>Is the current model &quot;simple&quot;?</p><p>I have never told that <a href="https://talesfrom.dev/blog/evolve-dont-hack#3-model">#3 Model</a> is free from downsides.</p><p>I made a trade.</p><p>I made a trade by picking options in the future by providing &quot;a structure&quot; that will accomodate changes within its area of responsibilities, instead of assigning those responsibilities to our <code>ImportantTraversalAlgorithm</code>.</p><p>I made a gamble that expressing the right language is far more important that &quot;simple&quot; (in fact easy, see <a href="https://talesfrom.dev/blog/simple-isnt-easy">Simple isn&#x27;t easy</a>), &quot;first-thought&quot; solution.</p><p>Could I have used different structure?</p><p><a href="https://tenor.com/en-GB/view/michael-scott-am-ia-hero-hero-gif-27082688">Well, I can&#x27;t really say, but yes.</a>.</p><p>As I expressed in <a href="essentially-bounded-accidentally-unlimited">Essentially bounded, Accidentally unlimited</a>:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>There is no single solution, but there is a single problem.</p></div></div></div><p>In the <a href="https://talesfrom.dev/blog/evolve-dont-hack#2-bugs-strike-back">#2 Bugs strike back</a>, we needed to express a closed set of variants (that&#x27;s why a <code>bool</code> was not sufficient).</p><p>We could use <a href="https://www.nuget.org/packages/OneOf">OneOf</a> nuget package and use discriminated unions.</p><p>The most important aspect is that we evolved the model by refactoring the structure (a <code>bool</code> is a data <em>structure</em>).</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Make the change easy, then make the easy change</p></div></div></div><p>That&#x27;s why &quot;refactoring sprints&quot; or &quot;tech debt maintaince sprints&quot; are harmful and pointless.</p><p>&quot;Knowledge structures&quot; (essentially representations of our understanding of the problem) are attracting more and more changes.</p><p>They tend to &quot;grow knowledge belly fat&quot; rapidly.</p><p>Of course, modularization, thoughtful responsibilities assignment and encapsulation might help us limiting the scope of the possible changes.</p><p>But one needs to design systems and applications really mindfully so structures yield those attributes.</p><h3 id="hacking-or-evolving"><a href="#hacking-or-evolving" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Hacking or evolving?</h3><p>Even if the <a href="https://talesfrom.dev/blog/evolve-dont-hack#3-model">#3 Model</a> is &quot;larger&quot;, it has clear purposes.</p><p>No solution is free from disadvantages that&#x27;s why we need to be aware of the trades we make.</p><p>Models need to evolve to provide business value, no matter how small they are.</p><p>One of such values is the ability to change the &quot;code&quot; in an easy way.</p><p>Sometimes we need to make that &quot;easy way&quot; happening by representing concepts (<a href="https://talesfrom.dev/blog/concepts-entities-data">Concepts, Entities, Data</a>) and letting them do the job.</p><p>We should still start with the question:</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>What is the simplest possible model that answers the main question?</p></div></div></div><p>Which forces us to find <a href="https://kiriakakis.net/comics/mused/a-day-at-the-park">the right question</a>.</p><p>But it is merely a start.</p><p>So next time dear Reader, if you have an assignment to fix a bug or provide a new capability, remember:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Evolve models, don&#x27;t hack them</p></div></div></div>]]></content:encoded>
    <pubDate>Sun, 30 Mar 2025 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>domain modeling</category><category>contextual models</category><category>modeling</category><category>software design</category><category>problem space</category><category>domain-driven design</category><category>software architecture</category><category>strategic thinking</category><category>business capabilities</category><category>software design</category><category>design thinking</category><category>knowledge working</category><category>patterns</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/context-segregation-principle</guid>
    <title>Context Segregation Principle</title>
    <link>https://talesfrom.dev/blog/context-segregation-principle</link>
    <description>is there a single unified way of looking at reality?</description>
    <content:encoded><![CDATA[<div class="bg-slate-600 rounded-xl "><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Attention!</span></div><div class="pb-2 px-3"><div class="break-words"><p>This blogpost is based on the narrative started in one of the previous posts: <a href="https://talesfrom.dev/blog/modeling-maturity-levels">Modeling Maturity Levels</a>.</p>
<p>I greatly encourage reading it in the first place.</p></div></div></div><h3 id="what-is-a-laminate-panel-made-of"><a href="#what-is-a-laminate-panel-made-of" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What is a laminate panel made of?</h3><p>Imagine a person named Sam who is the sales person of a company selling floor panels.</p><p>He knows dozen of various &quot;flavours&quot; - laminate, real wood, vinyl, etc. - and he is able to explain the differences between them to a customer. He knows the pros and cons of each type of panel, and he can help the customer to choose the best one for their needs.</p><p>He works in this part of the business about 15 years - he saw how it all progressed and how materials were changing along the way.</p><p>Sam was asked by his boss to drive to the clostest warehouse and check a very special order that should be shipped.</p><p>&quot;It&#x27;s a personal thing, Sam&quot;, said the boss, &quot;so I need you to check it, personally. This a real wood panel, made from a exclusive, exotic type of wood - African blackwood&quot;.</p><p>Our hero did it without a further ado.</p><p>Sam the salesman went into the warehouse. He was there multiplte times so he knew the place well.</p><p>He knew the people working there, their duties and responsibilities.</p><p>Sam noticed a warehouse worker who was moving a pallet of laminate panels so he started conversation.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><span class=""><span class="italic font-bold text-red-500">Sam</span>: How is it going William?</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-blue-500">William</span>: Hi there, Sam! Tons of work, you know. What do you need?</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-red-500">Sam</span>: Boss wanted me to check an order - something very important for him, hence important for me.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-blue-500">William</span>: Got order reference?</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-red-500">Sam</span>: Hmm, not really. Boss mentioned over the phone you will know it all.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-blue-500">William</span>: Sam, we are processing hundreds of orders each day. It is simply impossible that...</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-red-500">Sam</span>: Will, Will...Every person would recognize African blackwood...</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-blue-500">William</span>: Panel is just a panel - we store and ship thousands of them. I need an order reference, Sam.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-red-500">Sam</span>: JUST A PANEL?</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-blue-500">William</span>: Does it have extraordinary size? Extraordinary weight? Or maybe it needs to be kept in those advanced conditions?</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-red-500">Sam</span>: Extraordinary weight? It has a typical size that goes within the range, but when it comes to exclusiveness... Then African Blackwood is one of the rarest and most highly prized woods in the world, harvested from the Dalbergia melanoxylon tree, which grows in the eastern and southern regions of Africa. Each panel is unique, featuring a characteristic deep, almost black color with subtle purple and brown nuances that create a hypnotic effect in any interior.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-blue-500">William</span>: I need order reference, Sam. Can&#x27;t you call the boss?</span></span></div><p>This short discussion seemed to take ages. Sam was getting nervous.</p><p>How could this ignorant warehouse worker not know what African blackwood is?</p><p>Every person working in that business knows how precious, rare and unique this wood is!</p><p>Calling boss? If the boss would hear that Sam wasn&#x27;t able to recognize the African blackwood panel, he would think that Sam is really shitty salesman.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><span class=""><span class="italic font-bold text-red-500">Sam</span>: Will, I DON&#x27;T HAVE THE DAMN REFERENCE, just show me where exclusive panels are.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-blue-500">William</span>: Well, that&#x27;s not how it works, Sam. We typically do not...</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-red-500">Sam</span>: How did you ever made through in a floor panel industry with such incomplete knowledge?</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-blue-500">William</span>: Floor panel industry? I store things on shelves and pick them up to fulfill the order - that&#x27;s my job, not to mention restocking...</span></span></div><p>During this conversation Will was able to receive couple of new orders and reject some of them, as he checked that they had shortage of a specific batches in stock.</p><h3 id="why-laminates-color-does-not-matter"><a href="#why-laminates-color-does-not-matter" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Why laminate&#x27;s color does not matter?</h3><p>Sam sneaked into the warehouse and started to look for the exclusive panels. As Will told him, he was not able to find them.</p><p>At least not that easily as Sam thought.</p><p>Finally, he found what boss challenged him to take care of.</p><p>Sam reported the progress to his boss and got next orders: &quot;Take one panel and call Igor, the installer. You both drive to the customer and check if it fits.&quot;</p><p>And then the boss hang up.</p><p>Sam organized everything - summoned Igor, took the panel and drove to the customer.</p><p>The apartment was really...Breathtaking.</p><p>One of the rooms didn&#x27;t have a floor yet - it was just a concrete base, so that&#x27;s where the panel was supposed to be installed.</p><p>So Sam started the conversation with Igor.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><span class=""><span class="italic font-bold text-red-500">Sam</span>: Ok, let&#x27;s put it on the floor and we will see if it fits, as the boss wanted to confirm.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-green-500">Igor</span>: We have only one panel so how could it not fit?</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-red-500">Sam</span>: Pardon?</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-green-500">Igor</span>: Installing panels is like a jigsaw puzzle solving - with the difference you can cut them to make them fit.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-red-500">Sam</span>: You must be kidding, Igor...</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-green-500">Igor</span>: Not at all! Look over there - there&#x27;s a curved wall - I would need to cut the panels to...</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-red-500">Sam</span>: I know how to install panels, Igor.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-green-500">Igor</span>: Oh really, Mr. Egghead-I-Know-How-To-Cut-Panels? So tell me how to cut and then glue vinyl panels?</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-red-500">Sam</span>: When the boss asked us to check <i>if the panel fits</i>, he thought about the <span class="font-bold">experience</span> that it brings.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-green-500">Igor</span>: Oh belive me Sam, putting low quality laminate panels on the ground is a god damn experience...</span></span></div><p>Once again, Sam was amazed how incompenent people are - if the boss knew that Igor is such a smartass, especially when it comes to African blackwood knowledge, he would never hire him.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><span class=""><span class="italic font-bold text-red-500">Sam</span>: Igor, you are not getting the point. Boss wanted us to check if African blackwood matches the spirit of this space, of this room. This color does not like rooms where the light bends in a certain way so that...</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-green-500">Igor</span>: Sam, I am an installer. I put panels on the floor. I do not care about the color of the panel, I care about the quality of the material and montaging it properly.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-red-500">Sam</span>: So from your perspective Igor, would the African panel fit this space?</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-green-500">Igor</span>: I told you Sam - I am able to make any panel fit any space - whether it is African blackwood, European whiteoak or Chinese bamboo.</span></span></div><p>At least the discussion with Igor was shorter than with Will.</p><p>After experiencing storage and installation perspectives, and frustrations that came with them, Sam started to think about the context of the problem he was facing.</p><p>Seemed like he was the only one who truly knew the potential of the African blackwood.</p><p>It wasn&#x27;t a surprise that the boss asked him to check the order personally - Sam&#x27;s magficent knowledge about the products portfolio and details of each materials was well known in the company.</p><p>Sam felt the urge to report back to the boss and tell him that the panel fits the room perfectly.</p><h3 id="how-to-negotiate-using-a-floor-panel"><a href="#how-to-negotiate-using-a-floor-panel" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>How to negotiate using a floor panel?</h3><p>Sam drove to the HQ and went straight to the boss office.</p><p>He was waiting for the boss to finish the call, possibly with another important customer.</p><p>Finally, the boss hang up and looked at Sam, who was standing in front of his desk.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><span class=""><span class="italic font-bold text-red-500">Sam</span>: Boss, I have checked the order personally. The panel fits the room perfectly. It will bring the overall experience to the next levels. Believe me.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-violet-500">Boss</span>: What are you talking about, Sam?</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-red-500">Sam</span>: Sunlight traverses the executive suite, striking the African blackwood panel with golden precision. Like twilight settling over the savannah, the deep ebony surface absorbs light, yet releases hidden violet undertones when caressed by direct rays. For African wood will make the customer be looked as cheetah sizing its prey, eyes fixated on the hypnotic grain patterns that ripple like tall grasses in wind. Where light catches the polished edge, it creates a mirage-like shimmer—the same illusion that dances above sun-baked plains. Even in the corporate jungle, the wood commands attention, drawing everyone&#x27;s gaze with the same magnetic pull as a watering hole in drought.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-violet-500">Boss</span>: Sam, I don&#x27;t have time for those salesman games. Did the customer confirmed that the panel fits his &quot;blackness&quot; definition?</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-red-500">Sam</span>: Well, there was no customer in that apartement, only a secretary let us in.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-violet-500">Boss</span>: So you are telling me that you haven&#x27;t spoken to the customer yet?</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-red-500">Sam</span>: Boss, you told me to check if it fits the experience so I thought...</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-violet-500">Boss</span>: I said you go there and check if it fits customer&#x27;s image of this panel - last week we played poker and the guy said that African blackwood isn&#x27;t truly black and he would never let it be installed in his office. I said I will bring the finest African blackwood panels and install them for free.</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-red-500">Sam</span>: ...</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold text-violet-500">Boss</span>: He&#x27;s a big player - he has offices in most of the capitol cities in many countries in the Europe. I really thought he could get convinced and order huge batch of those panels for executive offices.</span></span></div><p>Boss was speechless - he couldn&#x27;t believe that Sam was so incompenent.</p><p>He knew that Sam was a great salesman, but he didn&#x27;t know that he is so detached from the reality.</p><h3 id="perspectives"><a href="#perspectives" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Perspectives?</h3><p>Ok, let&#x27;s stop here for a while, dear Reader.</p><p>You might be wondering - what the hell have we just wittnessed and how does it relate to software engineering?!</p><p>Possibly, the first thing that might come to one&#x27;s mind is that it was a classic example of a communication breakdown.</p><p>Assumptions all down the way which made it all wrecked.</p><p>Who didn&#x27;t experience such a situation in their life or work - where people throw invisible concepts into the discussion somehow expecting that the other side <em>knows</em> what they are talking about?</p><p>We could say that the language truly made the difference - all talked about the same thing, but from different perspectives, isn&#x27;t it?</p><p>In this particular toy example, it&#x27;s pretty easy case as &quot;floor panels&quot; are visible, tangible things - you can touch them, see them, &quot;cut them&quot;.</p><p>Worse if we move to &quot;abstract&quot; concepts like &quot;processes&quot; - &quot;installation process&quot;, &quot;negotiation process&quot;, &quot;sales process&quot;, and so on.</p><p>They might be strictly connected to real, physical world, but still our reasoning, our understanding of them, lies in the &quot;abstract thinking&quot; - as we use language to (im)precisely describe it all. (you might be interested in <a href="https://talesfrom.dev/blog/language-of-the-problem">Language of the problem</a>).</p><p>Language might work as a strong signal toward searching various perspectives, as in our tiny tale.</p><p>Those perspectives might contribute to totally different thinking about the &quot;problem&quot; - here about floor panels.</p><h3 id="modeling-maturity-levels"><a href="#modeling-maturity-levels" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Modeling Maturity Levels</h3><p>In one of the previous tales - <a href="https://talesfrom.dev/blog/modeling-maturity-levels">Modeling Maturity Levels</a>, we explored differences between levels and perspectives, especially when it comes to &quot;Being/Behaving/Becoming&quot;.</p><p>If you haven&#x27;t seen it, dear Reader, I think it&#x27;s good moment to take a look at it, as we are going to deepen this way of thinking further.</p><p>Ok, buckle up!</p><p>One of the conclusions was that we might model the same thing using various levels, depending on understanding which leads to proper design decisions.</p><p>As in the theme from <a href="https://talesfrom.dev/blog/modeling-maturity-levels">Modeling Maturity Levels</a>, we were able to observe how various perspectives look at the same thing - &quot;a floor panel&quot;.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/context-segregation-princinple-perspectives.png" class="max-h-[30rem]"/></div><div class="italic mx-24">Looking from different perspectives</div></div><p>Each of the people had a specific concept, a specific abstraction of the &quot;floor panel&quot; in their minds.</p><p>Sam could be thinking of it as &quot;something contributing to the experience&quot;.</p><p>Will could be thinking of it as &quot;something that needs to be stored and gave away&quot;.</p><p>Igor could be thinking of it as &quot;something that needs to be installed&quot;.</p><p>Boss could be thinking of it as &quot;something that leverages negotations&quot;.</p><p>Each perspective brings different context in the game - and as we already know, with context comes the meaning, which brings certain rules, policies and other concepts.</p><h3 id="there-is-no-floor-panel"><a href="#there-is-no-floor-panel" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;There is no floor panel&quot;</h3><p>Is there one, central, universal concept of a &quot;floor panel&quot;?</p><p>In a way - yes, there&#x27;s a physical object that we can interact with, although while interacting with it, we would immediately contextualize our sight toward a particular aspect or aspects of it.</p><p>Hence, one would get &quot;Sam&#x27;s floor panel&quot;, &quot;Will&#x27;s floor panel&quot;, &quot;Igor&#x27;s floor panel&quot;, &quot;Boss&#x27; floor panel&quot;, and more.</p><p>All characters in this tiny tale might represent certain roles in the business - sales, warehouse, installation, management.</p><p>Each of them segregated &quot;a floor panel&quot; concept into their a particular context, in which they are applying their knoweldge, skills, and experience (you might be interested in <a href="https://talesfrom.dev/blog/the-ambiguity-of-application">The ambiguity of application</a>).</p><p>Such segregration is an essence of the abstraction - &quot;focusing on what is relevant, ignoring what is irrelevant&quot;.</p><p>And the goal is not reusability, but the ability think about the concept in a very specific way (you might be interested in <a href="https://talesfrom.dev/blog/the-ambiguity-of-abstraction">The ambiguity of abstraction</a>).</p><p>So if one starts with a central abstract idea of &quot;a floor panel&quot;:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">FloorPanel</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> Material <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> Color <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">int</span></span> ExclusivenessLevel <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token punctuation">(</span><span class="token keyword">double</span><span class="token punctuation">,</span> <span class="token keyword">double</span><span class="token punctuation">,</span> <span class="token keyword">double</span><span class="token punctuation">)</span></span> Dimensions <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> InstallationType <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">double</span></span> Price <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">double</span></span> Weight <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>And then taking possible interactions that one can have with &quot;a floor panel&quot;:</p><ul><li>Sam&#x27;s interaction - &quot;selling the experience&quot;</li><li>Will&#x27;s interaction - &quot;storing&quot;</li><li>Igor&#x27;s interaction - &quot;installing&quot;</li><li>Boss&#x27; interaction - &quot;negotiating&quot;</li></ul><p><code>FloorPanel</code> might play various roles, depending on the context:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">FloorPanel</span> <span class="token punctuation">:</span> 
</span><span class="code-line">            <span class="token type-list"><span class="token class-name">ICanBeSold</span><span class="token punctuation">,</span>
</span></span><span class="code-line"><span class="token type-list">            <span class="token class-name">ICanBeStored</span><span class="token punctuation">,</span>
</span></span><span class="code-line"><span class="token type-list">            <span class="token class-name">ICanBeInstalled</span><span class="token punctuation">,</span>
</span></span><span class="code-line"><span class="token type-list">            <span class="token class-name">ICanBeNegotationLevarage</span></span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> Material <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> Color <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">int</span></span> ExclusivenessLevel <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token punctuation">(</span><span class="token keyword">double</span><span class="token punctuation">,</span> <span class="token keyword">double</span><span class="token punctuation">,</span> <span class="token keyword">double</span><span class="token punctuation">)</span></span> Dimensions <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> InstallationType <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">double</span></span> Price <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">double</span></span> Weight <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token comment">// many, many more *properties* and *types of interactions*!</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Note that I used specific .NET notation for interfaces - prefixed with &quot;I&quot; - if one drops it it still preserves the meaning (but you might be still interested in reading one I think it&#x27;s a very powerful technique for software design - <a href="https://talesfrom.dev/blog/i-interface">I, interface</a>).</p><p>Until now, nothing has changed.</p><p>Let&#x27;s apply contextual segregation.</p><h3 id="contextual-models"><a href="#contextual-models" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Contextual models</h3><p>Each of the roles that a <code>FloorPanel</code> might play, has a set of specific behaviors related to it, which require only a subset of the &quot;properties&quot; of the original <code>FloorPanel</code>:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">ICanBeSold</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> Material <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> Color <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">double</span></span> Price <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">ICanBeStored</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token punctuation">(</span><span class="token keyword">double</span><span class="token punctuation">,</span> <span class="token keyword">double</span><span class="token punctuation">,</span> <span class="token keyword">double</span><span class="token punctuation">)</span></span> Dimensions <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">double</span></span> Weight <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">ICanBeInstalled</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> Material <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token punctuation">(</span><span class="token keyword">double</span><span class="token punctuation">,</span> <span class="token keyword">double</span><span class="token punctuation">,</span> <span class="token keyword">double</span><span class="token punctuation">)</span></span> Dimensions <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> InstallationType <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">ICanBeNegotationLevarage</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">int</span></span> ExclusivenessLevel <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">double</span></span> Price <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Of course, some contexts might, and probably will, require certain information to be available to deliver its capabilities correctly.</p><p>And this means it might seem that those information are &quot;duplicated&quot;.</p><p>But the point is that the context is the king - it defines what is relevant and what is not.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/context-segregation-princinple-roles.png" class="max-h-[30rem]"/></div><div class="italic mx-24">a <code>FloorPanel</code> playing various roles</div></div><p>If we could explore each context, it might turn out that there contextual names, related to each perspective.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/context-segregation-princinple-language.png" class="max-h-[30rem]"/></div><div class="italic mx-24">different names, based on the context</div></div><p>And finally, a <code>FloorPanel</code> might be &quot;created&quot; by composing all of the contexts together - but only when there is a need for such interaction, not just to &quot;have it&quot;, but &quot;to use it&quot;.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">abstract</span> <span class="token keyword">class</span> <span class="token class-name">FloorPanel</span><span class="token punctuation">:</span>
</span><span class="code-line">    <span class="token type-list"><span class="token class-name">Product</span><span class="token punctuation">,</span>
</span></span><span class="code-line"><span class="token type-list">    <span class="token class-name">InventoryItem</span><span class="token punctuation">,</span>
</span></span><span class="code-line"><span class="token type-list">    <span class="token class-name">InstallationMaterial</span><span class="token punctuation">,</span>
</span></span><span class="code-line"><span class="token type-list">    <span class="token class-name">RelationshipToken</span></span>
</span><span class="code-line">    <span class="token comment">// many, many more *contexts*!</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// many, many *properties* and *types of interactions*!</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><h3 id="context-segregation-principle"><a href="#context-segregation-principle" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Context Segregation Principle</h3><p>Abstracting, by definition, means that one cannot model the &quot;reality&quot;.</p><p>Central concepts like <code>User</code>, <code>Product</code>, <code>Order</code> or <code>Appointment</code> lure us into such thinking as there are &quot;visible&quot; - during conversations and in our software.</p><p>People speak about them as if there were &quot;tangible&quot;, almost &quot;touchable&quot;, but those are just shortcuts to the real <strong>abstractions</strong> that are highly contextual.</p><p>In our work, we might be tempted to create a single, unified model that would cover all possible interactions, all possible contexts, all possible perspectives.</p><p>But we all know where does it leads - to models behaving as the &quot;god object&quot;, luring into a muddy terain where everything is connected with everything.</p><p>Instead, we should focus on segregating the contexts, by taking into account the usage, the interactions with &quot;a concept&quot;, and then model it accordingly.</p><p>Operations, actions, behaviors, ways of interacting, are going to guide us toward information needed.</p><p>To me, this is one of the most important aspects of Domain-Driven Design - thinking in terms of contextual models, each specialized in solving a particular problem or a set of problems.</p><p>Such contextual models can provide answers to questions, behaving as an authority, an expert, for a particular (sub)area of the business.</p><p>Playing a role of a single source of truth.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Different contexts require different abstractions of the same concept, each emphasizing only what is relevant to that specific perspective while intentionally ignoring what is irrelevant.</p></div></div></div><p>Probably nowadays no one would create a single abstract class <code>FloorPanel</code>, implementing strangely looking abstract classes or interfaces (I hope so, dear God).</p><p>Instead, there will be a way of composing all contexts by using an identifier:</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/context-segregation-princinple-composition.png" class="max-h-[30rem]"/></div><div class="italic mx-24">all contexts connected through a single identifier</div></div><p>One could say that in a way a <code>FloorPanel</code> stopped existing, even though people might still use this term in conversations.</p><p>Kind of Schrödinger&#x27;s floor panel - existing and not existing at the same time.</p><h3 id="so-what"><a href="#so-what" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>So what?</h3><p>Some of you might think: &quot;no way it can be practical, Damian&quot;</p><p>We should probably define what does &quot;practical&quot; mean in this context (pun intended).</p><p>I don&#x27;t think it will help you improve your deployment pipeline.</p><p>Same with the way one runs database migrations.</p><p>But can such a way of thinking help when doing modeling and software design?</p><p>Think about it, dear Reader, what is your &quot;floor panel&quot;?</p><p>Do you have a model that combines many perspectives, includes many contexts, and plays various roles?</p><p>What would happen if you would segregate those contexts, and model them separately?</p><p>In DDD, there&#x27;s a concept of <em>a bounded context</em>.</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">Bounded Context (one of possible definitions)</div><div class="pb-2 px-3"><div class="break-words"><p>An area inside which a particular model is applicable</p></div></div></div><p>It represents our way of solving things, stressing out the importance of the language, the meaning - hence the abstractions.</p><p>Thus, one could say that within a specific bounded context, contextual models live.</p><p>What would be the <a href="https://talesfrom.dev/blog/modeling-maturity-levels">level</a> that one is going to build those contextual models - that&#x27;s a different story.</p><p>And that&#x27;s where truly Domain-Driven Design really shines - we need to orient our thinking toward business (sub)areas to see problems contextually, find perspectives and seek for proper abstractions.</p><p>Some of the problems might involve transactional processing, some of them might be related to timeseries analysis, and others might be linked to handling everchanging business rules.</p><p>Each of those problems require highly specialized, contextual model - a solution that can answer important questions posed by the business.</p><h3 id="contexts-not-domains"><a href="#contexts-not-domains" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Contexts, not Domains?</h3><p>You might be wondering, dear Reader, why I phrased it as &quot;Context Segregation Principle&quot;, especially when I strongly relate to Domain-Driven Design.</p><p>Shouldn&#x27;t it be named as &quot;Domain Segregation Principle&quot;?</p><p>I was playing with the idea for a while and it seems to be that this &quot;principle&quot; directly corresponds to <em>Bounded Contexts</em> - we design them by organizing boundaries and assigning responsibilities accordingly.</p><p>As we are consciously doing so (hopefully), it means that segregation to contextual models also is an act of a designing, whereas &quot;domains&quot; are there - to be explored, to be understood, to be interacted with to provide those models, so that we are able to satisfy business needs and solve business problems (and make frigging moneyz!)</p><p>I considered also naming it as &quot;Abstraction Segregation Principle&quot; but it seemed to be too abstract (pun intended), and kind of disconnected from the business.</p><h3 id="whats-next"><a href="#whats-next" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What&#x27;s next?</h3><p>Go. Go, observe and try to find your &quot;floor panel&quot;, dear Reader.</p><p>I know that I left you without any tools, any heuristics or any guidelines.</p><p>If I could give one starter advice, it would be to look for the behaviors and ways people interact with the concept.</p><p>Behavior (verbs) carry the context. With the context, meaning comes. And after meaning, rules appear.</p><p>And rules, in order to be satisfied, need information.</p><p>All these will flock together, revealing seams - but only if you are willing to take various perspectives.</p><p>Actively.</p><p>Consciously.</p><p>Happy contextualizing!</p>]]></content:encoded>
    <pubDate>Mon, 24 Mar 2025 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>domain modeling</category><category>contextual models</category><category>modeling</category><category>software design</category><category>problem space</category><category>domain-driven design</category><category>software architecture</category><category>strategic thinking</category><category>business capabilities</category><category>software design</category><category>design thinking</category><category>knowledge working</category><category>patterns</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/the-ambiguity-of-problems</guid>
    <title>The ambiguity of problems</title>
    <link>https://talesfrom.dev/blog/the-ambiguity-of-problems</link>
    <description>What if problems whisper to us?</description>
    <content:encoded><![CDATA[<h3 id="411-tests"><a href="#411-tests" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>411 tests?</h3><p>Imagine that we work on a feature that requries doing some work around <code>VeryImportantGraphAnalyzer</code> class.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">VeryImportantGraphAnalyzer</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line"><span class="token keyword">public</span> <span class="token function">VeryImportantGraphAnalyzer</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token class-name">IGraphBuilder</span> graphBuilder<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">IGraphValidator</span> graphValidator<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">IGraphShuffler</span> graphShuffler<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">INodeFinder</span> nodeFinder<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">IEdgeComposer</span> edgeComposer
</span><span class="code-line">    <span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">//...</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Usually it is a pleasure to work with it - the domain is so interesting - computer science at its essence!</p><p>We follow &quot;best practices&quot; - we have a lot of tests around it. This brings the feeling of safety and confidence.</p><p>Turns out that in order to implement the feature we need to change the class itself - two new methods are required, and to provide new functionality, <code>VeryImportantGraphAnalyzer</code> needs to get some new collaborators invited to help witht the job (collaborators? invited? You might be interested in <a href="https://talesfrom.dev/blog/the-ambiguity-of-composition">The ambiguity of composition</a>).</p><p>We usually try to follow TDD, but this time we are in a hurry (who isn&#x27;t, right?) so we decide to check what is the scope of changes.</p><p>Let&#x27;s just add two new collaborators that we think we might need to implement the feature.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">VeryImportantGraphAnalyzer</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line"><span class="token keyword">public</span> <span class="token function">VeryImportantGraphAnalyzer</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token class-name">IGraphBuilder</span> graphBuilder<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">IGraphValidator</span> graphValidator<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">IGraphShuffler</span> graphShuffler<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">INodeFinder</span> nodeFinder<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">IEdgeComposer</span> edgeComposer<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">ICollisionDetector</span> collisionDetector<span class="token punctuation">,</span> <span class="token comment">// 👈🏻 new collaborator!</span>
</span><span class="code-line">        IAreaBuilder areaBuilder <span class="token comment">// 👈🏻 new collaborator!</span>
</span><span class="code-line">    <span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">//...</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>We run tests aaaand... 411 tests out of 2598 failed <span class="text-red-600">❌</span> .</p><p>Well, tests should help us but somehow it does not feel right.</p><p>We&#x27;ve heard stories that people are moaning about &quot;how a single method caused 4 days of tests fixing&quot; - maybe that&#x27;s the case too?</p><p>After some minutes of being alone with the <code>VeryImportantGraphAnalyzer</code> class, we see it grew a bit...Too much?</p><p>Well, it&#x27;s only 1458 lines of code now. Could be worse.</p><p>Everything is centralized, easy to find out what is going on. We have a lot of tests, maybe some are broken now, but we can fix them.</p><p>During the next daily we just say that we need to refactor the class a bit and that this might take up to 2 days.</p><p>&quot;Ok, next&quot;, we hear and we get back to the production line.</p><h3 id="10-days"><a href="#10-days" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>10 days?</h3><p>Turned out that the feature is now complete and ready for testing. Now it&#x27;s time for QA engineers to shine and to shoot at our work.</p><p>We can grab another task from the backlog and start working on it.</p><p>Fortunately or unfortunately, along with our change other features were also added so it&#x27;s pretty hard to isolate just our feature.</p><p>Each deployment takes at least couple of hours so we need to be really careful with what we are deploying.</p><p>In case of failure, we need to rollback but thanks God it can be done within 2 hours at most.</p><p>Product owner is a bit nervous - the feature was supposed to be already available, now it&#x27;s 10 days and we are still not sure if it&#x27;s working.</p><p>&quot;Feature freeze&quot; is announced - no new features until the current one is deployed.</p><p>But developers can&#x27;t just sit and &quot;do nothing&quot; - &quot;time for maintenance sprint&quot; - Product Owner says.</p><p>QA Engineers, Developers, Product Owner work together to test everything, just to make sure.</p><p>Finally, all features are deployed. The customer picks it up and... There&#x27;s a failure due to specific customer configuration in production.</p><p>&quot;Start rollback procedure&quot; we hear and almost automatically we start to do it.</p><h3 id="in-2-weeks"><a href="#in-2-weeks" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>In 2 weeks?</h3><p>The problem with configuration was resolved - turned out that no one actually tested this particular combination of settings.</p><p>We added another step in approval process so that this won&#x27;t happen again.</p><p>We are safe.</p><p>Feature lock was released so now we can get back to business as usual - daily standups, people giving their status, grabbing tasks from the backlog and going to the workstations to increment the product.</p><p>During the dependency analysis the team sees that one of the next features requires help from another department.</p><p>People from that tribe are hard to get - they are busy with their own stuff as they work with the customers directly.</p><p>To use the time of such a valuable expert wisely, we need to prepare a lot of things upfront.</p><p>&quot;Please give a time when I should book this person&quot; - Product Owner says.</p><p>After seven planning poker sessions and hectoliters of coffee, we have a plan - &quot;in two weeks we will be ready&quot;, we say.</p><p>Product Owner requests expert&#x27;s time in two weeks.</p><p>But there&#x27;s bumpy road ahead - we work with failing tests, broken build pipelines, data cleaning - the team didn&#x27;t make it in time.</p><p>&quot;Sorry, you need to wait another two weeks&quot;, another department leader says.</p><p>And we wait.</p><h3 id="10-classes"><a href="#10-classes" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>10 classes?</h3><p>The time has come - the expert joined the team.</p><p>We were adviced on how to handle various complex data relationships so that it will be easier to implement the feature.</p><p>This required changes in some database tables - some of them were too big, some of them were too small.</p><p>We even joked we do DDD - Database-Driven Design - as we started with database.</p><p>But there was a small, or maybe not that small, problem - as we changed the database structure, 22% of integration tests failed in runtime as the classes playing the roles of repositiories were affected - even though we had a repository pattern implemented.</p><p>We took additional 3 days to carefully refactor those 10 classes, prepare migration scripts and we scheduled &quot;maintenance window&quot; during which our services were not available.</p><p>We deployed changed, ran migrations, and... Everything was working.</p><p>At least this time there were no additional problems.</p><h3 id="problems"><a href="#problems" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Problems</h3><p>Let&#x27;s stop for a while dear Reader.</p><p>What one could notice in those tiny tales?</p><p>Did they sound familiar to you?</p><p>From the outside, all those cases might suggest that there were some problems along the way.</p><p>Based on the business context, team context, technological context - they might seem quite &quot;obvious&quot;.</p><p>&quot;Yeah, we need to wait for other people to help us, what&#x27;s the problem with that?&quot;, some might ask.</p><p>But how do we know that it is normal behavior? A baseline?</p><p>There&#x27;s another nice tale (a bonus tale!):</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>A little crayfish and a little fish were swimming in the lake and having fun underwater, until the crayfish was mature enough to leave the water and enter the beach. Crayfish was amazed about the sky, about trees, birds chirping and humans running around. He came back underwater and said &quot;Little fish, there&#x27;s a whole new world outside water!&quot; and little fish replied &quot;Water? What is that?&quot;.</p></div></div></div><p>What is your water, dear Reader?</p><h3 id="listen-to-your-tests"><a href="#listen-to-your-tests" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Listen to your tests</h3><p>Let&#x27;s take the first tale when there were 411 tests failing.</p><p>What if the problem was not in the tests?</p><p>Tests are provided by human beings (and now by &quot;AI&quot;?) so they are not inherently bad.</p><p>As authors of <a href="https://www.amazon.com/Growing-Object-Oriented-Software-Guided-Tests/dp/0321503627">GOOS</a> wrote:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>When writing unit and integration tests, we stay alert for areas of the code that are difficult to test. When we find a feature that’s difficult to test, we don’t just ask ourselves how to test it, but also why is it difficult to test</p></div></div></div><p>So all those 411 tests were whispering to us - &quot;Hey, there&#x27;s something wrong with the design of the object&quot;.</p><p>What could be improved? What could be done differently?</p><p>And as they continue:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Our experience is that, when code is difficult to test, the most likely cause is that our design needs improving. The same structure that makes the code difficult to test now will make it difficult to change in the future.</p></div></div></div><p>Untestable code tells about the design - it is just a diagnostic signal sent and propagated by the tests.</p><p>The only question is if we are able to listen to it.</p><p>It&#x27;s often mentioned that &quot;tests provide a quick feedback&quot; but it&#x27;s an ambiguity too (should I write about it too?) - it&#x27;s not only about correctness (if you are more interested about specification and verification, please check <a href="https://talesfrom.dev/blog/the-ambiguity-of-tdd">The ambiguity of TDD</a>) or understanding the consumer needs, then providing the well-structured API.</p><p>The feedback is also about the &quot;metabolic health&quot; of the code. Let&#x27;s check what GOOS authors say:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Our response is to regard the process of writing tests as a valuable early warning of potential maintenance problems and to use those hints to fix a problem while it’s still fresh.</p></div></div></div><p>So there are multiple levels of feedback provided by tests - we might get warnings about the consumer needs, the correctness, the growing entropy.</p><p>What do you think dear Reader, what could those 411 failing tests whisper to us?</p><h3 id="listen-to-your-release-process"><a href="#listen-to-your-release-process" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Listen to your release process</h3><p>If we apply similar reasoning (or model if you wish) to the other tales, we might see that the problems are communicating something to us.</p><p>They are not just &quot;problems&quot; - as we already stated, they are diagnostic signals.</p><p>In another tale we&#x27;ve seen that it took 10 days to go through QA process of all the changes and then deploy - without avoding problems in production.</p><p>What does this signal mean? Are we able to interpret it?</p><p>It required couple of hours to deploy new changes - will this rate encourage doing small changes, small deployments?</p><p>Or maybe it&#x27;s going to reinforce the &quot;big bang&quot; deployments?</p><p>As someone said:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>We have the abundance of data, but we have scarcity of insights.</p></div></div></div><p>In this case, the process whispers to us, begging to put our lenses on it and understand the underlying context.</p><p>Everything is emitting signals but we hardly subscribe and use those information to build intelligence.</p><h3 id="listen-to-your-dependencies"><a href="#listen-to-your-dependencies" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Listen to your dependencies</h3><p>In the next tale we&#x27;ve seen that the team was not able to deliver the feature in time as there was a dependency on another department.</p><p>The team needed to &quot;just give numbers&quot; so that project managers could plan the work.</p><p>Planning the knowledge work - it must be fun, right?</p><p>&quot;But Damian, if you have external dependency you need to communicate the plan and schedule, right?&quot;, some could ask.</p><p>I do not have the answers.</p><p>But I do have questions.</p><p>What does it mean that we need to wait for another department?</p><p>Do we have Scrum ceremonies and we plan the work?</p><p>What is &quot;the water&quot; in this context, dear Reader?</p><h3 id="listen-to-your-classes"><a href="#listen-to-your-classes" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Listen to your classes</h3><p>Isn&#x27;t it strange that by changing the database structure, the classes also changed?</p><p>Or maybe there&#x27;s nothing strange in it - it&#x27;s just a consequence of introducing a change.</p><p>Some smart folks could say there&#x27;s a coupling between the database and the application code.</p><p>Another signal, huh.</p><p>As GOOS authors stated, it warns about &quot;future maintenance problems&quot; - what future maintenance problems does it try to warn us about?</p><p>What does it tell us about the design?</p><p>And what about failing tests - what do they whisper to us?</p><h3 id="listen-to-your-problems"><a href="#listen-to-your-problems" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Listen to your problems</h3><p>Problems are a powerful tool.</p><p>Of course it depends on how do we understand the word &quot;problem&quot;.</p><p>I have a background in a control engineering and in that field &quot;an error&quot; is just a part of &quot;the life&quot;, a part of &quot;control feedback loop&quot;.</p><p>It&#x27;s a signal, a very useful one.</p><p>Also, the huge part of such a control feedback loop system is observability - sensors that work as &quot;ears and eyes&quot; for the controller, to make decision upon.</p><p>Still, the most difficult part is to look through &quot;the water&quot;, see beyond our own biases, misconceptions, and tear down abstractions that we&#x27;ve built around us to support us.</p><p>The structure, &quot;the water&quot;, might push us back to the same patterns, the same solutions, the topology.</p><p>To challenge the status quo we must jump into the neverending loop of improvement, full of unlearning (!) and learning - and all of these require being humble, curious and actionable</p><p>Interestingly, when things go wrong, meaning, when we experience problems - whether they are manifested through failing tests, problems in production, difficulities in the delivery or issues in deployment process - typically people want to minimize the risk by creating more structure, adding more processes.</p><p>Make all the steps bigger (structure-wise) - more approvals, more meetings, more resource planning (I was barely able to write it, believe me), more estimates, etc.</p><p>All to reduce the risk, actually increasing the risk by buying illusionary confidence - what if one could make the steps smaller?</p><p>Make smaller changes?</p><p>Establish smaller, trully cross-functional dedicated teams? (You might be interested in <a href="https://talesfrom.dev/blog/the-ambiguity-of-team-work">The ambiguity of team work</a>)</p><p>Additional observation might be that changing technical parts is easy - but changing the way we think, the way other people operate, the way we communicate - that&#x27;s the real challenge.</p><p>The Software System is a part of a bigger system - the organization, the society, the world. It does not exist in a vacuum.</p><p>Next time when you experience a problem, try to listen to it dear Read and ask yourself:</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>What is &quot;the water&quot; I can&#x27;t see?</p></div></div></div>]]></content:encoded>
    <pubDate>Mon, 10 Feb 2025 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>theory of contraints</category><category>software teaming</category><category>lean</category><category>the goal</category><category>model</category><category>modeling</category><category>mental models</category><category>representations</category><category>knowledge working</category><category>ambiguity</category><category>misconceptions</category><category>coding</category><category>abstractions</category><category>language</category><category>product engineering</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/functions-and-facts-describe-the-world</guid>
    <title>Functions (and facts) describe the world</title>
    <link>https://talesfrom.dev/blog/functions-and-facts-describe-the-world</link>
    <description>Can everything be modeled with this pair?</description>
    <content:encoded><![CDATA[<div class="bg-slate-600 rounded-xl "><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Attention!</span></div><div class="pb-2 px-3"><div class="break-words"><p>This tale is a tiny contribution to the great <a href="https://sergeytihon.com/2024/10/26/f-advent-calendar-in-english-2024/">F# Advent Calendar 2024</a>.</p>
<p>Take your time and check other contributions too (of course, after reading this tale)!</p></div></div></div> <div class="bg-slate-600 rounded-xl mt-10"><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Kudos! 🙏🏻</span></div><div class="pb-2 px-3"><div class="break-words"><p>This time, I want to express thankfulness to two people:</p>
<ul>
<li>big thanks to <a href="https://bsky.app/profile/borar.bsky.social">borar</a> (again!) for inspiring conversations and functional teachings</li>
<li>big thanks to <a href="https://bsky.app/profile/oskardudycz.bsky.social">Oskar Dudycz</a> for inspiring conversations, architectural (and more!) insights and for being a great person to talk to</li>
</ul>
<p>Both <a href="https://bsky.app/profile/borar.bsky.social">borar</a> and <a href="https://bsky.app/profile/oskardudycz.bsky.social">Oskar Dudycz</a> had an interesting <a href="https://bsky.app/profile/borar.bsky.social/post/3lczvxuxm722f">discussion</a> that somewhat inspired me to write something about the topic.</p></div></div></div> <br/><div class="bg-slate-600 rounded-xl "><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Attention!</span></div><div class="pb-2 px-3"><div class="break-words"><p>The title of this tale refers to <a href="https://www.youtube.com/watch?v=BWZTlfrneD8&amp;ab_channel=PatoMolina">a great video</a>.</p></div></div></div><h3 id="aggregates"><a href="#aggregates" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Aggregates?</h3><p>In one of my previous tales, prepared specifically for <a href="https://sergeytihon.com/2022/10/28/f-advent-calendar-in-english-2022/">F# Advent Calendar 2022</a>, we took a tour around representing &quot;an aggregate&quot;, a Domain-Driven Design tactical pattern, in variety of ways (see <a href="https://talesfrom.dev/blog/many-faces-of-ddd-aggregates-in-fsharp">Many faces of DDD Aggregates in F#</a>).</p><p>In the next tale, made for <a href="https://sergeytihon.com/2023/10/28/f-advent-calendar-in-english-2023/">F# Advent Calendar 2023</a>, we went down into the rabbit hole of modeling state machines using functional-first thinking (see <a href="https://talesfrom.dev/blog/fsm-functional-state-machines">FSM - Functional State Machines</a>).</p><p>In fact, both of those tales were about enforcing a set of rules so that the state of a part of the system stays transactionally consistent (whatever it actually means).</p><p>Of course, I wrote them having in mind that they must be immediately shipped to production in one of your critical service providers, dear Reader.</p><p>If you know me a bit (I hope, dear Reader), you probably understand that little sarcarsm.</p><p>Both of those tales had exploratory nature - we were able to had playful moments with various representations of a concept of &quot;an aggregate&quot;.</p><p>Ah, sweet aggregate of mine - everyone want to have you in one&#x27;s system, right?</p><p>But let&#x27;s get back to the main point of &quot;aggregates&quot; - &quot;enforcing a set of rules so that the state of a part of the system stays transactionally consistent&quot;.</p><h3 id="the-world-beyond-aggregates"><a href="#the-world-beyond-aggregates" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The world beyond &quot;aggregates&quot;</h3><p>Turns out that both of those tales had something in common (and it wasn&#x27;t only a concept of &quot;an aggregate&quot;) - we focused very much of rules enforcement (also called &quot;invariants&quot;), completely ignoring the output of application of the knowledge regarding those rules (application of the knowledge? You might be interested in <a href="https://talesfrom.dev/blog/the-ambiguity-of-application">The ambiguity of application</a>).</p><p>As a reminiscence, here are two code snippets (slightly modified) from the tales:</p><ul><li>from <a href="https://talesfrom.dev/blog/many-faces-of-ddd-aggregates-in-fsharp">Many faces of DDD Aggregates in F#</a></li></ul><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> ignoreFacts <span class="token operator">=</span> snd <span class="token comment">// built-in function!</span>
</span><span class="code-line"><span class="token keyword">let</span> shift <span class="token operator">=</span> BouncersShift<span class="token punctuation">.</span>start <span class="token punctuation">[</span><span class="token string">&quot;mike&quot;</span><span class="token punctuation">;</span><span class="token string">&quot;john&quot;</span><span class="token punctuation">;</span><span class="token string">&quot;derek&quot;</span><span class="token punctuation">]</span>
</span><span class="code-line">
</span><span class="code-line">shift 
</span><span class="code-line"><span class="token operator">|&gt;</span> BouncersShift<span class="token punctuation">.</span>startGuarding <span class="token string">&quot;mike&quot;</span>
</span><span class="code-line"><span class="token operator">|&gt;</span> <span class="token punctuation">(</span>ignoreFacts <span class="token operator">&gt;&gt;</span> BouncersShift<span class="token punctuation">.</span>startGuarding <span class="token string">&quot;derek&quot;</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token comment">//      \________________ each operation yields both facts that happened</span>
</span><span class="code-line"><span class="token comment">//                        during execution and current state machine</span>
</span></code></pre></div></div><ul><li>from <a href="https://talesfrom.dev/blog/fsm-functional-state-machines">FSM - Functional State Machines</a></li></ul><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> discardOutput <span class="token operator">=</span> snd
</span><span class="code-line">
</span><span class="code-line">doorMechanism
</span><span class="code-line"><span class="token operator">|&gt;</span> DoorMechanism<span class="token punctuation">.</span>send Open
</span><span class="code-line"><span class="token operator">&gt;&gt;</span><span class="token operator">=</span> <span class="token punctuation">(</span>discardOutput <span class="token operator">&gt;&gt;</span> DoorMechanism<span class="token punctuation">.</span>send Close<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token operator">&gt;&gt;</span><span class="token operator">=</span> <span class="token punctuation">(</span>discardOutput <span class="token operator">&gt;&gt;</span> DoorMechanism<span class="token punctuation">.</span>send Lock<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token operator">&gt;&gt;</span><span class="token operator">=</span> <span class="token punctuation">(</span>discardOutput <span class="token operator">&gt;&gt;</span> DoorMechanism<span class="token punctuation">.</span>send Open<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token comment">//      \________________ each operation yields both facts that happened</span>
</span><span class="code-line"><span class="token comment">//                        during execution and current state machine</span>
</span></code></pre></div></div><p>One could say that &quot;an aggregate&quot; is &quot;just&quot; something that <em>aggregates</em> <strong>the rules</strong> to enforce <strong>consistent state change</strong> - so it can be nicely represented as a (functional) state machine.</p><p>We saw that, right dear Reader?</p><p>But it is only one (tactical) &quot;pattern&quot; in the arsenal of Domain-Driven Designing engineer.</p><p>There are other building blocks that we can employ to build our systems using Domain-Driven Design approach (at least the &quot;tactical side&quot; of it), depending on the problem area we are building software solutions for (right?).</p><p>In this tale, instead of &quot;ignoring facts&quot; or &quot;discarding output&quot;, we are going to utilize those facts to build toy system, using other &quot;conceptual primitives&quot; from a &quot;tactical&quot; DDD and and Event Storming toolbelts.</p><p>Other building blocks?</p><p>Facts?</p><p>Let&#x27;s go!</p><h3 id="aggregates-state-machines-andfunctions"><a href="#aggregates-state-machines-andfunctions" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Aggregates, state machines and...Functions?!</h3><p>As I was doing a research for this tale, I stumbled upon a really interesting <a href="https://marcosh.github.io/post/2021/10/27/ddd-state-machines.html">resource</a>.</p><p>In his blog post, the author discusses using Mealy machines to model aggregates and...Projections and policies.</p><p>We used <a href="https://talesfrom.dev/blog/fsm-functional-state-machines#solution-1-mealy-state-machines">Mealy state machines</a> to model aggregates, but projections and policies?!</p><p>That made me really, really curious.</p><p>I enjoyed all the insightful observations the author made, especially that he focused on the compositional aspect of Mealy state machines (say hi to <a href="https://en.wikipedia.org/wiki/Category_theory">Category Theory</a>).</p><p>Also, all concepts were represented by...Functions.</p><p>As he omitted the implementation details, I decided to take a step further and implement a fully-functioning toy example (sounds like a paradox, isn&#x27;t it?), using the knowledge and observations from the post.</p><p>Firstly, we need to revisit the concept of &quot;an aggregate&quot;.</p><h3 id="wait-design-decisions-ahead"><a href="#wait-design-decisions-ahead" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Wait, design decisions ahead!</h3><p>But before that, a small design decision.</p><p>The author deliberately used Mealy machines to represent the &quot;tactical DDD&quot; and Event Storming building blocks.</p><p>As we already saw how to use <a href="https://talesfrom.dev/blog/fsm-functional-state-machines#solution-1-mealy-state-machines">Mealy state machines</a>, to make everything a little bit simpler, we&#x27;re going to drop &quot;halting&quot; aspect of the Mealy machines and assume that our state machines are going to work forever.</p><p>This means that instead of such state machine encoding:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">Step</span><span class="token operator">&lt;</span>&#x27;Output<span class="token punctuation">,</span> &#x27;Continue<span class="token operator">&gt;</span> <span class="token operator">=</span>
</span><span class="code-line">    <span class="token operator">|</span> Stop <span class="token comment">// 👈 this enables &quot;halting&quot;</span>
</span><span class="code-line">    <span class="token operator">|</span> ContinueWith <span class="token keyword">of</span> <span class="token punctuation">(</span>&#x27;Output <span class="token operator">*</span>  &#x27;Continue<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">Mealy</span><span class="token operator">&lt;</span>&#x27;Input<span class="token punctuation">,</span> &#x27;Output<span class="token operator">&gt;</span> <span class="token operator">=</span> Mealy <span class="token keyword">of</span> <span class="token punctuation">(</span>&#x27;Input <span class="token operator">-&gt;</span> Step<span class="token operator">&lt;</span>&#x27;Output<span class="token punctuation">,</span> Mealy<span class="token operator">&lt;</span>&#x27;Input<span class="token punctuation">,</span>&#x27;Output<span class="token operator">&gt;&gt;</span><span class="token punctuation">)</span>
</span></code></pre></div></div><p>We&#x27;re going to use the following finite-state machine representation:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">FSM</span><span class="token operator">&lt;</span>&#x27;Input<span class="token punctuation">,</span> &#x27;Output<span class="token punctuation">,</span> &#x27;State<span class="token operator">&gt;</span> <span class="token operator">=</span>
</span><span class="code-line">        FSM <span class="token keyword">of</span> <span class="token punctuation">(</span>&#x27;State <span class="token operator">*</span> <span class="token punctuation">(</span>&#x27;State <span class="token operator">-&gt;</span> &#x27;Input <span class="token operator">-&gt;</span> &#x27;Output<span class="token punctuation">)</span><span class="token punctuation">)</span>
</span></code></pre></div></div><p>Dropping <code>Stop</code> case means that we would work with a single-case union, keeping output and continuation.</p><p>It is an output of a processing and a function that does this processing.</p><p>Additionally, we&#x27;re going to use a signature for a function to evolve <code>FSM</code>:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">Evolve</span><span class="token operator">&lt;</span>&#x27;Input<span class="token punctuation">,</span> &#x27;Output<span class="token punctuation">,</span> &#x27;FSM<span class="token operator">&gt;</span> <span class="token operator">=</span> &#x27;Input <span class="token operator">-&gt;</span> &#x27;FSM <span class="token operator">-&gt;</span> &#x27;Output <span class="token operator">*</span> &#x27;FSM
</span></code></pre></div></div><p>There&#x27;s no type constraint on <code>&#x27;FSM</code> for sake of simplicity.</p><h3 id="wait-a-domain"><a href="#wait-a-domain" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Wait, a domain?</h3><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">Business area context</div><div class="pb-2 px-3"><div class="break-words"><p>Imagine that we are producing high-tech doors, full of sensors and actuators. One is able to interact with a single instance of a door remotely, using a handy app.
Thanks to our innovative approach to door manufacturing, we are able to track various interactions with physical doors, along with triggering actions on them.</p></div></div></div><p>This means, we&#x27;re able to continue a domain that was introduced in <a href="https://talesfrom.dev/blog/fsm-functional-state-machines">FSM-Functional State Machines</a> tale - a <code>DoorMechanism</code>.</p><p>Additionally, we&#x27;re going to extend it with a concept of &quot;door knocking&quot;, introduced in the mentioned <a href="https://marcosh.github.io/post/2021/10/27/ddd-state-machines.html">article</a>.</p><p>To do so, we need to think not only about &quot;mechanism&quot; itself, but about the door as a whole (to allow &quot;knocking&quot;).</p><p>Let&#x27;s sum up the rules to maintain the integrity of a door&#x27;s representation:</p><ul><li>door starts as <code>Open</code></li><li>only when it&#x27;s <code>Closed</code>, when trying to <code>Open</code> it, it becomes <code>Open</code></li><li>only when it&#x27;s <code>Opened</code>, when trying to <code>Close</code> it, it becomes <code>Closed</code></li><li>only when it&#x27;s <code>Closed</code>, when trying to <code>Lock</code> it, it becomes <code>Locked</code></li><li>only when it&#x27;s <code>Locked</code>, when trying to <code>Unlock</code> it, it becomes <code>Closed</code></li><li>when it&#x27;s <code>Closed</code>, it can be <code>Knocked</code> and it remains <code>Closed</code></li><li>when it&#x27;s <code>Locked</code>, it can be <code>Knocked</code> and it remains <code>Locked</code></li></ul><p>To make our understanding better, let&#x27;s draw it:</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/functions-and-facts-describe-the-world-door-fsm.png" class="max-h-[30rem]"/></div><div class="italic mx-24">Door state machine</div></div><h3><a href="#" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a></h3><p>As mentioned before, we&#x27;re going to represent three concepts:</p><ul><li>an aggregate</li><li>a policy</li><li>a projection</li></ul><p>In the original <a href="https://marcosh.github.io/post/2021/10/27/ddd-state-machines.html">article</a>, <a href="https://www.eventstorming.com/">&quot;Picture that explains (almost) everything&quot;</a> is mentioned:</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/functions-and-facts-describe-the-world-albertos-picture.png" class="max-h-[25rem]"/></div><div class="italic mx-24">invented by Alberto Brandolini</div></div><p>We are going to use it to visualize what part of this diagram we are focusing on at the moment of exploration.</p><p>To achieve so, we&#x27;re going to use the following, simplified, picture:</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/functions-and-facts-describe-the-world-interpretation-albertos-picture.png" class="max-h-[35rem]"/></div></div><p>Phew, that was a bit exhausting, wasn&#x27;t it?</p><p>Before starting our exploratory journey, we needed to set the frame, but finally we are ready.</p><p>Buckle up, we have things to play with!</p><h3 id="first-function---an-aggregate"><a href="#first-function---an-aggregate" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>First function - &quot;an aggregate&quot;</h3><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/functions-and-facts-describe-the-world-aggregate.png" class="max-h-[35rem]"/></div><div class="italic mx-24">An aggregate</div></div><p>Ok, time to encode a concept of &quot;an aggregate&quot;!</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">Aggregate</span><span class="token operator">&lt;</span>&#x27;Command<span class="token punctuation">,</span> &#x27;Event<span class="token punctuation">,</span> &#x27;State<span class="token operator">&gt;</span> <span class="token operator">=</span> 
</span><span class="code-line">    FSM<span class="token operator">&lt;</span>&#x27;Command<span class="token punctuation">,</span> &#x27;Event list<span class="token punctuation">,</span> &#x27;State<span class="token operator">&gt;</span>
</span></code></pre></div></div><p>Now let&#x27;s use it to represent concepts from our domain:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">module</span> Door <span class="token operator">=</span>
</span><span class="code-line">    <span class="token keyword">type</span> <span class="token class-name">DoorState</span> <span class="token operator">=</span> <span class="token keyword">private</span> DoorOpen <span class="token operator">|</span> DoorClosed <span class="token operator">|</span> DoorLocked
</span><span class="code-line">    <span class="token keyword">type</span> <span class="token class-name">DoorCommand</span> <span class="token operator">=</span> <span class="token keyword">private</span> Open <span class="token operator">|</span> Close <span class="token operator">|</span> Knock <span class="token operator">|</span> Lock <span class="token operator">|</span> Unlock
</span><span class="code-line">    <span class="token keyword">type</span> <span class="token class-name">DoorEvent</span> <span class="token operator">=</span> <span class="token keyword">private</span> Opened <span class="token operator">|</span> Closed <span class="token operator">|</span> Knocked <span class="token operator">|</span> Locked <span class="token operator">|</span> Unlocked
</span><span class="code-line">    <span class="token keyword">type</span> <span class="token class-name">Door</span> <span class="token operator">=</span> Door <span class="token keyword">of</span> <span class="token class-name">Aggregate</span><span class="token operator">&lt;</span>DoorCommand<span class="token punctuation">,</span> DoorEvent<span class="token punctuation">,</span> DoorEvent list<span class="token operator">&gt;</span>
</span><span class="code-line">    <span class="token comment">//                    |</span>
</span><span class="code-line">    <span class="token comment">//                    |</span>
</span><span class="code-line">    <span class="token comment">//                    |__ it can be thought of as:</span>
</span><span class="code-line">    <span class="token comment">//                       FSM (DoorEvent list, DoorState -&gt; DoorCommand -&gt; DoorEvent list * DoorState)</span>
</span><span class="code-line">    <span class="token keyword">type</span> <span class="token class-name">EvolveDoor</span> <span class="token operator">=</span> Evolve<span class="token operator">&lt;</span>DoorCommand<span class="token punctuation">,</span> DoorEvent list<span class="token punctuation">,</span> Door<span class="token operator">&gt;</span>
</span><span class="code-line">    <span class="token comment">//                  |</span>
</span><span class="code-line">    <span class="token comment">//                  |__ it can be thought of:</span>
</span><span class="code-line">    <span class="token comment">//                       DoorCommand -&gt; Door -&gt; DoorEvent list * Door</span>
</span></code></pre></div></div><p>As before, we want to express the language of the domain, hence we use single-case union <code>Door</code> to communicate &quot;aggregate&#x27;s&quot; intention.</p><p>(an avid Domain-Driven Design Reader might notice that naming your &quot;aggregates&quot; like that might be considered an &quot;anti-pattern&quot;, but I am adult so I know what I am doing, right?)</p><p>We have the basic structure, let&#x27;s focus on evolving our &quot;aggregate state machine&quot;:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> evolve<span class="token punctuation">:</span> <span class="token class-name">EvolveDoor</span> <span class="token operator">=</span>
</span><span class="code-line">    <span class="token comment">// DoorCommand -&gt; Door -&gt; DoorEvent list * Door</span>
</span><span class="code-line">    <span class="token keyword">fun</span> command aggregate <span class="token operator">-&gt;</span>
</span><span class="code-line">        <span class="token keyword">let</span> <span class="token punctuation">(</span>Door <span class="token punctuation">(</span>FSM <span class="token punctuation">(</span>events<span class="token punctuation">,</span> applyTo<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">=</span> aggregate <span class="token comment">// 👈 destructuring to get to &quot;state&quot; and &quot;deciding function&quot; </span>
</span><span class="code-line">        <span class="token keyword">let</span> applyTo&#x27; _ command <span class="token operator">=</span> command <span class="token operator">|&gt;</span> applyTo events <span class="token comment">// 👈 for &quot;better&quot; readability</span>
</span><span class="code-line">        <span class="token keyword">let</span> newEvents <span class="token operator">=</span> command <span class="token operator">|&gt;</span> applyTo&#x27; aggregate <span class="token comment">// 👈 as we saw on the diagram</span>
</span><span class="code-line">        newEvents<span class="token punctuation">,</span> <span class="token function">Door</span><span class="token punctuation">(</span><span class="token function">FSM</span><span class="token punctuation">(</span><span class="token punctuation">(</span>events <span class="token operator">|&gt;</span> List<span class="token punctuation">.</span>append newEvents<span class="token punctuation">)</span><span class="token punctuation">,</span> applyTo<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// 👈 returning &quot;output&quot; and appending new events to the history</span>
</span></code></pre></div></div><p>We&#x27;re going to start with something we already know - <a href="https://talesfrom.dev/blog/functions-and-facts-describe-the-world#wait-a-domain">state transitions</a>:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">module</span> DoorState <span class="token operator">=</span>
</span><span class="code-line">    <span class="token keyword">let</span> applyTo state events <span class="token operator">=</span>
</span><span class="code-line">    <span class="token comment">//  DoorState -&gt; DoorEvent list -&gt; DoorState</span>
</span><span class="code-line">        events <span class="token operator">|&gt;</span> List<span class="token punctuation">.</span>fold applyTo&#x27; state
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">let</span> <span class="token keyword">private</span> applyTo&#x27; state <span class="token keyword">event</span> <span class="token operator">=</span> <span class="token comment">// 👈 evolving &quot;state&quot; with a single event</span>
</span><span class="code-line">    <span class="token comment">//  DoorState -&gt; DoorEvent -&gt; DoorState</span>
</span><span class="code-line">        <span class="token keyword">match</span> state<span class="token punctuation">,</span> <span class="token keyword">event</span> <span class="token keyword">with</span>
</span><span class="code-line">        <span class="token operator">|</span> DoorOpen<span class="token punctuation">,</span> Closed <span class="token operator">-&gt;</span> DoorClosed
</span><span class="code-line">        <span class="token operator">|</span> DoorOpen<span class="token punctuation">,</span> _ <span class="token operator">-&gt;</span> DoorOpen
</span><span class="code-line">        <span class="token operator">|</span> DoorClosed<span class="token punctuation">,</span> Opened <span class="token operator">-&gt;</span> DoorOpen
</span><span class="code-line">        <span class="token operator">|</span> DoorClosed<span class="token punctuation">,</span> Locked <span class="token operator">-&gt;</span> DoorLocked
</span><span class="code-line">        <span class="token operator">|</span> DoorClosed<span class="token punctuation">,</span> _ <span class="token operator">-&gt;</span> DoorClosed
</span><span class="code-line">        <span class="token operator">|</span> DoorLocked<span class="token punctuation">,</span> Unlocked <span class="token operator">-&gt;</span> DoorClosed
</span><span class="code-line">        <span class="token operator">|</span> DoorLocked<span class="token punctuation">,</span> _ <span class="token operator">-&gt;</span> DoorLocked
</span></code></pre></div></div><p>That was pretty straightforward, wasn&#x27;t it?</p><p>We are able to evolve a <code>DoorState</code> by utilizing all <code>DoorEvent</code>s that happened before.</p><p>But &quot;an aggregate&quot; is something else than a state. It is able to transform a command into a list of events, here we dealt &quot;just&quot; with state transitions.</p><p>In fact, Mealy machines express both <strong>state transitions</strong> and <strong>output</strong>, provided with each transition.</p><p>This fact (pun intended) - outputs - weren&#x27;t captured in previous tales because we completely ignored the them, but now the story is different - this is our main star (next to functions, of course).</p><p>Let&#x27;s fix our FSM chart:</p><div class="flex justify-between items-center flex-col"><img src="https://talesfrom.dev/static/images/functions-and-facts-describe-the-world-door-fsm-outputs.png" class="max-h-[35rem]"/><div class="flex flex-col justify-center items-center"><div class="italic mx-24">A canonical Mealy machine diagram with inputs, outputs and states.</div> <div class="italic mx-24">Click <a target="_blank" href="https://talesfrom.dev/static/images/functions-and-facts-describe-the-world-door-fsm-outputs.png">here</a> to see bigger picture.</div></div></div><p>Of course, we used our deep domain knowledge to express what events happen for a given state transition, knowing the incoming command.</p><p>And this is our <code>applyTo</code> we were missing!</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> applyTo state command <span class="token operator">=</span>
</span><span class="code-line">    <span class="token comment">//  DoorEvent list -&gt; DoorCommand -&gt; DoorEvent list</span>
</span><span class="code-line">    <span class="token keyword">let</span> state <span class="token operator">=</span> events <span class="token operator">|&gt;</span> DoorState<span class="token punctuation">.</span>applyTo DoorOpen <span class="token comment">// 👈 we &quot;build&quot; door state from each events that happened</span>
</span><span class="code-line">    <span class="token keyword">let</span> newEvents <span class="token operator">=</span>
</span><span class="code-line">            <span class="token keyword">match</span> state<span class="token punctuation">,</span> command <span class="token keyword">with</span> <span class="token comment">// 👈 we&#x27;re deciding what events happen after a certain command is applied to a &quot;state&quot;</span>
</span><span class="code-line">            <span class="token operator">|</span> DoorOpen<span class="token punctuation">,</span> Close <span class="token operator">-&gt;</span> <span class="token punctuation">[</span>Closed<span class="token punctuation">]</span>
</span><span class="code-line">            <span class="token operator">|</span> DoorOpen<span class="token punctuation">,</span> _ <span class="token operator">-&gt;</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
</span><span class="code-line">            <span class="token operator">|</span> DoorClosed<span class="token punctuation">,</span> Knock <span class="token operator">-&gt;</span> <span class="token punctuation">[</span>Knocked<span class="token punctuation">]</span>
</span><span class="code-line">            <span class="token operator">|</span> DoorClosed<span class="token punctuation">,</span> Open <span class="token operator">-&gt;</span> <span class="token punctuation">[</span>Opened<span class="token punctuation">]</span>
</span><span class="code-line">            <span class="token operator">|</span> DoorClosed<span class="token punctuation">,</span> Lock <span class="token operator">-&gt;</span> <span class="token punctuation">[</span>Locked<span class="token punctuation">]</span>
</span><span class="code-line">            <span class="token operator">|</span> DoorClosed<span class="token punctuation">,</span> _ <span class="token operator">-&gt;</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
</span><span class="code-line">            <span class="token operator">|</span> DoorLocked<span class="token punctuation">,</span> Unlock <span class="token operator">-&gt;</span> <span class="token punctuation">[</span>Unlocked<span class="token punctuation">]</span>
</span><span class="code-line">            <span class="token operator">|</span> DoorLocked<span class="token punctuation">,</span> Knock <span class="token operator">-&gt;</span> <span class="token punctuation">[</span>Knocked<span class="token punctuation">]</span>
</span><span class="code-line">            <span class="token operator">|</span> DoorLocked<span class="token punctuation">,</span> _ <span class="token operator">-&gt;</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
</span><span class="code-line">            
</span><span class="code-line">    newEvents
</span></code></pre></div></div><p>It seems we have almost everything in place to play with our &quot;aggregate&quot;.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">module</span> Door <span class="token operator">=</span>
</span><span class="code-line">    <span class="token keyword">let</span> noInitialEvents <span class="token operator">=</span> List<span class="token punctuation">.</span>empty<span class="token operator">&lt;</span>DoorEvent<span class="token operator">&gt;</span>
</span><span class="code-line">    <span class="token keyword">let</span> <span class="token function">door</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token function">Door</span><span class="token punctuation">(</span><span class="token function">FSM</span><span class="token punctuation">(</span>noInitialEvents<span class="token punctuation">,</span> applyTo<span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">let</span> close <span class="token operator">=</span> evolve Close
</span><span class="code-line">    <span class="token keyword">let</span> <span class="token keyword">open</span>&#x27; <span class="token operator">=</span> evolve Open
</span><span class="code-line">    <span class="token keyword">let</span> knock <span class="token operator">=</span> evolve Knock
</span><span class="code-line">    <span class="token keyword">let</span> lock <span class="token operator">=</span> evolve Lock
</span><span class="code-line">    <span class="token keyword">let</span> unlock <span class="token operator">=</span> evolve Unlock
</span></code></pre></div></div><p>Here is the public API to work with &quot;a door&quot;.</p><p>Up to now, it should look familiar (if you had chance to see previous tales, dear Reader).</p><p>Ok, no more waiting - let&#x27;s interact with a representation of &quot;a door&quot; (in fact, just one aspect of a door, because the rest, like weight, height, price, isn&#x27;t in the area of our interest!).</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> aDoor <span class="token operator">=</span> Door<span class="token punctuation">.</span><span class="token function">door</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token keyword">let</span> aDoor&#x27; <span class="token operator">=</span>
</span><span class="code-line">    aDoor
</span><span class="code-line">    <span class="token operator">|&gt;</span> <span class="token punctuation">(</span>Door<span class="token punctuation">.</span>close <span class="token operator">&gt;&gt;</span> andPublish<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token operator">|&gt;</span> <span class="token punctuation">(</span>Door<span class="token punctuation">.</span>knock <span class="token operator">&gt;&gt;</span> andPublish<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token operator">|&gt;</span> <span class="token punctuation">(</span>Door<span class="token punctuation">.</span>knock <span class="token operator">&gt;&gt;</span> andPublish<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token operator">|&gt;</span> <span class="token punctuation">(</span>Door<span class="token punctuation">.</span>lock <span class="token operator">&gt;&gt;</span> andPublish<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token operator">|&gt;</span> <span class="token punctuation">(</span>Door<span class="token punctuation">.</span>knock <span class="token operator">&gt;&gt;</span> andPublish<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token operator">|&gt;</span> <span class="token punctuation">(</span>Door<span class="token punctuation">.</span>knock <span class="token operator">&gt;&gt;</span> andPublish<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token operator">|&gt;</span> <span class="token punctuation">(</span>Door<span class="token punctuation">.</span>unlock <span class="token operator">&gt;&gt;</span> andPublish<span class="token punctuation">)</span>
</span></code></pre></div></div><p>For the sake of this tale, let&#x27;s assume that such sequence - <code>close, knock, knock, lock, knock, knock, unlock</code> - will be used from now on when interacting with the door.</p><p>If we run it in FSI, then we get something like this:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="code-highlight language-sh"><span class="code-line">val aDoor: Door.Door <span class="token operator">=</span> Door <span class="token punctuation">(</span>FSM <span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span>, <span class="token operator">&lt;</span>fun:aDoor@357-<span class="token operator"><span class="token file-descriptor important">8</span>&gt;</span><span class="token punctuation">))</span>
</span><span class="code-line">val aDoor&#x27;: Door.Door <span class="token operator">=</span>
</span><span class="code-line">  Door <span class="token punctuation">(</span>FSM <span class="token punctuation">(</span><span class="token punctuation">[</span>Closed<span class="token punctuation">;</span> Knocked<span class="token punctuation">;</span> Knocked<span class="token punctuation">;</span> Locked<span class="token punctuation">;</span> Knocked<span class="token punctuation">;</span> Knocked<span class="token punctuation">;</span> Unlocked<span class="token punctuation">]</span>, <span class="token operator">&lt;</span>fun:aDoor@357-<span class="token operator"><span class="token file-descriptor important">8</span>&gt;</span><span class="token punctuation">))</span>
</span></code></pre></div></div><p>Ok, this time we have a new player in the game - <code>andPublish</code> function:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> andPublish<span class="token punctuation">,</span> subscribeToDoorEvents <span class="token operator">=</span> 
</span><span class="code-line">    Messaging<span class="token punctuation">.</span>InMemory<span class="token punctuation">.</span><span class="token function">doorEventBroker</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span></code></pre></div></div><p>It is a simple implementation of a &quot;publish-subscribe&quot; pattern, where we can subscribe to events and publish them.</p><p>Of course it is production-grade as it is in-memory.</p><p>Now, it&#x27;s time to subscribe to those events and see the history of our door&#x27;s life:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token function">subscribeToDoorEvents</span><span class="token punctuation">(</span><span class="token keyword">fun</span> <span class="token keyword">event</span> <span class="token operator">-&gt;</span>
</span><span class="code-line">    printfn $<span class="token string">&quot;A door has been {event}&quot;</span>    
</span><span class="code-line"><span class="token punctuation">)</span>
</span></code></pre></div></div><p>After subscribing and interacting with the door&#x27;s representation, we get:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="code-highlight language-sh"><span class="code-line">A door has been Closed
</span><span class="code-line">A door has been Knocked
</span><span class="code-line">A door has been Knocked
</span><span class="code-line">A door has been Locked
</span><span class="code-line">A door has been Knocked
</span><span class="code-line">A door has been Knocked
</span><span class="code-line">A door has been Unlocked
</span></code></pre></div></div><p>Here is a dumb simple implementation of <code>doorEventBroker</code>:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> <span class="token function">doorEventBroker</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">    broker<span class="token operator">&lt;</span>_<span class="token punctuation">,</span> _<span class="token punctuation">,</span> _<span class="token operator">&gt;</span><span class="token punctuation">(</span> <span class="token comment">// 👈 we&#x27;re using a generic broker and we completely let the Almighty F# Compiler do the heavylifting for us</span>
</span><span class="code-line">        <span class="token keyword">fun</span> result subscriber <span class="token operator">-&gt;</span>
</span><span class="code-line">            <span class="token keyword">let</span> events<span class="token punctuation">,</span> _ <span class="token operator">=</span> result <span class="token comment">// 👈 we&#x27;re destructuring the result of evolving FSM and use events</span>
</span><span class="code-line">            
</span><span class="code-line">            events <span class="token operator">|&gt;</span> List<span class="token punctuation">.</span>iter subscriber <span class="token comment">// 👈 we&#x27;re letting subscriber know about new events</span>
</span><span class="code-line">    <span class="token punctuation">)</span>
</span></code></pre></div></div><p>Beware, here comes the most complex code in this tale!</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token annotation"><span class="token punctuation">[&lt;</span><span class="token class-name">RequireQualifiedAccess</span><span class="token punctuation">&gt;]</span></span>
</span><span class="code-line"><span class="token keyword">module</span> Messaging <span class="token operator">=</span>
</span><span class="code-line">    <span class="token annotation"><span class="token punctuation">[&lt;</span><span class="token class-name">RequireQualifiedAccess</span><span class="token punctuation">&gt;]</span></span>
</span><span class="code-line">    <span class="token keyword">module</span> InMemory <span class="token operator">=</span>
</span><span class="code-line">        <span class="token keyword">let</span> broker<span class="token operator">&lt;</span>&#x27;OutputToPublish<span class="token punctuation">,</span> &#x27;SubscriberInput<span class="token punctuation">,</span> &#x27;FSM<span class="token operator">&gt;</span>
</span><span class="code-line">            <span class="token punctuation">(</span>createPublishTo<span class="token punctuation">:</span> &#x27;OutputToPublish <span class="token operator">*</span> &#x27;FSM <span class="token operator">-&gt;</span> <span class="token punctuation">(</span>&#x27;SubscriberInput <span class="token operator">-&gt;</span> unit<span class="token punctuation">)</span> <span class="token operator">-&gt;</span> unit<span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">            <span class="token keyword">let</span> <span class="token keyword">mutable</span> subscribers <span class="token operator">=</span> List<span class="token punctuation">.</span>empty<span class="token operator">&lt;</span>&#x27;SubscriberInput <span class="token operator">-&gt;</span> unit<span class="token operator">&gt;</span>
</span><span class="code-line">            <span class="token keyword">let</span> subscribe <span class="token punctuation">(</span>subscriber<span class="token punctuation">:</span> &#x27;SubscriberInput <span class="token operator">-&gt;</span> unit<span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">                subscribers <span class="token operator">&lt;-</span> subscriber <span class="token operator">::</span> subscribers <span class="token comment">// 👈 we maintain in-memory list of subscribers</span>
</span><span class="code-line">
</span><span class="code-line">            <span class="token keyword">let</span> publish <span class="token punctuation">(</span>outputToPublish<span class="token punctuation">:</span> &#x27;OutputToPublish<span class="token punctuation">,</span> fsm<span class="token punctuation">:</span> &#x27;FSM<span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">                <span class="token keyword">let</span> publishTo <span class="token operator">=</span> createPublishTo <span class="token punctuation">(</span>outputToPublish<span class="token punctuation">,</span> fsm<span class="token punctuation">)</span>
</span><span class="code-line">                List<span class="token punctuation">.</span>iter publishTo <span class="token operator">&lt;|</span> subscribers
</span><span class="code-line">                fsm <span class="token comment">// 👈 we want to return FSM for pipe-friendly processing</span>
</span><span class="code-line">            
</span><span class="code-line">            publish<span class="token punctuation">,</span> subscribe <span class="token comment">// 👈 our public API</span>
</span></code></pre></div></div><p>So this little function creates an in-memory list of subscribers and allows to publish an output from FSMs to them.</p><p>Dumb simple.</p><p>Wouldn&#x27;t it be nice to use events for something else than just printing them?</p><p>Let&#x27;s move on to policies!</p><h3 id="second-function---a-policy"><a href="#second-function---a-policy" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Second function - &quot;a policy&quot;</h3><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/functions-and-facts-describe-the-world-policy.png" class="max-h-[35rem]"/></div><div class="italic mx-24">A policy</div></div><p>So according to the diagram, it is driven by events and it produces commands.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">Policy</span><span class="token operator">&lt;</span>&#x27;Event<span class="token punctuation">,</span> &#x27;Command<span class="token punctuation">,</span> &#x27;PolicyState<span class="token operator">&gt;</span> <span class="token operator">=</span>
</span><span class="code-line">    FSM<span class="token operator">&lt;</span>&#x27;Event<span class="token punctuation">,</span> &#x27;Command<span class="token punctuation">,</span> &#x27;PolicyState<span class="token operator">&gt;</span>
</span></code></pre></div></div><p>In the mentioned <a href="https://marcosh.github.io/post/2021/10/27/ddd-state-machines.html">article</a>, the author does not provide any state for the policy, so it is stateless.</p><p>Let&#x27;s try the same.</p><p>Here&#x27;s the policy structure:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">module</span> Policies <span class="token operator">=</span>
</span><span class="code-line">    <span class="token keyword">module</span> EachKnockNotifies <span class="token operator">=</span>
</span><span class="code-line">        <span class="token keyword">type</span> <span class="token class-name">EachKnockNotifiesCommand</span> <span class="token operator">=</span> 
</span><span class="code-line">            SendSms <span class="token operator">|</span> NoAction
</span><span class="code-line">        <span class="token keyword">type</span> <span class="token class-name">EachKnockNotifiesPolicy</span> <span class="token operator">=</span>
</span><span class="code-line">            EachKnockNotifies <span class="token keyword">of</span> <span class="token class-name">Policy</span><span class="token operator">&lt;</span>DoorEvent<span class="token punctuation">,</span> EachKnockNotifiesCommand<span class="token punctuation">,</span> unit<span class="token operator">&gt;</span>
</span><span class="code-line">        <span class="token keyword">type</span> <span class="token class-name">EvolveKnockNotifiesPolicy</span> <span class="token operator">=</span> 
</span><span class="code-line">            Evolve<span class="token operator">&lt;</span>DoorEvent<span class="token punctuation">,</span> EachKnockNotifiesCommand<span class="token punctuation">,</span> EachKnockNotifiesPolicy<span class="token operator">&gt;</span>
</span></code></pre></div></div><p>It means that we will have no state (<code>unit</code>) and as an output we are going to give <code>EachKnockNotifiesCommand</code> back.</p><p>We wanted to encode &quot;complete&quot; problem space, so in case other event than <code>Knocked</code> happened, we want to express &quot;no action&quot; - hence <code>NoAction</code>.</p><p>This also makes our policy &quot;pure&quot; - it just describes the reaction to the event, and execution might happen later (as &quot;someone&quot; interprets the result).</p><p>As you noticed, dear Reader, I already gave a name to your policy so we could state the policy in the natural language as: &quot;whenever knocked then send SMS&quot;.</p><p>As our policy is stateless, we can use a simple function to evolve it:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> applyTo <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">event</span> <span class="token operator">=</span>
</span><span class="code-line">    <span class="token comment">// unit -&gt; DoorEvent -&gt; EachKnockNotifiesCommand</span>
</span><span class="code-line">    <span class="token keyword">match</span> <span class="token keyword">event</span> <span class="token keyword">with</span> <span class="token comment">// 👈 we are making a decision how to react on events</span>
</span><span class="code-line">    <span class="token operator">|</span> Knocked <span class="token operator">-&gt;</span> SendSms
</span><span class="code-line">    <span class="token operator">|</span> _ <span class="token operator">-&gt;</span> NoAction
</span><span class="code-line"><span class="token keyword">let</span> evolve<span class="token punctuation">:</span> <span class="token class-name">EvolveKnockNotifiesPolicy</span> <span class="token operator">=</span>
</span><span class="code-line">    <span class="token comment">// DoorEvent -&gt; EachKnockNotifiesPolicy -&gt; EachKnockNotifiesCommand * EachKnockNotifiesPolicy</span>
</span><span class="code-line">    <span class="token keyword">fun</span> <span class="token keyword">event</span> policy <span class="token operator">-&gt;</span>
</span><span class="code-line">        <span class="token keyword">let</span> <span class="token punctuation">(</span><span class="token function">EachKnockNotifies</span><span class="token punctuation">(</span><span class="token function">FSM</span><span class="token punctuation">(</span>noPolicyState<span class="token punctuation">,</span> applyTo<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">=</span> policy
</span><span class="code-line">        
</span><span class="code-line">        <span class="token keyword">let</span> command <span class="token operator">=</span> <span class="token keyword">event</span> <span class="token operator">|&gt;</span> applyTo noPolicyState <span class="token comment">// 👈 here is our stateless &quot;policy&quot;</span>
</span><span class="code-line">        
</span><span class="code-line">        command<span class="token punctuation">,</span> policy
</span><span class="code-line">        
</span><span class="code-line"><span class="token keyword">let</span> <span class="token function">eachKnockNotifiesPolicy</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token function">EachKnockNotifies</span><span class="token punctuation">(</span><span class="token function">FSM</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> applyTo<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre></div></div><p>As we have our policy in place, let&#x27;s react to door events:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> eachKnockNotifiesPolicy <span class="token operator">=</span> Door<span class="token punctuation">.</span>Policies<span class="token punctuation">.</span>EachKnockNotifies<span class="token punctuation">.</span><span class="token function">eachKnockNotifiesPolicy</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// 👈 in-memory representation of our policy</span>
</span><span class="code-line"><span class="token function">subscribeToDoorEvents</span><span class="token punctuation">(</span><span class="token keyword">fun</span> <span class="token keyword">event</span> <span class="token operator">-&gt;</span>
</span><span class="code-line">    <span class="token keyword">let</span> command<span class="token punctuation">,</span> _ <span class="token operator">=</span> eachKnockNotifiesPolicy <span class="token operator">|&gt;</span> EachKnockNotifies<span class="token punctuation">.</span>evolve <span class="token keyword">event</span> <span class="token comment">// 👈 policy is stateless so we discard the FSM</span>
</span><span class="code-line">    
</span><span class="code-line">    printfn $<span class="token string">&quot;{event} triggers {command}&quot;</span>
</span><span class="code-line"><span class="token punctuation">)</span>
</span></code></pre></div></div><p>If we run everything in FSI, we shall get:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="code-highlight language-sh"><span class="code-line">// as a reminder, sequence of door interactions we ran:
</span><span class="code-line">// close, knock, knock, lock, knocked, knocked, unlock
</span><span class="code-line">
</span><span class="code-line">EachKnockNotifiesPolicy: Closed triggers NoAction
</span><span class="code-line">EachKnockNotifiesPolicy: Knocked triggers SendSms
</span><span class="code-line">EachKnockNotifiesPolicy: Knocked triggers SendSms
</span><span class="code-line">EachKnockNotifiesPolicy: Locked triggers NoAction
</span><span class="code-line">EachKnockNotifiesPolicy: Knocked triggers SendSms
</span><span class="code-line">EachKnockNotifiesPolicy: Knocked triggers SendSms
</span><span class="code-line">EachKnockNotifiesPolicy: Unlocked triggers NoAction
</span></code></pre></div></div><p>It&#x27;s quite strange to send SMS each time someone knocks on the door, isn&#x27;t it?</p><p>Imagine we want to be notified after someone knocked the door every three times.</p><p>This means that our policy is no longer stateless, as we need to count how many times the fact of knocking happened.</p><p>Time to model!</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">module</span> Policies <span class="token operator">=</span>
</span><span class="code-line">    <span class="token keyword">module</span> ThreeKnocksNotification <span class="token operator">=</span>
</span><span class="code-line">        <span class="token keyword">type</span> <span class="token class-name">ThreeKnocksNotificationCommand</span> <span class="token operator">=</span> SendSms <span class="token operator">|</span> NoAction
</span><span class="code-line">        <span class="token keyword">type</span> <span class="token class-name">KnocksCount</span> <span class="token operator">=</span> KnocksCount <span class="token keyword">of</span> count<span class="token punctuation">:</span> <span class="token class-name">int</span>
</span><span class="code-line">        <span class="token keyword">type</span> <span class="token class-name">SendingSmsOnThreeKnocksPolicy</span> <span class="token operator">=</span>
</span><span class="code-line">            SendingSmsOnThreeKnocksPolicy <span class="token keyword">of</span> <span class="token class-name">Policy</span><span class="token operator">&lt;</span>DoorEvent<span class="token punctuation">,</span> KnocksCount <span class="token operator">*</span> ThreeKnocksNotificationCommand<span class="token punctuation">,</span> KnocksCount<span class="token operator">&gt;</span>
</span><span class="code-line">        <span class="token keyword">type</span> <span class="token class-name">EvolveSendingSmsOnThreeKnocksPolicy</span> <span class="token operator">=</span>
</span><span class="code-line">            Evolve<span class="token operator">&lt;</span>DoorEvent<span class="token punctuation">,</span> ThreeKnocksNotificationCommand<span class="token punctuation">,</span> SendingSmsOnThreeKnocksPolicy<span class="token operator">&gt;</span>
</span></code></pre></div></div><p>Now time to apply our knowledge to evolve the policy:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> applyTo policyState <span class="token keyword">event</span> <span class="token operator">=</span>
</span><span class="code-line">    <span class="token comment">// KnocksCount -&gt; DoorEvent -&gt; KnocksCount * ThreeKnocksNotificationCommand</span>
</span><span class="code-line">    <span class="token keyword">let</span> <span class="token punctuation">(</span>KnocksCount knocksCount<span class="token punctuation">)</span> <span class="token operator">=</span> 
</span><span class="code-line">        <span class="token keyword">event</span> <span class="token operator">|&gt;</span> ThreeKnocksNotificationPolicyState<span class="token punctuation">.</span>applyTo policyState
</span><span class="code-line">    <span class="token keyword">let</span> command <span class="token operator">=</span>
</span><span class="code-line">        <span class="token keyword">match</span> <span class="token keyword">event</span><span class="token punctuation">,</span> knocksCount <span class="token keyword">with</span> <span class="token comment">// 👈 we decide how to react to door event that happened before</span>
</span><span class="code-line">        <span class="token operator">|</span> Knocked<span class="token punctuation">,</span> knocksCount&#x27; <span class="token keyword">when</span> knocksCount&#x27; <span class="token operator">%</span> <span class="token number">3</span> <span class="token operator">=</span> <span class="token number">0</span> <span class="token operator">-&gt;</span> SendSms 
</span><span class="code-line">        <span class="token operator">|</span> _<span class="token punctuation">,</span> _ <span class="token operator">-&gt;</span> NoAction
</span><span class="code-line">        
</span><span class="code-line">    <span class="token punctuation">(</span>KnocksCount knocksCount<span class="token punctuation">)</span><span class="token punctuation">,</span> command
</span><span class="code-line">        
</span><span class="code-line"><span class="token keyword">let</span> evolve<span class="token punctuation">:</span> <span class="token class-name">EvolveSendingSmsOnThreeKnocksPolicy</span> <span class="token operator">=</span>
</span><span class="code-line">    <span class="token comment">// DoorEvent -&gt; SendingSmsOnThreeKnocksPolicy -&gt; ThreeKnocksNotificationCommand * SendingSmsOnThreeKnocksPolicy</span>
</span><span class="code-line">    <span class="token keyword">fun</span> <span class="token keyword">event</span> policy <span class="token operator">-&gt;</span>
</span><span class="code-line">        <span class="token keyword">let</span> <span class="token punctuation">(</span><span class="token function">SendingSmsOnThreeKnocksPolicy</span><span class="token punctuation">(</span><span class="token function">FSM</span><span class="token punctuation">(</span>policyState<span class="token punctuation">,</span> applyTo<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">=</span> policy
</span><span class="code-line">
</span><span class="code-line">        <span class="token keyword">let</span> knocksCount<span class="token punctuation">,</span> command <span class="token operator">=</span> <span class="token keyword">event</span> <span class="token operator">|&gt;</span> applyTo policyState <span class="token comment">// 👈 now &quot;a policy&quot; deals with its state</span>
</span><span class="code-line">        
</span><span class="code-line">        command<span class="token punctuation">,</span> <span class="token function">SendingSmsOnThreeKnocksPolicy</span><span class="token punctuation">(</span><span class="token function">FSM</span><span class="token punctuation">(</span>knocksCount<span class="token punctuation">,</span> applyTo<span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">let</span> sendingSmsOnThreeKnocksPolicy <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token function">SendingSmsOnThreeKnocksPolicy</span><span class="token punctuation">(</span><span class="token function">FSM</span><span class="token punctuation">(</span><span class="token punctuation">(</span>KnocksCount <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">,</span> applyTo<span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">module</span> ThreeKnocksNotificationPolicyState <span class="token operator">=</span>
</span><span class="code-line">    <span class="token keyword">let</span> applyTo policyState <span class="token keyword">event</span> <span class="token operator">=</span>
</span><span class="code-line">    <span class="token comment">//  KnocksCount -&gt; DoorEvent -&gt; KnocksCount</span>
</span><span class="code-line">        <span class="token keyword">let</span> <span class="token punctuation">(</span>KnocksCount knocksCount<span class="token punctuation">)</span> <span class="token operator">=</span> policyState
</span><span class="code-line">        <span class="token keyword">match</span> <span class="token keyword">event</span><span class="token punctuation">,</span> knocksCount <span class="token keyword">with</span> <span class="token comment">// 👈 we decide how to evolve &quot;policy state&quot;</span>
</span><span class="code-line">        <span class="token operator">|</span> Knocked<span class="token punctuation">,</span> knocksCount&#x27; <span class="token operator">-&gt;</span> <span class="token punctuation">(</span>KnocksCount <span class="token punctuation">(</span>knocksCount&#x27; <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token operator">|</span> _<span class="token punctuation">,</span> _ <span class="token operator">-&gt;</span> <span class="token punctuation">(</span>KnocksCount knocksCount<span class="token punctuation">)</span>
</span></code></pre></div></div><p>Ok, we have all in place to subscribe to the events and react to them!</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> knocksPolicyRepository <span class="token operator">=</span> 
</span><span class="code-line">    InMemory<span class="token punctuation">.</span><span class="token function">repositoryFor</span><span class="token punctuation">(</span>Door<span class="token punctuation">.</span>Policies<span class="token punctuation">.</span>ThreeKnocksNotificationPolicy<span class="token punctuation">.</span>sendingSmsOnThreeKnocksPolicy<span class="token punctuation">)</span> <span class="token comment">// 👈 in-memory representation of our policy</span>
</span><span class="code-line"><span class="token function">subscribeToDoorEvents</span><span class="token punctuation">(</span><span class="token keyword">fun</span> <span class="token keyword">event</span> <span class="token operator">-&gt;</span>
</span><span class="code-line">    <span class="token keyword">let</span> currentPolicyState <span class="token operator">=</span> knocksPolicyRepository<span class="token punctuation">.</span><span class="token function">read</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// 👈 we&#x27;re reading the current state of the policy</span>
</span><span class="code-line">    <span class="token keyword">let</span> command<span class="token punctuation">,</span> newPolicyState <span class="token operator">=</span> 
</span><span class="code-line">        Door<span class="token punctuation">.</span>Policies<span class="token punctuation">.</span>ThreeKnocksNotificationPolicy<span class="token punctuation">.</span>evolve <span class="token keyword">event</span> currentPolicyState <span class="token comment">// 👈 evolving the policy</span>
</span><span class="code-line">
</span><span class="code-line">    printfn $<span class="token string">&quot;ThreeKnocksNotificationPolicy: {event} triggers {command}&quot;</span> <span class="token comment">// 👈 here we are executing the result of &quot;a reaction&quot; to event</span>
</span><span class="code-line">
</span><span class="code-line">    knocksPolicyRepository<span class="token punctuation">.</span>save newPolicyState <span class="token comment">// 👈 we&#x27;re saving the new state of the policy</span>
</span><span class="code-line"><span class="token punctuation">)</span>
</span></code></pre></div></div><p>If we run everything in FSI, this is the output we should see:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="code-highlight language-sh"><span class="code-line">// as a reminder, sequence of door interactions we ran:
</span><span class="code-line">// close, knock, knock, lock, knocked, knocked, unlock
</span><span class="code-line">
</span><span class="code-line">ThreeKnocksNotificationPolicy: Closed triggers NoAction
</span><span class="code-line">ThreeKnocksNotificationPolicy: Knocked triggers NoAction
</span><span class="code-line">ThreeKnocksNotificationPolicy: Knocked triggers NoAction
</span><span class="code-line">ThreeKnocksNotificationPolicy: Locked triggers NoAction
</span><span class="code-line">ThreeKnocksNotificationPolicy: Knocked triggers SendSms
</span><span class="code-line">ThreeKnocksNotificationPolicy: Knocked triggers NoAction
</span><span class="code-line">ThreeKnocksNotificationPolicy: Unlocked triggers NoAction
</span></code></pre></div></div><p>It seems that we are going to be notified only after the third knock.</p><p>One thing we need to reveal is the implementation of <code>repositoryFor</code>.</p><p>An avid Reader might notice that this is a in-memory implementation of a <code>Repository</code> pattern.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">module</span> Persistence <span class="token operator">=</span>
</span><span class="code-line">    <span class="token keyword">type</span> <span class="token class-name">Repository</span><span class="token operator">&lt;</span>&#x27;FSM<span class="token operator">&gt;</span> <span class="token operator">=</span>
</span><span class="code-line">        <span class="token keyword">abstract</span> <span class="token keyword">member</span> read<span class="token punctuation">:</span> <span class="token class-name">unit</span> <span class="token operator">-&gt;</span> &#x27;FSM
</span><span class="code-line">        <span class="token keyword">abstract</span> <span class="token keyword">member</span> save<span class="token punctuation">:</span> &#x27;FSM <span class="token operator">-&gt;</span> unit
</span><span class="code-line">
</span><span class="code-line">    <span class="token annotation"><span class="token punctuation">[&lt;</span><span class="token class-name">RequireQualifiedAccess</span><span class="token punctuation">&gt;]</span></span>
</span><span class="code-line">    <span class="token keyword">module</span> InMemory <span class="token operator">=</span>
</span><span class="code-line">        <span class="token keyword">let</span> repositoryFor<span class="token operator">&lt;</span>&#x27;FSM<span class="token operator">&gt;</span> <span class="token punctuation">(</span>initialize<span class="token punctuation">:</span> <span class="token class-name">unit</span> <span class="token operator">-&gt;</span> &#x27;FSM<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token comment">// 👈 deferred initialization</span>
</span><span class="code-line">            <span class="token keyword">let</span> <span class="token keyword">mutable</span> fsm <span class="token operator">=</span> <span class="token function">initialize</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">
</span><span class="code-line">            <span class="token keyword">let</span> read <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span> fsm
</span><span class="code-line">            <span class="token keyword">let</span> save newFsm <span class="token operator">=</span>
</span><span class="code-line">                fsm <span class="token operator">&lt;-</span> <span class="token keyword computation-expression">newFsm</span>
</span><span class="code-line">
</span><span class="code-line">            <span class="token punctuation">{</span>
</span><span class="code-line">                <span class="token keyword">new</span> <span class="token class-name">Repository</span><span class="token operator">&lt;</span>&#x27;FSM<span class="token operator">&gt;</span> <span class="token keyword">with</span>
</span><span class="code-line">                    <span class="token keyword">member</span> this<span class="token punctuation">.</span><span class="token function">read</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token function">read</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">                    <span class="token keyword">member</span> this<span class="token punctuation">.</span><span class="token function">save</span><span class="token punctuation">(</span>newFsm<span class="token punctuation">)</span> <span class="token operator">=</span> save newFsm
</span><span class="code-line">            <span class="token punctuation">}</span>
</span></code></pre></div></div><p>We can read the &quot;state&quot; of the policy after all interactions with the door:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token comment">// executed in FSI</span>
</span><span class="code-line">knocksPolicyRepository<span class="token punctuation">.</span><span class="token function">read</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token keyword">val</span> it<span class="token punctuation">:</span> <span class="token class-name">ThreeKnocksNotificationPolicy<span class="token punctuation">.</span>SendingSmsOnThreeKnocksPolicy</span> <span class="token operator">=</span>
</span><span class="code-line">  SendingSmsOnThreeKnocksPolicy
</span><span class="code-line">    <span class="token punctuation">(</span>FSM <span class="token punctuation">(</span>KnocksCount <span class="token number">4</span><span class="token punctuation">,</span> <span class="token operator">&lt;</span><span class="token keyword">fun</span><span class="token punctuation">:</span><span class="token class-name">sendingSmsOnThreeKnocksPolicy</span>@<span class="token number">178</span><span class="token operator">-</span><span class="token number">16</span><span class="token operator">&gt;</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
</span></code></pre></div></div><p>Phew, that was longer than expected, huh.</p><p>We explored stateless and stateful policies, and typically when thinking about the &quot;state&quot;, one could think of &quot;read-models&quot;.</p><p>Isn&#x27;t it an excellent moment to make a transition (pun intended) to projections?</p><h3 id="third-function---a-projection"><a href="#third-function---a-projection" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Third function - &quot;a projection&quot;</h3><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/functions-and-facts-describe-the-world-projection.png" class="max-h-[35rem]"/></div><div class="italic mx-24">A projection</div></div><p>So according to the diagram, it is driven by events and it produces &quot;read-models&quot;.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">Projection</span><span class="token operator">&lt;</span>&#x27;Event<span class="token punctuation">,</span> &#x27;ReadModel<span class="token operator">&gt;</span> <span class="token operator">=</span> 
</span><span class="code-line">    FSM<span class="token operator">&lt;</span>&#x27;Event<span class="token punctuation">,</span> &#x27;ReadModel<span class="token punctuation">,</span> &#x27;ReadModel<span class="token operator">&gt;</span>
</span></code></pre></div></div><p>Hmm, but wait a second.</p><p>As we are discussing functions, and both &quot;an aggregate&quot; and &quot;a policy&quot; are functions with their corresponding blocks (&quot;stickies&quot;) in the diagram, shouldn&#x27;t &quot;a projection&quot; be a subject of the same property?</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/functions-and-facts-describe-the-world-missing-projection.png" class="max-h-[35rem]"/></div><div class="italic mx-24">What is missing?</div></div><p>Meaning, shouldn&#x27;t a function have a corresponding &quot;sticky&quot; in the diagram?</p><p>It seem that an arrow from a <span class="text-orange-500">Domain Event</span> to a <span class="text-green-200">Read Model</span> is a bit of simplification and &quot;transforming&quot; effect is hidden &quot;in the arrow&quot;.</p><p>Let&#x27;s make &quot;a projection&quot; function explicit!</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/functions-and-facts-describe-the-world-expressed-projection.png" class="max-h-[35rem]"/></div><div class="italic mx-24">Visible projection function</div></div><p>It feels somewhat right - &quot;a projection&quot; is expressed visually in the diagram.</p><p>In the original <a href="https://marcosh.github.io/post/2021/10/27/ddd-state-machines.html">article</a>, the author used <code>Opened</code> event to be applied to a projection - we&#x27;re going to use <code>Unlocked</code> instead.</p><p>This might be a nice event to follow up with second-order events in the next tales.</p><p>We have all in place to represent &quot;a projection&quot; in code:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">module</span> Projections <span class="token operator">=</span>
</span><span class="code-line">    <span class="token keyword">module</span> UnlockedCounts <span class="token operator">=</span>
</span><span class="code-line">        <span class="token keyword">type</span> <span class="token class-name">UnlockCount</span> <span class="token operator">=</span> UnlockCount <span class="token keyword">of</span> count<span class="token punctuation">:</span> <span class="token class-name">int</span>
</span><span class="code-line">        <span class="token keyword">type</span> <span class="token class-name">UnlockCountProjection</span> <span class="token operator">=</span> 
</span><span class="code-line">            UnlockCountProjection <span class="token keyword">of</span> <span class="token class-name">Projection</span><span class="token operator">&lt;</span>DoorEvent<span class="token punctuation">,</span> UnlockCount<span class="token operator">&gt;</span>   
</span><span class="code-line">        <span class="token keyword">type</span> <span class="token class-name">EvolveUnlockCountProjection</span> <span class="token operator">=</span> 
</span><span class="code-line">            Evolve<span class="token operator">&lt;</span>DoorEvent<span class="token punctuation">,</span> UnlockCount<span class="token punctuation">,</span> UnlockCountProjection<span class="token operator">&gt;</span>
</span></code></pre></div></div><p>It means that we are going to count how many times the door was unlocked.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> applyTo readModel <span class="token keyword">event</span> <span class="token operator">=</span>
</span><span class="code-line">    <span class="token comment">// UnlockCount -&gt; DoorEvent -&gt; UnlockCount</span>
</span><span class="code-line">    <span class="token keyword">let</span> <span class="token punctuation">(</span>UnlockCount count<span class="token punctuation">)</span> <span class="token operator">=</span> readModel
</span><span class="code-line">    <span class="token keyword">let</span> newCount <span class="token operator">=</span>
</span><span class="code-line">        <span class="token keyword">match</span> <span class="token keyword">event</span><span class="token punctuation">,</span> readModel <span class="token keyword">with</span> <span class="token comment">// 👈 we&#x27;re deciding how to build &quot;read model&quot; with a new event</span>
</span><span class="code-line">        <span class="token operator">|</span> Unlocked<span class="token punctuation">,</span> UnlockCount count <span class="token operator">-&gt;</span> UnlockCount <span class="token punctuation">(</span>count <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token operator">|</span> _ <span class="token operator">-&gt;</span> readModel
</span><span class="code-line">    
</span><span class="code-line">    newCount
</span><span class="code-line">                
</span><span class="code-line"><span class="token keyword">let</span> evolve<span class="token punctuation">:</span> <span class="token class-name">EvolveUnlockCountProjection</span> <span class="token operator">=</span>
</span><span class="code-line">    <span class="token comment">// DoorEvent -&gt; UnlockCountProjection -&gt; UnlockCount * UnlockCountProjection</span>
</span><span class="code-line">    <span class="token keyword">fun</span> <span class="token keyword">event</span> projection <span class="token operator">-&gt;</span>
</span><span class="code-line">        <span class="token keyword">let</span> <span class="token punctuation">(</span><span class="token function">UnlockCountProjection</span><span class="token punctuation">(</span><span class="token function">FSM</span><span class="token punctuation">(</span>readModel<span class="token punctuation">,</span> applyTo<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">=</span> projection
</span><span class="code-line">        <span class="token keyword">let</span> newCount <span class="token operator">=</span> <span class="token keyword">event</span> <span class="token operator">|&gt;</span> applyTo readModel
</span><span class="code-line">
</span><span class="code-line">        newCount<span class="token punctuation">,</span> <span class="token function">UnlockCountProjection</span><span class="token punctuation">(</span><span class="token function">FSM</span><span class="token punctuation">(</span>newCount<span class="token punctuation">,</span> applyTo<span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class="code-line">        
</span><span class="code-line"><span class="token keyword">let</span> <span class="token function">unlockCountProjection</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token function">UnlockCountProjection</span><span class="token punctuation">(</span><span class="token function">FSM</span><span class="token punctuation">(</span>UnlockCount <span class="token number">0</span><span class="token punctuation">,</span> applyTo<span class="token punctuation">)</span><span class="token punctuation">)</span>
</span></code></pre></div></div><p>Now we can subscribe to the events and react to them:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> unlockCountProjectionRepository <span class="token operator">=</span>
</span><span class="code-line">    InMemory<span class="token punctuation">.</span><span class="token function">repositoryFor</span><span class="token punctuation">(</span>Door<span class="token punctuation">.</span>Projections<span class="token punctuation">.</span>UnlockedCounts<span class="token punctuation">.</span>unlockCountProjection<span class="token punctuation">)</span>
</span><span class="code-line">subscribeToDoorEvents <span class="token punctuation">(</span><span class="token keyword">fun</span> <span class="token keyword">event</span> <span class="token operator">-&gt;</span>
</span><span class="code-line">    <span class="token keyword">let</span> existingUnlocksCountProjection <span class="token operator">=</span> unlockCountProjectionRepository<span class="token punctuation">.</span><span class="token function">read</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token keyword">let</span> <span class="token punctuation">(</span>UnlockCount count<span class="token punctuation">)</span><span class="token punctuation">,</span> newUnlocksCountProjection <span class="token operator">=</span>
</span><span class="code-line">        existingUnlocksCountProjection
</span><span class="code-line">        <span class="token operator">|&gt;</span> Door<span class="token punctuation">.</span>Projections<span class="token punctuation">.</span>UnlockedCounts<span class="token punctuation">.</span>evolve <span class="token keyword">event</span>
</span><span class="code-line">
</span><span class="code-line">    printfn $<span class="token string">&quot;Door unlocked {count} number of times&quot;</span>
</span><span class="code-line">    
</span><span class="code-line">    unlockCountProjectionRepository<span class="token punctuation">.</span>save newUnlocksCountProjection
</span><span class="code-line"><span class="token punctuation">)</span>
</span></code></pre></div></div><p>Applying the same door interactions sequence as before, we&#x27;re getting:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="code-highlight language-text"><span class="code-line">// as a reminder, sequence of door interactions we ran:
</span><span class="code-line">// close, knock, knock, lock, knocked, knocked, unlock
</span><span class="code-line">Door unlocked 0 number of times
</span><span class="code-line">Door unlocked 0 number of times
</span><span class="code-line">Door unlocked 0 number of times
</span><span class="code-line">Door unlocked 0 number of times
</span><span class="code-line">Door unlocked 0 number of times
</span><span class="code-line">Door unlocked 0 number of times
</span><span class="code-line">Door unlocked 1 number of times
</span></code></pre></div></div><p>Preditable as we unlocked the door only at the end of the sequence.</p><p>Same with reading the &quot;state&quot; of the projection using FSI:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="code-highlight language-sh"><span class="code-line">unlockCountProjectionRepository.read<span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">val it: UnlockCountProjection <span class="token operator">=</span>
</span><span class="code-line">  UnlockCountProjection
</span><span class="code-line">    <span class="token punctuation">(</span>FSM <span class="token punctuation">(</span>UnlockCount <span class="token number">1</span>, <span class="token operator">&lt;</span>fun:unlockCountProjection@118-1<span class="token operator"><span class="token file-descriptor important">9</span>&gt;</span><span class="token punctuation">))</span>
</span></code></pre></div></div><p>It looks strangely similar to the policy state, isn&#x27;t it?</p><p>Maybe we should look at signatures of all <code>applyTo</code> functions from modules (<code>DoorState</code>, <code>ThreeKnocksNotificationPolicyState</code> and <code>Projections.UnlockedCounts</code>) related to &quot;state&quot;?</p><ul><li><code>Door.DoorState</code> module</li></ul><p><span class="text-green-200">DoorState</span> -&gt; <span class="text-orange-500">DoorEvent</span> -&gt; <span class="text-green-200">DoorState</span></p><ul><li><code>ThreeKnocksNotificationPolicy.ThreeKnocksNotificationPolicyState</code> module</li></ul><p><span class="text-green-200">KnocksCount</span> -&gt; <span class="text-orange-500">DoorEvent</span> -&gt; <span class="text-green-200">KnocksCount</span></p><ul><li><code>Projections.UnlockedCounts</code> module</li></ul><p><span class="text-green-200">UnlockCount</span> -&gt; <span class="text-orange-500">DoorEvent</span> -&gt; <span class="text-green-200">UnlockCount</span></p><p>All of them follow the same pattern - <code>&#x27;State -&gt; &#x27;Event -&gt; &#x27;State</code> - and it turns out that&#x27;s exactly the function signature of &quot;a projection&quot;!</p><p>This means that both &quot;a policy&quot; and &quot;an aggregate&quot; functions used &quot;a projection&quot; function to &quot;build&quot; (or <strong>evolve</strong>) a &quot;read-model&quot; (or rather <strong>a state</strong>), to <strong>decide</strong> how to deal with incoming input, based on the current <strong>state</strong>.</p><p>Dear Reader, if you are interested in detailed origins of <strong>evolve</strong> and <strong>decide</strong> concepts, please depart to a great work by Jeremie Chassaing, titled <a href="https://thinkbeforecoding.com/post/2021/12/17/functional-event-sourcing-decider">Functional Event Sourcing Decider</a>, and read it carefully.</p><p>It is very insightful and thought provoking!</p><h3 id="functions-and-facts-described-the-world"><a href="#functions-and-facts-described-the-world" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Functions (and facts) described the world</h3><p>What a journey!</p><p>We were able to visit three concepts from &quot;tactical Domain-Driven Design&quot; and Event Storming - &quot;an aggregate&quot;, &quot;a policy&quot; and &quot;a projection&quot;.</p><p>Each of them was modelled using a &quot;state machine&quot; - a basic structure to represent its &quot;state&quot; (which eventually for &quot;a policy&quot; and &quot;an aggregate&quot; turned out to be &quot;a projection&quot;&#x27;s state!) and &quot;deciding function&quot;.</p><p>Thanks to F# and FSI, we were able to quickly get feedback from our findings.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/functions-and-facts-describe-the-world-functions.png" class="max-h-[35rem]"/></div><div class="italic mx-24">Three functions</div> <div class="italic mx-24">Click <a target="_blank" href="https://talesfrom.dev/static/images/functions-and-facts-describe-the-world-functions.png">here</a> to see bigger picture.</div></div><p>Even though each of those concepts have three distinct names - all of them can be represented by functions, either driven by events or producing them.</p><p>&quot;functions are just functions&quot; - this is how the <a href="https://bsky.app/profile/borar.bsky.social/post/3lczvxuxm722f">discussion</a> ended up (at least the one I referred to) - which undeniably is true and I agree with it wholeheartedly.</p><p>I hope you were able to see it too, dear Reader.</p><p>At the same time, &quot;strategic Domain-Driven Design&quot; teaches us to organize the knowledge of the domain, in the form of the language, so that we are able to communicate clearly and effectively.</p><p>I believe this applies to those building blocks too - &quot;an aggregate&quot;, &quot;a policy&quot; and &quot;a projection&quot; - as they are just functions, but they are also &quot;a language&quot; to communicate the intention behind.</p><h3 id="objects-functions-and-words"><a href="#objects-functions-and-words" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Objects, functions and words</h3><p>And it is not the fault of the functions to get misinterpreted - especially when it comes to our sweet &quot;aggregates&quot; - which often get bloated, heavy and full of unnecessary responsibilities.</p><p>&quot;The beauty is in the eye of the beholder&quot; - if someone wants to see &quot;an object&quot; in &quot;an aggregate&quot;, soon &quot;a state&quot; might cover the whole thing.</p><p>Similar to a Zen Koan, we could express:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>“When a wise man points at a set of rules to enforce consistent state change with a state, the fools look at the state, not at a set of rules to enforce consistent state change.”</p></div></div></div><p>Of course, one could argue &quot;Damian, but each of FSMs you presented aggregated a state and a function! We saw objects, didn&#x27;t we?!&quot;.</p><p>Even though there was &quot;a state&quot; involved, typically it is a private business of &quot;an object&quot; - its &quot;implementation detail&quot;.</p><p>And yet again this &quot;state&quot; easily distracts us from the main capability of &quot;an object&quot; - to be able to collaborate with others via message-passing and transforming the incoming input into the output. (if you are interested in more, please check <a href="https://talesfrom.dev/blog/the-ambiguity-of-objects">The ambiguity of objects</a>)</p><p>We used the best language in the universe (no, I am not biased) - my beloved F# - to explore the transfoming nature of all those DDD building blocks.</p><p>It was easy to focus on that processing aspect, as functions are the first-class citizens in F# - which was followed by an immutable-first approach for modeling structures (even though if it wasn&#x27;t emphasized earlier), giving birth to &quot;events&quot;.</p><p>Functions are just functions and giving them names should nourish and ease the collaboration.</p><p>We reached the end of our journey, dear Reader - thank you for your patience and time, as we needed plenty of both.</p><p>Til the next time!</p>]]></content:encoded>
    <pubDate>Fri, 03 Jan 2025 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>model</category><category>modeling</category><category>mental models</category><category>representations</category><category>knowledge working</category><category>abstractions</category><category>exploration</category><category>fsharp</category><category>fsharp-advent-calendar</category><category>functional</category><category>paradigms</category><category>state-machines</category><category>event sourcing</category><category>event driven</category><category>events</category><category>event storming</category><category>domain-driven design</category><category>software design</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/abstracting-over-people</guid>
    <title>Abstracting over people</title>
    <link>https://talesfrom.dev/blog/abstracting-over-people</link>
    <description>How to model people?</description>
    <content:encoded><![CDATA[<h3 id="an-underperforming-piston"><a href="#an-underperforming-piston" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>An underperforming piston</h3><p>Imagine that there&#x27;s a team of four: Mark, Tim, Noah and Sarah. They are software engineers, working together and building digital product.</p><p>They all have different skills, experiences and personalities.</p><p>Turns out that during &quot;a performance review&quot;, a project manager discovered that Tim is underperforming.</p><p>&quot;We have underperforming piston in the engine&quot;, he said.</p><p>Underperforming? What does it actually mean?</p><p>Well, based on number of lines, number of commits, number of solved tickets in Jira - of course.</p><p>All other people are dilligently taking tasks from the backlog and finishing them.</p><p>Well, Tim takes the courage to suggest improvements to the process - working together and finding a way to have a sustainable pace.</p><p>But missles of feedback have been launched and now Tim knows that he need to improve.</p><h3 id="money"><a href="#money" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Money</h3><p>The same team is doing their best to bring the best feature of all time - users are impatiently waiting to get their hands on it.</p><p>Thanks to applied feedback, now Tim takes more work on his shoulders and finishes things on time.</p><p>Even though the digital product has numerous users (both private individuals and businesses), growth rate went down, slightly.</p><p>Management is not happy with that.</p><p>Even adding an aid of the archtecture team didn&#x27;t help.</p><p>Decision is there: &quot;we need to cut costs&quot;.</p><p>Sarah, the team leader, costs the most. She&#x27;s really experienced with the product and also technically skilled.</p><p>&quot;A cost is a cost&quot;, a project manager says.</p><p>She&#x27;s asked to do a handover with all of her leadership duties to the project manager and let others ask all the questions regarding the product (&quot;because it&#x27;s all about technical stuff, right?&quot;).</p><h3 id="a-replacement"><a href="#a-replacement" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>A replacement</h3><p>Turns out that couple of weeks after &quot;cost cutting&quot;, the team is not doing well.</p><p>Somehow the work isn&#x27;t getting done - &quot;the engine&quot; is not working as expected.</p><p>&quot;But we had all those architectural meetings and metrics in place...&quot;, a project manager was thinking silently.</p><p>The decision has been made - &quot;we need a team leader&quot;.</p><p>Countless hours of interviews, discussions and meetings later, a new team leader is contracted: Keith - a person with a lot of IT experience.</p><p>The team got this information in a form of an email - a day before Keith&#x27;s first day.</p><p>&quot;He is just a replacement for Sarah - you will love him&quot;, a project manager said.</p><p>Keith is a nice person, but he&#x27;s not Sarah.</p><p>He does not understand the product, and actually, doesn&#x27;t want to learn the domain - &quot;somewhere down the line, it&#x27;s all about the code, right?&quot;, he once said.</p><h3 id="a-perspective"><a href="#a-perspective" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>A perspective</h3><p>How the hell one can abstract over people?</p><p>What does it actually mean?!</p><p>You might be wondering, dear Reader, if I am playing with you by using trickery of software design concepts - like &quot;abstraction&quot;.</p><p>Turns out that it&#x27;s yet again about looking at the subject from a different perspective, using various lenses.</p><p>We are trained in finding patterns, creating models and pulling abstractions out of the domain so that we can fight back with the complexity that unmercifully nibbles us.</p><p>Sometimes charging at us like a hungry, <a href="https://grugbrain.dev">invisible</a> lion.</p><p>It&#x27;s tempting to state that we were trained through the evolution to build abstractions - to survive.</p><p>Even if we might not do it consciously, we abstract over people.</p><h3 id="modeling-people"><a href="#modeling-people" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Modeling people</h3><p>I hope dear Reader you know that I really like definitions - not because I am a fan of dictionaries, but because they provide a common ground for the discussion.</p><p>One of the simplest definition of &quot;an abstraction&quot;, I like to use, is the following:</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">a process of abstraction</div><div class="pb-2 px-3"><div class="break-words"><p>Taking away the details</p></div></div></div><p>It comes from the latin etymology of the word &quot;abstractio&quot; but still it conveys a general meaning.</p><p>So in a way we &quot;abstract over people&quot; by taking away the details of a humane aspect - a specific person &quot;ceases to exist&quot; in favor of an abstraction.</p><p>And as we all know, abstractions help us taming the complexity.</p><p>But sometimes we want to deal with this complexity - we want to understand the person, not the abstraction.</p><p>It isn&#x27;t rare that people are abstracted into &quot;isolated pistons&quot; in the engine, subconsciously leading our thinking to the conclusion: &quot;a system is the same as the sum of its parts&quot;.</p><p>Easily interchangeable, easily measurable.</p><p>Which leads into another level of abstraction - a replacable cogwheel.</p><p>Even if we can &quot;model&quot; people as resources, especially when talking about their availability, we should remember it is just an abstraction.</p><p>Its main function is to help reducing the complexity of the designed system so that we can think about it differently (or at all?).</p><p>We couldn&#x27;t tame the depth of each human being, the same as we cannot comprehend the complexity of the world we live in.</p><p>So it is not about know-how (how to abstract over people, what abstractions or metaphors we can use) but know-when (when to use abstractions).</p><h3 id="modeling-teams"><a href="#modeling-teams" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Modeling teams</h3><p>As soon as we jump onto another level of abstraction, we no longer deal with people, but with another &quot;grouping&quot; concept - a team.</p><p>How do we think about such a concept?</p><p>The most common is that there&#x27;s a group of individuals, taking tasks from the backlog, exchanging status each morning and sprinting through sprints - a typical description of a team, right?</p><p>There&#x27;s a great <a href="https://talesfrom.dev/blog/the-ambiguity-of-team-work">ambiguity of team work</a> - all stemming from used abstractions.</p><p>Words have power - they carry the context with them, along with implicit, invisible rules.</p><p>Do we build our teams?</p><p>Assemble them from parts, excuse me, poeple?</p><p>Or maybe we grow teams, letting the maturity to happen, through blood, tears?</p><p>I know, it&#x27;s just &quot;a language&quot; and it for sure does not affect the way we operate and see the world.</p><h3 id="everything-has-its-place-and-everything-is-on-its-place"><a href="#everything-has-its-place-and-everything-is-on-its-place" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Everything has its place and everything is on its place</h3><p>Don&#x27;t get me wrong, dear Reader, I do not claim we should never abstract when &quot;dealing&quot; with people.</p><p>As it is with other tools (abstractions are tools too!), we should use them wisely.</p><p>When it comes to knowledge working, things get complicated, or even complex, really, really fast.</p><p>&quot;Handovers&quot; do not work, coordination meetings are full of wishful thinking and &quot;cost cutting&quot; looks more like a &quot;cutting the roots&quot;.</p><p>At the time of writing, I do not hire people and I do not pay their salaries - so it might be easy for me to say so.</p><p>But I do work with people, I do talk with them, I do listen to them.</p><p>I know that we build <a href="https://talesfrom.dev/blog/systems-by-with-for-people">Systems: by, with, for people</a>.</p><p>When one is &quot;modeling&quot; people as isolated, replacable, costful cogwheels or pistons, the attention is placed on the very specific plane: optimizing for work.</p><p>Leading to constant thinking about the utilization, the efficiency and the performance - totally missing <a href="https://www.amazon.com/Goal-Process-Ongoing-Improvement/dp/0884271951">the goal</a>.</p><h3 id="all-models-are-wrong-imperfect-but-some-are-useful"><a href="#all-models-are-wrong-imperfect-but-some-are-useful" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;All models are wrong (=imperfect), but some are useful&quot;</h3><p>Knowing that we can be &quot;modeled&quot; as &quot;a cost&quot;, how can we use that knowledge?</p><p>What about focusing on the things that really matter - deliverying value to the stakeholders and users, and not performing next round of cargo culting?</p><p>Then, maybe our energy will flow into optimizing for outcomes, not for outputs.</p><p>What is with the goal of &quot;the engine&quot; - to make each piston perform at its best, risking some of them getting locally &quot;better&quot;?</p><p>Or maybe the goal is to get the car from point A to point B, because the user wants to book a reservation for their life trip?</p><p>Interestingly, the closer we apply the abstractions to the humane aspects, the more we might get into the realm of metaphors.</p><p>Are metaphors same as abstractions? Perspectives that one can have on the same thing? Looking from various angles?</p><p>This might lead us to the very powerful expression, that can be found in <a href="https://www.amazon.com/Joy-Abstraction-Exploration-Category-Theory/dp/1108477224">The joy of abstraction</a>: &quot;There is a context in which...&quot;.</p><p>And as always, undeniably, the context is the king.</p>]]></content:encoded>
    <pubDate>Tue, 10 Dec 2024 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>model</category><category>modeling</category><category>mental models</category><category>representations</category><category>knowledge working</category><category>ambiguity</category><category>misconceptions</category><category>abstractions</category><category>language</category><category>language patterns</category><category>peopleware</category><category>people skills</category><category>team building</category><category>leadership</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/the-ambiguity-of-objects</guid>
    <title>The ambiguity of objects</title>
    <link>https://talesfrom.dev/blog/the-ambiguity-of-objects</link>
    <description>Are objects essentially bad?</description>
    <content:encoded><![CDATA[<h3 id="wanna-eat-a-burger"><a href="#wanna-eat-a-burger" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Wanna eat a burger?</h3><p>Imagine there&#x27;s a guy named <span class="mr-2 text-[#d963dd]">Chris</span>, who took his fate in his own hands and started his life career as CEO of a little burger foodtruck.</p><p>&quot;Anti-hunger&quot;, he called it.</p><p><span class="mr-2 text-[#d963dd]">Chris</span>had the experience and the idea how to run the best burger foodtruck in town.</p><p>Even though people adviced him to start a restaurant, hire chefs and staff, buy very expensive cooking equipment, he decided to start small.</p><p>&quot;But what if you suddenly need to scale infinitely?!&quot;, they asked.</p><p>So <span class="mr-2 text-[#d963dd]">Chris</span>had his little foodtruck.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-objects-chris-foodtruck.png" class="max-h-[20rem]"/></div><div class="italic mx-24"><span class="mr-2 text-[#d963dd]">Chris</span>, his foodtruck and a customer</div></div><p>This is how it all began.</p><h3 id="anti-hunger-process"><a href="#anti-hunger-process" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Anti-hunger process</h3><p>Everything started with a customer having a desire to battle the hunger.</p><p><span class="mr-2 text-[#d963dd]">Chris</span>was ready to take the order and write it down so that he knew what to prepare.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-objects-steps-taking-an-order.png" class="max-h-[20rem]"/></div><div class="italic mx-24">Taking an order</div></div><p>Then <span class="mr-2 text-[#d963dd]">Chris</span>needed to prepare the beef.</p><p>He needed to take a raw beef and flip it two times on the grill, with a strictly measured time and temperature, to get the perfectly grilled beef.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-objects-steps-preparing-beef.png" class="max-h-[20rem]"/></div><div class="italic mx-24">Preparing a beef</div></div><p>Next phase was to prepare the bun.</p><p>It was pretty simple - just slicing it.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-objects-steps-slicing-bun.png" class="max-h-[20rem]"/></div><div class="italic mx-24">Slicing a bun</div></div><p>When the perfectly prepared beef and sliced bun were ready, <span class="mr-2 text-[#d963dd]">Chris</span>needed to put them together.</p><p>He added his homemade cheese and homegrown tomatoes - composing everything together, in his special way, created the best experience for the customer!</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-objects-steps-composing-a-burger.png" class="max-h-[20rem]"/></div><div class="italic mx-24">Composing a burger</div></div><p><span class="mr-2 text-[#d963dd]">Chris</span>also decided that each of his burgers should be packaged in a dedicated box, with a special message on it.</p><p>Just to make the customer feel special.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-objects-steps-packaging-a-burger.png" class="max-h-[20rem]"/></div><div class="italic mx-24">Packaging a burger</div></div><p>When the burger was ready - well-prepared, well-composed and well-packaged - <span class="mr-2 text-[#d963dd]">Chris</span>handed it over to the customer.</p><p>So this event turned a hungry customer into a happy customer.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-objects-deliverying-product.png" class="max-h-[20rem]"/></div><div class="italic mx-24">Deliverying the experience</div></div><p>That&#x27;s everything that <span class="mr-2 text-[#d963dd]">Chris</span>needed to do to make his customer happy.</p><p>That was the &quot;Anti-hunger&quot; process, in the nutshell.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-objects-process.png" class="max-h-[20rem]"/></div><div class="italic mx-24">The &quot;Anti-hunger&quot; process</div></div><p><span class="mr-2 text-[#d963dd]">Chris</span>knew every single step, all the rules and all the details of the &quot;Anti-hunger&quot; process.</p><p>He was able to transform a raw beef into a perfectly grilled beef, based on the set of instructions he had in his head.</p><p>Same for turning a whole bun into a sliced one, and finally composing everything into a masterpiece.</p><p>He was responsibile for everything and because of working alone, he didn&#x27;t need to share any information with anyone.</p><p><span class="mr-2 text-[#d963dd]">Chris</span>was a true virtuoso - he was able to transform raw products into a magical experience!</p><h3 id="what-more-customers"><a href="#what-more-customers" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What?! More customers?!</h3><p><span class="mr-2 text-[#d963dd]">Chris</span>was definitely doing great.</p><p>People were recommending his burgers to their friends, and they were coming to his foodtruck to try them.</p><p>In a blazingly fast time, <span class="mr-2 text-[#d963dd]">Chris</span>had a line of customers waiting to order his burgers.</p><p>That made him both happy and concerned.</p><p>He knew he wouldn&#x27;t be able to handle every single step alone.</p><p>That was his eventual decision - &quot;I need to delegate some of the responsibilities!&quot;.</p><p>So he hired a new team members: <span class="mr-2 text-[#2c74c9]">Ben</span>, <span class="mr-2 text-[#186321]">Jim</span>, <span class="mr-2 text-[#5f262a]">Mike</span>and <span class="mr-2 text-[#6f747d]">Henry</span>.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-objects-chris-and-friends.png" class="max-h-[20rem]"/></div><div class="italic mx-24"><span class="mr-2 text-[#d963dd]">Chris</span>and his team</div></div><p><span class="mr-2 text-[#d963dd]">Chris</span>needed to organize the work in a totally different manner, as before he didn&#x27;t need to collaborate.</p><p>He was responsible for the entire processing.</p><p><span class="mr-2 text-[#d963dd]">Chris</span>decided that he is going to be responsible for taking the orders and for having a lovely chat with the customer.</p><p>He is going to play a role of a &quot;frontman&quot;.</p><p>But from now on, everything was about to change.</p><h3 id="anti-hunger-process-version-20"><a href="#anti-hunger-process-version-20" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Anti-hunger process, version 2.0</h3><p>The role that <span class="mr-2 text-[#d963dd]">Chris</span>played was similar to the first step from the initial version of the &quot;Anti-hunger&quot; process.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-objects-steps-taking-an-order.png" class="max-h-[20rem]"/></div><div class="italic mx-24">Taking an order</div></div><p>Placed order was very important fact for <span class="mr-2 text-[#2c74c9]">Ben</span>- he was responsible for preparing the beef.</p><p><span class="mr-2 text-[#2c74c9]">Ben</span>was a master of grilling beef - he took all necessary training from <span class="mr-2 text-[#d963dd]">Chris</span>, becoming the expert in the domain of burger grilling, and eventually understood the secret of &quot;Anti-hunger burger&quot;.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-objects-steps-preparing-beef-collaboration.png" class="max-h-[20rem]"/></div><div class="italic mx-24">Preparing a beef</div></div><p>There was one difference between jobs of <span class="mr-2 text-[#d963dd]">Chris</span>and <span class="mr-2 text-[#2c74c9]">Ben</span>- along with yielding the perfectly grilled beef, <span class="mr-2 text-[#2c74c9]">Ben</span>needed to send a message regarding his part being finished.</p><p>Then, <span class="mr-2 text-[#186321]">Jim</span>knew what to do and he was able to pick the burger up to perfom his part - taking a bun and slicing it.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-objects-steps-slicing-bun-collaboration.png" class="max-h-[20rem]"/></div><div class="italic mx-24">Slicing a bun</div></div><p>When <span class="mr-2 text-[#186321]">Jim</span>finished his slicing part, he needed to send a message that the bun became sliced, providing the product of his processing too.</p><p>The big final! Composing everything together, with some additions - that was the job of <span class="mr-2 text-[#5f262a]">Mike</span>.</p><p>Because everything was working in a perfect, sequential harmony, <span class="mr-2 text-[#5f262a]">Mike</span>was waiting to respond to a &quot;call&quot; from <span class="mr-2 text-[#186321]">Jim</span>about bun becoming sliced so that he could grab both perfectly grilled burger and sliced bun and start his part!</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-objects-steps-composing-a-burger-collaboration.png" class="max-h-[20rem]"/></div><div class="italic mx-24">Composing a burger</div></div><p>Of course, as before, <span class="mr-2 text-[#5f262a]">Mike</span>needed to send a message that his part was finished.</p><p><span class="mr-2 text-[#6f747d]">Henry</span>was sitting there and, waiting to pick up the message and get the Anti-hunger burger and package it.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-objects-steps-packaging-a-burger-collaboration.png" class="max-h-[20rem]"/></div><div class="italic mx-24">Packaging a burger</div></div><p>Next to the ready Anti-hunger package, <span class="mr-2 text-[#6f747d]">Henry</span>loudly notified a hungry customer that his hunger is about to be defeated.</p><p>The customer was able to respond to a call and pick up his Anti-hunger burger which resulted in a happy customer.</p><p>When the customer experienced the joy of battling the hunger, he was ready to share this experience with others, by sending text messages to his friends.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-objects-deliverying-product-collaboration.png" class="max-h-[20rem]"/></div><div class="italic mx-24">Deliverying the experience</div></div><p><span class="mr-2 text-[#d963dd]">Chris</span>, <span class="mr-2 text-[#2c74c9]">Ben</span>, <span class="mr-2 text-[#186321]">Jim</span>, <span class="mr-2 text-[#5f262a]">Mike</span>and <span class="mr-2 text-[#6f747d]">Henry</span>were collaborating together to provide the best experience for the customer - each of them was responsible for a different part of the &quot;Anti-hunger&quot; process.</p><p>&quot;Anti-hunger&quot; process, version 2.0, was a success!</p><p>They were working in prosperity, with a clear understanding of their roles and responsibilities, evolving into the best burger foodtruck enteprise in the whole town!</p><h3 id="you-must-be-kidding-right"><a href="#you-must-be-kidding-right" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>You must be kidding, right?</h3><p>&quot;What are all those fancy pictures, Damian?!&quot;, you might ask, dear Reader.</p><p>You might feel that I lured you to read about objects, explain intentions with code, but instead I gave you a tale about a guy who is making burgers.</p><p>Fair point!</p><p>Let me start from the beginning then.</p><p>From time to time I observe the eternal fight between two groups of people - those who are in &quot;favor of objects&quot; and those who are in &quot;cursing on objects&quot; (simply saying).</p><p>Objects might seem an obsolete tool for solving modern problems.</p><p>&quot;We all shall use functional programming!&quot;, some people say.</p><p>&quot;I need no objects - I just need data and transformations!&quot;, others comment.</p><p>Well, it might be all true but the problem is that there is too much focus on &quot;objects&quot; and not of an phenomenon that emerges when they start collaborating.</p><h3 id="object-ism"><a href="#object-ism" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Object-ism</h3><p>As the famous Zen Koan says:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>“When a wise man points at the moon with his finger, the fools look at the finger, not at the moon.”</p></div></div></div><p>We could have similar when it comes to objects:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>“When a wise man points at collaboration via message passing with objects, the fools look at objects, not at collaboration via message passing.”</p></div></div></div><p>I am not a wise man, that&#x27;s for sure, but a smart guy, named Alan Kay, <a href="https://userpage.fu-berlin.de/~ram/pub/pub_jf47ht81Ht/doc_kay_oop_en">once said (paraphrasing)</a>:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>OOP to me means only <strong>messaging</strong>, local retention and protection and hiding of state-process, and extreme late-binding of all things.</p></div></div></div><p>When we think about messaging for a while - why are we sending messages? Why are we exchanging thoughts? Why are we communicating our struggles?</p><p>To interact.</p><p>To collaborate.</p><p>To organize ourselves.</p><p>To solve problems, together.</p><p>When <span class="mr-2 text-[#d963dd]">Chris</span>was working alone, he didn&#x27;t need to communicate with anyone.</p><p>We was able to <strong>transform</strong> raw products into a magical experience.</p><p>During applying those transformations, he used his <strong>mental models</strong> - even though it was highly unconscious process (pun intended), still it all translated to lower-level instructions to follow.</p><p>When <span class="mr-2 text-[#d963dd]">Chris</span>invited collaborators to join the crew, <strong>transformations</strong> did not disappear, they got assigned to different roles.</p><p>Of course, he needed to share specific <strong>rules</strong>, related to each transformation, by teaching his fellow team members.</p><h3 id="objects-transformations-and-responsibilities"><a href="#objects-transformations-and-responsibilities" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Objects, transformations and responsibilities</h3><p>Let&#x27;s take a look at grilling a beef.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-objects-steps-preparing-beef.png" class="max-h-[20rem]"/></div><div class="italic mx-24">Transforming a raw beef burger in a grilled burger</div></div><p>One could say is forms a function:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">GrillBeef</span> <span class="token operator">=</span> RawBeef <span class="token operator">-&gt;</span> OneSideGrilledBeef <span class="token operator">-&gt;</span> GrilledBurger
</span></code></pre></div></div><p>That signatures enforces some contraints, e.g. you cannot turn a raw beef directly into a grilled burger.</p><p>In other words, to get a <code>GrilledBurger</code>, one needs to pass a <code>RawBeef</code>, then pass a <code>OneSideGrilledBeef</code>.</p><p>Such simple transformation can be done by one person, right?</p><p>We saw it during our little tale - initially <span class="mr-2 text-[#d963dd]">Chris</span>was able to do it all by himself but eventually he assigned this <strong>responsibilitity</strong> to someone else.</p><p>And by the way, what is a responsibilitity? (ah, my sweet definitions!)</p><p>Possibly the simplest one is:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>An ability to respond to a call.</p></div></div></div><p>So someone, who was assigned to this role, should be able to respond when someone else calls him to get the beef grilled.</p><p><span class="mr-2 text-[#2c74c9]">Ben</span>could sit there all day long and do nothing <strong>until</strong> get got called to perform his role.</p><p>He then took the raw beef and <strong>transformed</strong> it into grilled burger.</p><p>Of course, he needed to use some external tools like oven, frying pan, etc. but that&#x27;s a different tale, dear Reader.</p><p>The main point is that he was doing some kind of processing, when he was called to do so.</p><p>That&#x27;s why he started his job <strong>only</strong> when he received a message from <span class="mr-2 text-[#d963dd]">Chris</span>.</p><p>Same goes for completing turning a raw beef into a grilled burger - he send a new message.</p><p>Transformations and message passing are two sides of the same coin.</p><p>Without message passing, transformations are useless (no one uses them).</p><p>Without transformations, message passing is vain effort (nothing is produced).</p><h3 id="transforming-core-messaging-shell"><a href="#transforming-core-messaging-shell" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Transforming Core, Messaging Shell</h3><p>Imagine that someone had a crazy idea to split grilling beef into two parts:</p><ul><li>one part is responsible for flipping the beef</li><li>the other part is responsible for second flipping</li></ul><p>Let&#x27;s assume there are some rationale behind that.</p><p>As we saw in our little tale, each of the collaborators had his own burger preparation station.</p><p>Let&#x27;s say it&#x27;s same for this idea.</p><p>What it means is that each of those functions need to be coordinated to get the final job done - getting a grilled burger.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-objects-transformations-separated.png" class="max-h-[20rem]"/></div><div class="italic mx-24">Preparing a beef</div></div><p>The core transformations could be represented by functions:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">GrillOneSideOfBeef</span> <span class="token operator">=</span> RawBeef <span class="token operator">-&gt;</span> OneSideGrilledBeef
</span><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">GrillSecondSideOfBeef</span> <span class="token operator">=</span> OneSideGrilledBeef <span class="token operator">-&gt;</span> GrilledBurger
</span></code></pre></div></div><p>Without collaborating roles, the partial product - grilled burger - cannot be achieved.</p><p>They would need to communicate with each other, exchange information about their job and information about results of their processing (not processing results but <strong>information</strong> about them).</p><p>Those two parties would need to excel their core functions on a call, so core transformations could be &quot;packaged&quot; into:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">GrillOneSideOfBeef</span> <span class="token operator">=</span> 
</span><span class="code-line">    Message <span class="token operator">-&gt;</span> RawBeef <span class="token operator">-&gt;</span> <span class="token punctuation">(</span>OneSideGrilledBeef<span class="token punctuation">,</span> Message<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">GrillSecondSideOfBeef</span> <span class="token operator">=</span>
</span><span class="code-line">    Message <span class="token operator">-&gt;</span> OneSideGrilledBeef <span class="token operator">-&gt;</span> <span class="token punctuation">(</span>GrilledBurger<span class="token punctuation">,</span> Message<span class="token punctuation">)</span>
</span></code></pre></div></div><p>If one looks closely, it starts with <em>a message</em> and ends with <em>an another message</em>.</p><p>Inside there&#x27;s a <em>processing</em>, a <em>transformation</em>, that takes <em>values</em> and produces <em>a new value/new values</em>.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-objects-transformations-messages.png" class="max-h-[20rem]"/></div><div class="italic mx-24">Transforming Core, Messaging Shell</div></div><p>How does it relate to &quot;object-orienation&quot; that all of us hear here and there?</p><h3 id="message-passing-on-the-outside-functional-in-the-inside"><a href="#message-passing-on-the-outside-functional-in-the-inside" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Message-passing on the outside, functional in the inside</h3><p>When I think about canonical resource for &quot;object-oriented design&quot;, I think about one of the best books on that topic I know - <a href="https://www.amazon.com/Growing-Object-Oriented-Software-Guided-Tests/dp/0321503627">GOOS</a>.</p><p>In the section &quot;Different Levels of Language&quot;, the authors wrote:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>As well as distinguishing between <strong>value</strong> and <strong>object types</strong>, we find that we tend towards different programming styles at different levels in the code. Loosely speaking, we <strong>use</strong> the <strong>message-passing</strong> style we’ve just described <strong>between objects</strong>, but we tend to <strong>use</strong> a more <strong>functional style</strong> within <strong>an object</strong>, building up <strong>behavior from methods and values that have no side effects</strong>.</p></div></div></div><p>&quot;What a discovery&quot;, one might say.</p><p>That has profound effects on one&#x27;s thinking, though.</p><p>Even though your language might have a strong concept of a &quot;class&quot; but mentally you should think in two categories: transformations (functions that process values) and messaging (collaborating parties).</p><p>The ambiguity of objects gives as false impression that they are the most important part of the paradigm, whereas they are just value-transforming, collaborating messengers.</p><p>As Sandi Metz <a href="https://www.sandimetz.com">once stated</a>:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>You don&#x27;t send messages because you have objects, you have objects because you send messages.</p></div></div></div><p>At least from the outside, that&#x27;s true - as this is something we shall only see, as they should take care of their &quot;job security&quot;, by hiding the way they do their job.</p><p>But from inside, they are masters of processing - where values, transformations and becoming level (if you know what I am talking about, please check <a href="https://talesfrom.dev/blog/modeling-maturity-levels">Modeling Maturity Levels</a>) are really important.</p><h3 id="from-objects-to-actors"><a href="#from-objects-to-actors" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>From objects to actors</h3><p>If it&#x27;s about message passing, communication and collaboration - what is then an object?</p><p>Is it an instance of a class that is able to respond to a call?</p><p>Is it a web service that is able to respond to a request?</p><p>Is it an event handler that is able to respond to an event?</p><p>That&#x27;s what comes with focusing on messaging - one is able to leverage collaboration between parties, and not focus only on &quot;collaborators in the small scale&quot; (e.g. objects in C# or Java).</p><p>And turns out there&#x27;s a programming model that takes messaging quite seriously - it is your beloved <a href="https://en.wikipedia.org/wiki/Actor_model">Actor Model</a>.</p><p>Somehow when we think of actors - messaging and collaboration is a natural way of reasoning - but when we think of objects - we tend to focus on structures, properties and inheritance (yes, I know I might be exaggerating here).</p><p>When a language, that one is thinking in, has a strong concept of a <code>class</code>, &quot;an obejct&quot; mistakenly can be understood as something with &quot;is-a&quot;, &quot;has-a&quot; attributes (which strongly manifests &quot;being&quot; level - you can find more in <a href="https://talesfrom.dev/blog/modeling-maturity-levels">Modeling Maturity Levels</a>, dear Reader).</p><p>Actors are natural collaborators, social creatures by design - somehow we forgot same aspects when it comes to objects. (and of course - I totally neglected one of the biggest advantages of actors, namely their superpowers when it comes to concurrency - but this will come, some time later)</p><p>I don&#x27;t remember when I read it, but it&#x27;s a quite nice summary of such sad dichotomy:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Every obejct wants to be an actor but eventually becomes a table.</p></div></div></div><p>And what about functional programming?</p><p>It&#x27;s all about transformations, right?</p><p>Even though it&#x27;s all about functions, transforming values into another - at some level, one will encounter the need to delegate the further processing to others - whether they are web services, serveless functions or database stored procedures.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Transformations and message passing are two sides of the same coin.</p></div></div></div><p>Same goes for collaborating parties - when one looks from a specific perspective, it all starts forming a processing function, e.g. that is able to transform hunger into magical and satisfying experience.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-objects-transformation-in-large.png" class="max-h-[20rem]"/></div><div class="italic mx-24">It&#x27;s all about transformations and message-passing</div></div><p>And still we might be able to look inside and find a stream of messages, working as facts, happening throughout the large-scale transformation:</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-objects-events-messages.png" class="max-h-[20rem]"/></div><div class="italic mx-24">Messages as facts (different color outline means different role)</div></div><h3 id="pass-values-invite-collaborators"><a href="#pass-values-invite-collaborators" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Pass values, invite collaborators</h3><p>I firmly believe that the language we use shapes the way we think (thus see the world around) - in small scale and in large scale.</p><p>This tiny tale I brought to you, dear Reader, is a metaphor - and as metaphors have in their nature - they are incomplete (if they were complete, we would be talking about a reality or something close to a reality).</p><p>I am conscious it does not cover all the aspects, it has holes/gaps and is created with general simplification - but it is just <strong>a model</strong>.</p><p>A model of thinking.</p><p>Treat your objects as units of behavior, capable of processing and transforming values (often represtend by objects!) - and you understand only half of the truth.</p><p>Treat your objects as collaborating messengers, capable of exchanging information (often represented by objects!) - and you understand only half of the truth.</p><p>Next time, dear Reader, consider various scenarios and levels - when you need to make two parties collaborate and when you need &quot;just&quot; transform something into something else.</p><p>Some time you might transform <code>PendingDocument</code> into <code>ApprovedDocument</code>, and sometimes it will be just turning <code>RawBeef</code> into <code>GrilledBurger</code>.</p><p>Then, the question might be - what roles need to collaborate to get the job done? (you might be interested in <a href="https://talesfrom.dev/blog/i-interface">I, interface</a> and in <a href="https://talesfrom.dev/blog/the-ambiguity-of-interfaces">The ambiguity of interfaces</a> for more about roles)</p><p>Objects, web services, event processors, actors - from a certain angle and level, they are all the same.</p>]]></content:encoded>
    <pubDate>Tue, 12 Nov 2024 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>model</category><category>modeling</category><category>mental models</category><category>representations</category><category>knowledge working</category><category>ambiguity</category><category>misconceptions</category><category>coding</category><category>abstractions</category><category>language</category><category>language patterns</category><category>object-oriented design</category><category>messaging</category><category>functional design</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/representing-knowledge-what-how-and-why</guid>
    <title>Representing knowledge: what, how and why</title>
    <link>https://talesfrom.dev/blog/representing-knowledge-what-how-and-why</link>
    <description>What are the different levels of representing knowledge?</description>
    <content:encoded><![CDATA[<h3 id="a-problem"><a href="#a-problem" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>A problem</h3><p>Imagine that we work in a software system which deals with appliances.</p><p>There are various types of appliances, each with its own set of properties and behaviors.</p><p>One of the most interesting attributes of an appliance is its connectivity with other appliances.</p><p>Let&#x27;s assume it was already modeled and works perfectly.</p><p>But now, things changed (did they or it&#x27;s just our understanding of those &quot;things&quot;?).</p><p>Turns out that some of the applicances include other appliances - making them &quot;a container&quot;.</p><p>How to model that?</p><h3 id="a-collaborative-modeling-session"><a href="#a-collaborative-modeling-session" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>A collaborative modeling session</h3><p>Imagine we gathered the entire team, including the domain experts, to discuss this, learn together and solve it together.</p><p>That&#x27;s what real teams do, right? (you might be interested in reading about <a href="https://talesfrom.dev/blog/the-ambiguity-of-team-work">The ambiguity of team work</a>).</p><p>After some cycles, we decided to model it in a really easy way so that as we undergo the real usage, from which we will learn from, then we shall evolve it.</p><p>The rule was pretty easy to understand: an appliance is a container if it is connected to any appliance of a type of &quot;TYP-990&quot; or &quot;TYP-P0-1&quot;.</p><p>&quot;Container-ism&quot; was immediately used in one of the parts of the system to make a decision about a specific way of showing the attribute of &quot;being&quot; a container.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">if</span><span class="token punctuation">(</span>appliance<span class="token punctuation">.</span>Connections<span class="token punctuation">.</span><span class="token function">Any</span><span class="token punctuation">(</span>c <span class="token operator">=&gt;</span> 
</span><span class="code-line">    c<span class="token punctuation">.</span>ConnectedAppliance<span class="token punctuation">.</span>Type <span class="token operator">==</span> <span class="token string">&quot;TYP-990&quot;</span> <span class="token operator">||</span>
</span><span class="code-line">    c<span class="token punctuation">.</span>ConnectedAppliance<span class="token punctuation">.</span>Type <span class="token operator">==</span> <span class="token string">&quot;TYP-P0-1&quot;</span>
</span><span class="code-line"><span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// ...some important consequences</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>As all agreed, it was a good start. The rule was directly translated into code so everyone understood where did it come from.</p><p>Non-IT experts, who were present, were happy to see how their knowledge was directly used in the system - they were able to follow it too!</p><p>Amazing, isn&#x27;t it?</p><p>Thanks to <code>Connections</code> public property, we were able to easily check if an appliance is a container.</p><p>It is used in other places of the system so it was a natural candidate to utilize it further.</p><p>Someone suggested we could put some comment there to explain we deal with a container under those circumstances.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">if</span><span class="token punctuation">(</span>appliance<span class="token punctuation">.</span>Connections<span class="token punctuation">.</span><span class="token function">Any</span><span class="token punctuation">(</span>c <span class="token operator">=&gt;</span> 
</span><span class="code-line">    c<span class="token punctuation">.</span>ConnectedAppliance<span class="token punctuation">.</span>Type <span class="token operator">==</span> <span class="token string">&quot;TYP-990&quot;</span> <span class="token operator">||</span>
</span><span class="code-line">    c<span class="token punctuation">.</span>ConnectedAppliance<span class="token punctuation">.</span>Type <span class="token operator">==</span> <span class="token string">&quot;TYP-P0-1&quot;</span>
</span><span class="code-line"><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// a container</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// ...some important consequences</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Even better, now someone looking at this piece of code will immediately grasp the underlying concept.</p><h3 id="changes-changes-never-change"><a href="#changes-changes-never-change" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Changes, changes never change.</h3><p>As we were working on the system, we discovered that the rule was not that simple.</p><p>It turned out that there might be appliances that do not have any connections at all but still are containers.</p><p>Both type and size of the appliance were important pieces of information to determine if it is a container, provided that it has no connections.</p><p>Unfortunately, there was no &quot;size&quot; property on the <code>Appliance</code> class, so we needed to use dimensions to determine it.</p><p>We rushed to the code to make proper changes and express the new rule.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">if</span><span class="token punctuation">(</span>
</span><span class="code-line">appliance<span class="token punctuation">.</span>Connections<span class="token punctuation">.</span><span class="token function">Any</span><span class="token punctuation">(</span>c <span class="token operator">=&gt;</span> 
</span><span class="code-line">    c<span class="token punctuation">.</span>ConnectedAppliance<span class="token punctuation">.</span>Type <span class="token operator">==</span> <span class="token string">&quot;TYP-990&quot;</span> <span class="token operator">||</span>
</span><span class="code-line">    c<span class="token punctuation">.</span>ConnectedAppliance<span class="token punctuation">.</span>Type <span class="token operator">==</span> <span class="token string">&quot;TYP-P0-1&quot;</span>
</span><span class="code-line"><span class="token punctuation">)</span> <span class="token operator">||</span>
</span><span class="code-line"><span class="token punctuation">(</span><span class="token operator">!</span>appliance<span class="token punctuation">.</span>Connections<span class="token punctuation">.</span><span class="token function">Any</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token punctuation">(</span>appliance<span class="token punctuation">.</span>Dimensions<span class="token punctuation">.</span>Width <span class="token operator">&gt;</span> <span class="token number">100</span> <span class="token operator">&amp;&amp;</span> appliance<span class="token punctuation">.</span>Dimensions<span class="token punctuation">.</span>Height <span class="token operator">&gt;</span> <span class="token number">100</span> <span class="token operator">&amp;&amp;</span> appliance<span class="token punctuation">.</span>Dimensions<span class="token punctuation">.</span>Depth <span class="token operator">&gt;</span> <span class="token number">100</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">||</span>
</span><span class="code-line"><span class="token punctuation">(</span><span class="token operator">!</span>appliance<span class="token punctuation">.</span>Connections<span class="token punctuation">.</span><span class="token function">Any</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token punctuation">(</span>appliance<span class="token punctuation">.</span>Type <span class="token operator">==</span> <span class="token string">&quot;TYP-100&quot;</span> <span class="token operator">||</span> appliance<span class="token punctuation">.</span>Type <span class="token operator">==</span> <span class="token string">&quot;TYP-101&quot;</span> <span class="token operator">||</span> appliance<span class="token punctuation">.</span>Type <span class="token operator">==</span> <span class="token string">&quot;TYP-X0-1&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">)</span> <span class="token comment">// a container</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// ...some important consequences</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Well, it got a bit ugly. But at least the comment is there to explain what is going on.</p><h3 id="all-those-pesky-old-systems"><a href="#all-those-pesky-old-systems" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>All those pesky old systems!</h3><p>There was additional problem - as we are integrating with an older system of ours, we discovered that those rules might apply and a given applicance might not be a container.</p><p>Fortunately for us, all appliances having a prefix <code>M999-</code> in its name determine that it comes from the old system - then for sure such appliance can&#x27;t be a container and we should treat it as a regular one.</p><p>We needed to add this information to our rule.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">if</span><span class="token punctuation">(</span>
</span><span class="code-line">    <span class="token punctuation">(</span>appliance<span class="token punctuation">.</span>Connections<span class="token punctuation">.</span><span class="token function">Any</span><span class="token punctuation">(</span>c <span class="token operator">=&gt;</span> 
</span><span class="code-line">        c<span class="token punctuation">.</span>ConnectedAppliance<span class="token punctuation">.</span>Type <span class="token operator">==</span> <span class="token string">&quot;TYP-990&quot;</span> <span class="token operator">||</span>
</span><span class="code-line">        c<span class="token punctuation">.</span>ConnectedAppliance<span class="token punctuation">.</span>Type <span class="token operator">==</span> <span class="token string">&quot;TYP-P0-1&quot;</span>
</span><span class="code-line">    <span class="token punctuation">)</span> <span class="token operator">||</span>
</span><span class="code-line">    <span class="token punctuation">(</span><span class="token operator">!</span>appliance<span class="token punctuation">.</span>Connections<span class="token punctuation">.</span><span class="token function">Any</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token punctuation">(</span>appliance<span class="token punctuation">.</span>Dimensions<span class="token punctuation">.</span>Width <span class="token operator">&gt;</span> <span class="token number">100</span> <span class="token operator">&amp;&amp;</span> appliance<span class="token punctuation">.</span>Dimensions<span class="token punctuation">.</span>Height <span class="token operator">&gt;</span> <span class="token number">100</span> <span class="token operator">&amp;&amp;</span> appliance<span class="token punctuation">.</span>Dimensions<span class="token punctuation">.</span>Depth <span class="token operator">&gt;</span> <span class="token number">100</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">||</span>
</span><span class="code-line">    <span class="token punctuation">(</span><span class="token operator">!</span>appliance<span class="token punctuation">.</span>Connections<span class="token punctuation">.</span><span class="token function">Any</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token punctuation">(</span>appliance<span class="token punctuation">.</span>Type <span class="token operator">==</span> <span class="token string">&quot;TYP-100&quot;</span> <span class="token operator">||</span> appliance<span class="token punctuation">.</span>Type <span class="token operator">==</span> <span class="token string">&quot;TYP-101&quot;</span> <span class="token operator">||</span> appliance<span class="token punctuation">.</span>Type <span class="token operator">==</span> <span class="token string">&quot;TYP-X0-1&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span>
</span><span class="code-line">    <span class="token punctuation">(</span><span class="token operator">!</span>appliance<span class="token punctuation">.</span>Name<span class="token punctuation">.</span><span class="token function">Contains</span><span class="token punctuation">(</span><span class="token string">&quot;M999-&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">)</span> <span class="token comment">// a container</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// ...some important consequences</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Well, our tiny rule evolved into something like...This.</p><h3 id="when-a-senior-speaks-up"><a href="#when-a-senior-speaks-up" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>When a senior speaks up</h3><p>It was decided - this piece of code gets messy and hard to understand - even though we had our little comment (which saved our asses many times!)</p><p>One of the seniors suggested that we should extract this rule to a separate method.</p><p>Fortunately to us, C# allows expressing such rule as a property, as it was not requiring any other information to determine &quot;container-ism&quot;.</p><p>Couple of keyboard shortcuts and we had it.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token comment">// somewhere in `Appliance` class</span>
</span><span class="code-line"><span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">bool</span></span> IsContainer <span class="token operator">=&gt;</span> 
</span><span class="code-line">    <span class="token punctuation">(</span>appliance<span class="token punctuation">.</span>Connections<span class="token punctuation">.</span><span class="token function">Any</span><span class="token punctuation">(</span>c <span class="token operator">=&gt;</span> 
</span><span class="code-line">        c<span class="token punctuation">.</span>ConnectedAppliance<span class="token punctuation">.</span>Type <span class="token operator">==</span> <span class="token string">&quot;TYP-990&quot;</span> <span class="token operator">||</span>
</span><span class="code-line">        c<span class="token punctuation">.</span>ConnectedAppliance<span class="token punctuation">.</span>Type <span class="token operator">==</span> <span class="token string">&quot;TYP-P0-1&quot;</span>
</span><span class="code-line">    <span class="token punctuation">)</span> <span class="token operator">||</span>
</span><span class="code-line">    <span class="token punctuation">(</span><span class="token operator">!</span>appliance<span class="token punctuation">.</span>Connections<span class="token punctuation">.</span><span class="token function">Any</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token punctuation">(</span>appliance<span class="token punctuation">.</span>Dimensions<span class="token punctuation">.</span>Width <span class="token operator">&gt;</span> <span class="token number">100</span> <span class="token operator">&amp;&amp;</span> appliance<span class="token punctuation">.</span>Dimensions<span class="token punctuation">.</span>Height <span class="token operator">&gt;</span> <span class="token number">100</span> <span class="token operator">&amp;&amp;</span> appliance<span class="token punctuation">.</span>Dimensions<span class="token punctuation">.</span>Depth <span class="token operator">&gt;</span> <span class="token number">100</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">||</span>
</span><span class="code-line">    <span class="token punctuation">(</span><span class="token operator">!</span>appliance<span class="token punctuation">.</span>Connections<span class="token punctuation">.</span><span class="token function">Any</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token punctuation">(</span>appliance<span class="token punctuation">.</span>Type <span class="token operator">==</span> <span class="token string">&quot;TYP-100&quot;</span> <span class="token operator">||</span> appliance<span class="token punctuation">.</span>Type <span class="token operator">==</span> <span class="token string">&quot;TYP-101&quot;</span> <span class="token operator">||</span> appliance<span class="token punctuation">.</span>Type <span class="token operator">==</span> <span class="token string">&quot;TYP-X0-1&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span>
</span><span class="code-line">    <span class="token punctuation">(</span><span class="token operator">!</span>appliance<span class="token punctuation">.</span>Name<span class="token punctuation">.</span><span class="token function">Contains</span><span class="token punctuation">(</span><span class="token string">&quot;M999-&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token comment">// and this is how our well known if statement looks like now</span>
</span><span class="code-line"><span class="token keyword">if</span><span class="token punctuation">(</span>appliance<span class="token punctuation">.</span>IsContainer<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// ...some important consequences</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Glory!</p><p>Victory!</p><p>The code started serving its capabilities even better than before.</p><p>So readable, so understandable, easy to maintain!</p><h3 id="what-changes"><a href="#what-changes" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What, changes?</h3><p>As we all know, if something has changed before has a higher probability of changing again.</p><p>Same happened to our rule.</p><p>As with the older system, appliances imported from a partners&#x27; systems also have special rules for determining if an appliance is a container.</p><p>However, this time it wasn&#x27;t that easy.</p><p>It was <code>Name</code> property that was a target for checking, but each partner had its own unique name that got embedded as a prefix.</p><p>A suggestion from domain experts was to firstly check if the appliance is from a partner system and then apply the rule.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">if</span><span class="token punctuation">(</span>partners<span class="token punctuation">.</span><span class="token function">Any</span><span class="token punctuation">(</span>p <span class="token operator">=&gt;</span> <span class="token operator">!</span>appliance<span class="token punctuation">.</span>Name<span class="token punctuation">.</span><span class="token function">Contains</span><span class="token punctuation">(</span>p<span class="token punctuation">.</span>Name<span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token operator">&amp;&amp;</span> appliance<span class="token punctuation">.</span>IsContainer<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// ...some important consequences</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>It wasn&#x27;t that readable anymore. Maybe another structure of the code would be better?</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">if</span><span class="token punctuation">(</span>appliance<span class="token punctuation">.</span><span class="token function">IsContainer</span><span class="token punctuation">(</span>partners<span class="token punctuation">.</span><span class="token function">Select</span><span class="token punctuation">(</span>p <span class="token operator">=&gt;</span> p<span class="token punctuation">.</span>Name<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// ...some important consequences</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>It looks a bit weird that we need to pass the names of the partners to the <code>IsContainer</code> method but it does the job.</p><p>We decided to leave it as it is, for now.</p><p>Of course, we did not forget to update the <code>IsContainer</code> property, but let&#x27;s stop here, dear Reader.</p><p>Time to reflect on what the hell just happened.</p><h3 id="code"><a href="#code" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Code?</h3><p>As you probably know, dear Reader, this code is just a toy example and no real software systems have such code in them.</p><p>Everything is readable and straightforward, right?</p><p>I hope you got my cynical tone.</p><p>&quot;Damian, do you think I am that naive? No one writes code like this!&quot;, one might state.</p><p>Nothing is wrong with writing such code, in the first place.</p><p>&quot;Every complex system that works is evolved from a simple system that worked&quot;, as John Gall stated once (I believe it was in the <a href="https://www.amazon.com/Systems-Bible-Beginners-Guide-Large/dp/0961825170">&quot;The Systems Bible&quot;</a>).</p><p>Same with our &quot;code&quot;, right?</p><p>It was a subject of a natural evolution as we learned along the journey.</p><p>As you might remember, dear Reader, we typically deal with <a href="https://talesfrom.dev/blog/the-ambiguity-of-code">The ambiguity of code</a> - and it&#x27;s about something more profound.</p><p>The knowledge.</p><p>The knowledge and its application (you might be interested in <a href="https://talesfrom.dev/blog/the-ambiguity-of-application">The ambiguity of application</a>).</p><p>As we saw during this tiny tale, it all started from a simple rule on how to determine if an appliance is a container.</p><p>Then it grew, grew and grew.</p><p>It was a natural process of learning and applying the knowledge - but the knowledge was actually leaking here, leaking there.</p><p>Putting the &quot;a container&quot; comment was a small exaggeration, but I believe one can imagine that this might have actually happened - as it was easy, right? (and we already know that <a href="https://talesfrom.dev/blog/simple-isnt-easy">Simple isn&#x27;t easy</a>).</p><h3 id="knowledge"><a href="#knowledge" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Knowledge?</h3><p>During the entire process, the team learned about various ways of determining &quot;container-ism&quot; - expressing an abstract idea, a concept of something being a container.</p><p>Some of those ways were related to other systems, some to the domain itself.</p><p>If one recaps, we started with <strong>how</strong> to determine if an appliance is a container.</p><p>By initially by adding a comment - &quot;a container&quot; - we represented <strong>what</strong> it is all about.</p><p>Then this <strong>what</strong> became a legitimate programming construct - a property.</p><p>And even though it was eventually expressed in the code by handy <code>IsContainer</code> property (which can be naturally translated to a method/a function/a field, in other languages than C#), we didn&#x27;t capture details on <strong>why</strong> things are the way they are.</p><p>Nothing was mentioned about different reasons for determining &quot;container-ism&quot; - and that might hurt us in the future.</p><p>It is not &quot;bad&quot; to start with implementation details (<strong>how</strong>), as it is a natural way of learning as the understanding emerges in front of our eyes.</p><p>But we shouldn&#x27;t stop there.</p><p>As we got to the point when we know <strong>what</strong> an abstract idea or a concept we are supposed to represent, let&#x27;s go for it.</p><p>If suddenly we discover that this <strong>what</strong> has different <strong>why</strong>s behind it&#x27;s <strong>how</strong>s, we should capture meaningful and sometimes subtle details, as they might be crucial for building the correct understanding.</p><h3 id="what-how-and-why"><a href="#what-how-and-why" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What, how and why</h3><p>We might not yet know <strong>how</strong> to represent something but we know <strong>what</strong> we want to represent - as in this case, the &quot;container-ism&quot;.</p><p>I once heard a term &quot;programming with wishful thinking&quot;, so focusing on capturing this <strong>what</strong> - as we don&#x27;t need to know <strong>how</strong> it will be provided.</p><p>Naturally, we will step into <strong>how</strong>&#x27;s territory - an implementation - but at some level of thinking it&#x27;s just a secondary concern.</p><p>Why?</p><p>By articulating, so specifying the <strong>what</strong> we want to represent, we &quot;drive&quot; this <strong>how</strong>, using the inner knowledge we just built.</p><p>&quot;Drive&quot;? It might sound familiar to you, dear Reader, as I deliberately refer to Test-Driven Development (btw. it&#x27;s not about &quot;tests&quot;, if you&#x27;re interested, check <a href="https://talesfrom.dev/blog/the-ambiguity-of-tdd">The ambiguity of TDD</a>).</p><p>Of course, eventually, we might encounter dragons and behemoths, so it might be a good idea to capture the <strong>why</strong> - probably by placing comments.</p><p>Comments have their time and place, so don&#x27;t be afraid to use them, especially when capturing <strong>why</strong>!</p><p>And this <strong>why</strong> might be anything: a description, a simple explanation, a reference to an external document or a github issue.</p><h3 id="start-with-how-too"><a href="#start-with-how-too" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Start with <strong>how</strong> too!</h3><p>It all sounds easy - start with <strong>what</strong>, follow with <strong>how</strong>, and if needed, capture <strong>why</strong>.</p><p>But is it really that easy?</p><p>There are many things that <a href="https://x.com/alexbunardzic">Alex Bunardzic</a> mentioned and that sticked with me. One of them is this little and big gem:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>It&#x27;s not possible to understand the problem before we try the solution.</p></div></div></div><p>This might mean that to get to the <strong>what</strong>, we need to start with <strong>how</strong>.</p><p>(please note dear Reader that there&#x27;s no &quot;always&quot;!)</p><p>As I understand those wise words, it&#x27;s about the process of learning - as we jump into the arena of solving problems, we learn about the problem itself.</p><p>And as we saw during this tiny tale, it&#x27;s all fine to grab all those <strong>how</strong>s and let <strong>what</strong>s to emerge.</p><p><strong>How</strong>s should be transformed into <strong>what</strong>s.</p><h3 id="language-abstractions-and-modeling"><a href="#language-abstractions-and-modeling" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Language, abstractions and modeling</h3><p>All of this sounds like a pixie dust, isn&#x27;t it?</p><p>Should you always start with <strong>what</strong>? Cynically, I would respond: yes my acolyte, you should.</p><p>I hope you know it already, dear Reader, that I am afraid of dangerous quantifiers like &quot;always&quot;, &quot;never&quot; and so on.</p><p>I don&#x27;t belive there&#x27;s a silver bullet, &quot;a best practice&quot; or &quot;a golden standard&quot; to achieve the Holy Grail of modeling (whatever actually it is).</p><p>Still, it&#x27;s tempting to say that starting with specifying <strong>what</strong> is a good idea - as it involves working with <a href="https://talesfrom.dev/blog/language-of-the-problem">Language of the problem</a> and putting focus on the domain.</p><p>Every move incurrs <a href="https://talesfrom.dev/blog/the-cost-of-modeling">The cost of modeling</a> and it&#x27;s up to us to decide what makes sense, <strong>now</strong>.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Start with <strong>what</strong>, continuously follow with <strong>how</strong>, and if needed, capture <strong>why</strong>.</p></div></div></div><p>This still might sound &quot;magical&quot; and one might reason on <strong>how</strong> to apply this knowledge (pun intended) in the real world problems - and it&#x27;s a good question.</p><p>I believe that awareness is all of what we have so being aware of &quot;what, how and why&quot; might be a nice opener.</p><p>Next time dear Reader, when dealing with a problem and trying to find a solution, consider asking yourself those questions:</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>What an abstract idea or a concept do I try to represent?</p>
<p>How can it be represented?</p>
<p>Why is it represented in this particular way?</p>
<p>Why are there various ways of representing it?</p></div></div></div><p>And wait for more interesting questions to emerge.</p><p>Happy modeling!</p>]]></content:encoded>
    <pubDate>Sun, 29 Sep 2024 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>model</category><category>modeling</category><category>development process</category><category>mental models</category><category>representations</category><category>knowledge working</category><category>ambiguity</category><category>misconceptions</category><category>coding</category><category>abstractions</category><category>language</category><category>language patterns</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/the-ambiguity-of-team-work</guid>
    <title>The ambiguity of team work</title>
    <link>https://talesfrom.dev/blog/the-ambiguity-of-team-work</link>
    <description>Heads or hands?</description>
    <content:encoded><![CDATA[<h3 id="we-had-one-job"><a href="#we-had-one-job" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>We had one job</h3><p>Imagine there is a group of individuals, building a product.</p><p>Not a &quot;legacy&quot;, not a &quot;greenfield&quot;.</p><p>Something in between. (what does it mean legacy, anyway?)</p><p>They follow agile practices - stand ups, retros, grooming sessions, planning sessions, and so on.</p><p>You can feel the scrum in the air.</p><p>Cross-functional team, they say - three software engineers, a QA engineer, an architect and a product owner.</p><p>They have a backlog, a sprint goal, and a definition of done.</p><p>They have a product vision, a roadmap, and a strategy.</p><p>Everything.</p><h3 id="a-new-feature-wildly-appears"><a href="#a-new-feature-wildly-appears" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>A new feature wildly appears!</h3><p>One day, the product owner comes to the team with a new feature request.</p><p>It was in the 5 year plan, but it was not supposed to be developed now.</p><p>The team is excited, they start to discuss the feature.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>We would need to touch Users Service, BCS and DLS. I will prepare new sketches.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-blue-400">Jim, a software engineer:</span><span>DLS?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-yellow-300">Alex, an architect:</span><span>You know, Document Lifecycle Service. We established it month ago. Wasn&#x27;t you Jim who made it according to my specs?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-blue-400">Jim, a software engineer:</span><span>Nah, it was Pete, right Pete?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold text-green-600">Pete:</span><span> Yes, it was me. I think I can handle that one pretty easily.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-purple-400">Bob, a software engineer:</span><span>I will take care of BCS. It might be tough but I kinda like that beast.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-blue-400">Jim, a software engineer:</span><span>Wait, BCS?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-purple-400">Bob, a software engineer</span> and <span class="italic font-bold mr-2 text-yellow-300">Alex, an architect</span>: <span>Background Checking Service.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-blue-400">Jim, a software engineer:</span><span>Yeah, now I understand, thanks.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-orange-400">Mike, a QA Engineer:</span><span>Any front-end work guys? I have some remaining UI tests to do, so I could wait with them until you finish that new UI.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2 text-red-300">Paul, a product owner:</span><span>Cool, let&#x27;s just start. We need to get some progress soon!</span></div></span></div><p>And they started.</p><p><span class="italic font-bold text-green-600">Pete</span> took DLS, <span class="italic font-bold text-purple-400">Bob</span> took BCS, <span class="italic font-bold text-blue-400">Jim</span> took the new UI and Users Service, and <span class="italic font-bold text-orange-400">Mike</span> started to prepare the UI tests, according to specs prepared by <span class="italic font-bold text-yellow-300">Alex</span> and <span class="italic font-bold text-red-300">Paul</span>.</p><p>Everyone got busy pretty quickly.</p><p>If we joined their standups, oh boy, we would hear buzzing!</p><h3 id="buzzing-reviewing-andwaiting"><a href="#buzzing-reviewing-andwaiting" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Buzzing, reviewing and...Waiting?</h3><p>As the sprint progressed, PRs started emerge and waited to get reviewed.</p><p><span class="italic font-bold text-green-600">Pete</span> finished part of the DLS but was waiting for <span class="italic font-bold text-blue-400">Jim</span> to finish the UI, so he could integrate his changes.</p><p><span class="italic font-bold text-purple-400">Bob</span> pretty quickly started drowning with BCS and eventually got a call to review <span class="italic font-bold text-blue-400">Jim</span>&#x27;s PR in Users Service, as <span class="italic font-bold text-blue-400">Jim</span> wasn&#x27;t sure about the changes he made.</p><p>Turned out that there was a part of BCS that wasn&#x27;t according to the diagrams prepared by <span class="italic font-bold text-yellow-300">Alex</span> which needed clarification between <span class="italic font-bold text-purple-400">Bob</span> and <span class="italic font-bold text-yellow-300">Alex</span>.</p><p>UI was almost ready but <span class="italic font-bold text-green-600">Pete</span> was still waiting for <span class="italic font-bold text-blue-400">Jim</span> to finish the last part of the UI, so he could integrate his changes.</p><p><span class="italic font-bold text-orange-400">Mike</span> prepared the UI test cases and was waiting for the UI to be ready.</p><p><span class="italic font-bold text-red-300">Paul</span> was waiting for the feature to be ready, so he could show it to the stakeholders.</p><p>After clarifyinig the BCS part, <span class="italic font-bold text-purple-400">Bob</span> could revisit some design issues he found during his &quot;coding&quot; session (coding? you might be interested in <a href="https://talesfrom.dev/blog/the-ambiguity-of-code">The ambiguity of code</a>).</p><p>PR in Users Service was almost forgotten, as <span class="italic font-bold text-blue-400">Jim</span> was still struggling with the UI but turned out that there a technical debt inside, and it seemed a good moment to clean it up.</p><p><span class="italic font-bold text-red-300">Paul</span> wasn&#x27;t happy about it, especially that there was not much progress in the sprint.</p><p><span class="italic font-bold text-blue-400">Jim</span> was a bit hesitant about the UI, as he wasn&#x27;t sure if it was according to the specs prepared by <span class="italic font-bold text-yellow-300">Alex</span> and <span class="italic font-bold text-red-300">Paul</span>.</p><p>There was a path in the workflow that made UI pretty unusable so it required some re-thinking.</p><p>And then <span class="italic font-bold text-purple-400">Bob</span> got sick.</p><h3 id="bcs---anyone"><a href="#bcs---anyone" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>BCS - anyone?</h3><p><span class="italic font-bold text-purple-400">Bob</span> was sick, so <span class="italic font-bold text-green-600">Pete</span> was asked by <span class="italic font-bold text-yellow-300">Alex</span> to take care of BCS.</p><p><span class="italic font-bold text-green-600">Pete</span> resisted as he didn&#x27;t have DLS finished and still he was waiting for the UI to make proper integration.</p><p><span class="italic font-bold text-yellow-300">Alex</span> was a bit frustrated, as he didn&#x27;t expect that <span class="italic font-bold text-purple-400">Bob</span> would get sick.</p><p><span class="italic font-bold text-red-300">Paul</span> wanted to prioritize the UI, as it was the most important part of the feature.</p><p>And prioritize BCS as it was almost finished, according to <span class="italic font-bold text-purple-400">Bob</span>, before he got sick.</p><p><span class="italic font-bold text-red-300">Paul</span> and <span class="italic font-bold text-yellow-300">Alex</span> had a discussion about the priorities, and they decided that <span class="italic font-bold text-blue-400">Jim</span> should finish the UI first and <span class="italic font-bold text-green-600">Pete</span> should take care of BCS, as he is waiting for UI to be finished by <span class="italic font-bold text-blue-400">Jim</span>.</p><p><span class="italic font-bold text-orange-400">Mike</span> was still waiting but got asked to test BCS as soon as possible.</p><h3 id="wait-what-does-it-mean-not-according-to-the-specs"><a href="#wait-what-does-it-mean-not-according-to-the-specs" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Wait, what does it mean not according to the specs?&quot;</h3><p>Well, as BCS got finished, it turned out that there was a part of the service that was not according to the specs prepared by <span class="italic font-bold text-yellow-300">Alex</span>.</p><p><span class="italic font-bold text-green-600">Pete</span> was a bit surprised as he did everything according to what they agreed on at the beginning.</p><p><span class="italic font-bold text-red-300">Paul</span> got mad as he wanted to show the feature to the stakeholders and now it seems that BCS requires major rework as it does not work according to the specs.</p><p><span class="italic font-bold text-orange-400">Mike</span> was eager for testing but he eventually understood that his test cases are not valid anymore.</p><p>And UI design changed which required UI to be changed as well.</p><p>&quot;It will took 4 days to prepare new test cases&quot;, <span class="italic font-bold text-orange-400">Mike</span> said.</p><p><span class="italic font-bold text-red-300">Paul</span> decided to ask a principal software engineer, from another team, to help with the BCS.</p><p><span class="italic font-bold text-violet-700">Tim, a principal software engineer</span> immediately jumped into BCS, without asking much questions.</p><p>&quot;Alex told me everything I need to know&quot;, he said.</p><h3 id="the-pr"><a href="#the-pr" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>THE PR</h3><p><span class="italic font-bold text-violet-700">Tim</span> asked <span class="italic font-bold text-green-600">Pete</span> to review his PR, as he worked with BCS already.</p><p>231 files changed.</p><p>It took 3 full days of reviewing - during that time there was no movement in UI, in Users Service.</p><p>But there was a lot of discussions about SOLID, variable naming, programming styles, object orientation, and so on.</p><p><span class="italic font-bold text-violet-700">Tim</span> was a bit surprised as he thought that the PR was pretty straightforward.</p><p><span class="italic font-bold text-green-600">Pete</span> got a bit angry as he couldn&#x27;t finish DLS - he even had a crazy thought to jump into UI code and do fixes but he wasn&#x27;t skilled with Next.js or whatever meta or teta framework they had.</p><p>&quot;You are a senior dev, come one, you can do it&quot;, <span class="italic font-bold text-red-300">Paul</span> said.</p><p>Time was running and <span class="italic font-bold text-green-600">Pete</span> decided to put &quot;LGTM&quot; on the PR.</p><p>Finally, BCS got merged, woohoo!</p><p><span class="italic font-bold text-violet-700">Tim</span> got back to his team, as he was borrowed for a few days.</p><p>Thanks to this waiting time, <span class="italic font-bold text-orange-400">Mike</span> prepared some test scenarios for BCS and started testing.</p><p><span class="italic font-bold text-blue-400">Jim</span> continued the UI work, and <span class="italic font-bold text-green-600">Pete</span> still waited to finish DLS, so he started thinking about taking something next from the backlog.</p><h3 id="bcs---buggy-custom-software"><a href="#bcs---buggy-custom-software" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>BCS - Buggy Custom Software?</h3><p>Well, something wasn&#x27;t according to the latest specs by <span class="italic font-bold text-yellow-300">Alex</span>, as <span class="italic font-bold text-orange-400">Mike</span> reported after doing his QA part.</p><p>&quot;Seems like Tim misunderstood some things...&quot;, <span class="italic font-bold text-orange-400">Mike</span> mumbled.</p><p>&quot;You should fix it, Pete&quot;, <span class="italic font-bold text-red-300">Paul</span> said.</p><p>&quot;Guys, I finished the UI part so Pete can integrate DLS&quot;, <span class="italic font-bold text-blue-400">Jim</span> mentioned.</p><p>&quot;Well, it might take some days...&quot;, <span class="italic font-bold text-green-600">Pete</span> commented.</p><p>&quot;What?! I thought you are familiar with <a href="https://talesfrom.dev/blog/the-ambiguity-of-code">code</a> as you did a code review.&quot;, <span class="italic font-bold text-red-300">Paul</span> counter-commented.</p><h3 id="team-work"><a href="#team-work" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Team work&quot;</h3><p>Does it sound famililar, dear Reader?</p><p>All people were busy, all people were working.</p><p>Each day, they &quot;reported&quot; their progress.</p><p>Seemed that everyone was pretty productive.</p><p>PRs, reviews, discussions, meetings, coding, testing, designing.</p><p>But the feature was not ready.</p><p>Why so?</p><p>Could we name this group of individuals a &quot;team&quot;?</p><p>No doubt that each of the people progressed with their tasks.</p><p>This looked as a highly collaborative environment, wasn&#x27;t it?</p><h3 id="the-ambiguity-of-team-work"><a href="#the-ambiguity-of-team-work" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The ambiguity of team work</h3><p>It&#x27;s about heads, not hands.</p><p>It&#x27;s about understanding, not just doing.</p><p>As very smart people noticed already, <a href="https://blog.ploeh.dk/2018/09/17/typing-is-not-a-programming-bottleneck/">typing is not a programming bottleneck</a>.</p><p>With the advancement of technology as automated typists, like LLMs and friends, the impact of &quot;this problem&quot; decreased (a bit).</p><p>Similar to &quot;the system isn&#x27;t just a sum of it parts&quot;, the sum of the work done in isolation does not equal the work done in collaboration, when it comes to knowledge work</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-team-work.png" class="max-h-[60rem]"/></div><div class="italic mx-24">Superposition of isolated increments does not give the superposition of increments done in the collaborative way.</div></div><p>Crucial aspects is when this superposition happens - skilled and brilliant minds should work together and let the collective knowledge emerge during the collaborative time.</p><p>How often do we see PRs with more than 50 files, heck, 20 files, that just capture the snapshot of the context that someone created during the work in isolation?</p><p>There was the thought process which yielded understanding/knowledge, and eventually got represented &quot;in the code&quot; (what am I talking about? Please check <a href="https://talesfrom.dev/blog/the-ambiguity-of-code">The ambiguity of code</a> and <a href="https://talesfrom.dev/blog/the-ambiguity-of-application">The ambiguity of application</a>).</p><p>Syntactic checks, rambling about SOLID or something similar - LGTM is almost there.</p><p>Typically, we have abundance of code but scarcity of understanding.</p><p>Is it really true that we are able to build even the 1/10 of another person&#x27;s understanding by just reading the code, even if we get a &quot;clarifying call&quot;?</p><h3 id="heads-not-hands"><a href="#heads-not-hands" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Heads, not hands</h3><p>A single letter makes a huge difference here.</p><p>As we saw in this tiny tale, queues and waiting time were a &quot;subtle&quot; consequence that emerged from this style of product development.</p><p>Someone agrees upon something here, someone else changes the assumptions there - quickly things get out of sync.</p><p>Cross-functional teams might not mean over-specialization - the flow of the knowledge, between &quot;heads&quot;, contributes to the flow of the work (will it?).</p><p>&quot;Damian, are you nuts? Working like this all the time?&quot;, you might wonder, dear Reader.</p><p>I like to say that there are some dangerous words in the world, like &quot;always&quot;, &quot;never&quot;, &quot;everytime&quot;, &quot;all&quot; and so on.</p><p>I don&#x27;t believe it is possible to work like this all the time.</p><p>There are things that should be done in isolation but at least they could be discussed together.</p><p>I am not an expert to tell anyone what to work but I firmly believe that it greatly matters on the context in which each of us operates.</p><p>If you do a next level CRUD app when there is almost no complexity - does it make sense to sit together, always?</p><p>Maybe not.</p><p>What if we work on the core functionality that spans, within team&#x27;s ownership boundaries, across the whole system?</p><p>Wouldn&#x27;t it make sense to collaborate on it in real-time (virtually or on-site)?</p><p>How much knowledge might be lost if we decompose work on entire feature?</p><p>As we discussed some time ago, <a href="https://talesfrom.dev/blog/the-law-of-eventual-composition">The law of eventual composition</a> still applies and question is if one can compose &quot;knowledge gaps&quot;?</p><p>Integration problems never cease to exist (I used dangerous word, buckle up) but what if we could reduce them or even get rid of them by working together?</p><h3 id="overmind-the-head"><a href="#overmind-the-head" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Overmind, &quot;the head&quot;</h3><p>Of course I didn&#x27;t come up with those ideas and observations by myself.</p><p>I stand on the shoulders of giants, like <a href="https://en.wikipedia.org/wiki/Conway%27s_law">Conway&#x27;s Law</a>, <a href="https://en.wikipedia.org/wiki/The_Goal_(novel)">The Goal</a> and <a href="https://softwareteaming.com/">The Software Teaming</a>, and just want to share my thoughts and personal observations.</p><p>I read somewhere the following quote, it was something like: &quot;when two people are working together, in fact there are three people: the third &quot;person&quot; is the overmind&quot;.</p><p>This &quot;overmind&quot; is the collective knowledge that emerges during the collaboration.</p><p>Isolation does not give same kind of experience.</p><p>Even though we might be able to &quot;mimic&quot; the experience by working &quot;collaboratively&quot; with LLMs and friends, this &quot;overmind&quot; won&#x27;t happen to materialize itself, invisibly.</p><h3 id="overmind---overhead"><a href="#overmind---overhead" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Overmind - overhead?</h3><p>If you ask me, dear Reader, whether we should <strong>always</strong> pursue this kind of working - my answer is going to be simple: <a href="https://tenor.com/en-GB/view/michael-scott-am-ia-hero-hero-gif-27082688">Well, I can&#x27;t really say, but yes.</a></p><p>Hail to the King of Kings - the context.</p><p>One need to be aware that it requires changing attitude, it has its costs (e.g. psychological, like letting of the ego) and for sure will impact perception of the work itself too.</p><p>What benefits do you see, dear Reader?</p><p>What are potential downsides?</p><p>And remember:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>The sum of the work done in isolation does not equal the work done in collaboration, when it comes to knowledge work.</p></div></div></div>]]></content:encoded>
    <pubDate>Wed, 11 Sep 2024 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>model</category><category>modeling</category><category>development process</category><category>mental models</category><category>representations</category><category>leadership</category><category>ambiguity</category><category>misconceptions</category><category>knowledge</category><category>knowledge working</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/the-ambiguity-of-application</guid>
    <title>The ambiguity of application</title>
    <link>https://talesfrom.dev/blog/the-ambiguity-of-application</link>
    <description>What do we mean by &quot;to apply&quot;?</description>
    <content:encoded><![CDATA[<h3 id="a-pile"><a href="#a-pile" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>A pile</h3><p>Imagine that we got asked to help in the company that provides training services in the woodworking industry.</p><p>Most of their processes are still paper based and our job is going to be to help them to digitize their processes.</p><p>We got paired with a guy named Tommy, who is responsible for processing enrollment requests.</p><p>When we enter the room, we see a pile of papers on his desk.</p><p>Then we engage in the discussion.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Listen</div><div class="cursor-pointer border-2 border-l-0 border-b-0 border-gray-50 w-48 text-center text-gray-700">Listen carefully</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2">Us:</span><span>Hi Tommy! How is it going?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2">Tommy, the enrollment expert:</span><span>Hi! All good but the work is literally piling up, haha!</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2">Us:</span><span>What&#x27;s with this pile of paper?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2">Tommy, the enrollment expert:</span><span>Well, those are all <span class="">enrollment requests </span>we received in our mailbox or delivered personally by clients.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2">Us:</span><span>What are you going to do with them?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2">Tommy, the enrollment expert:</span><span>I need to go one by one and build <span class="">participant lists</span></span></div></span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2">Us:</span><span>How are you building such lists?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2">Tommy, the enrollment expert:</span><span>It might sound a bit strange but <span class="">I just know </span>. I mean, <span class="">I know company rules </span>for creating such lists. There are some strict <span class="">rules </span>I need, I mean, we need to follow. Those policies were evolving for some time and my job is <span class="">to apply all this knowledge</span>.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2">Us:</span><span>So you have all this <span class="">knowledge </span>in your head?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2">Tommy, the enrollment expert:</span><span>Pretty much, yes. Everything from <span class="">applying priority policies</span>, up to <span class="">applying recommendation rules</span>.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2">Us:</span><span>Thanks, Tommy!</span></div></span></div><h3 id="enrollment-participant-lists-customer-loyality"><a href="#enrollment-participant-lists-customer-loyality" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Enrollment, participant lists, customer loyality</h3><p>Well, that was a nice discussion, wasn&#x27;t it?</p><p>Turns out that Tommy is a very experienced guy. He posseses a lot of knowledge about the company&#x27;s rules and policies on various topics, when it comes to the process of enrollment.</p><p>We could say he would be our subject expert, as he knows a lot about this business.</p><p>Btw. would you like to see his office?</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-application-woodworking-office.png" class="max-h-[40rem]"/></div><div class="italic mx-24">Tommy&#x27;s office.</div></div><p>Nothing fancy, one might say. But it&#x27;s not about the office, it&#x27;s about the knowledge that is kept in Tommy&#x27;s head.</p><p>(btw. the office itself might work as a nice metaphor too - if you&#x27;re interested, please check <a href="https://talesfrom.dev/blog/microoffices-vs-officeolith">&quot;Microoffices&quot; vs &quot;Officeolith&quot;</a>)</p><p>As he stated, he applies all the knowledge - rules, policies and so on - to build participant lists.</p><p>Let&#x27;s imagine we asked him to explain at least some rules he applies.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2">Tommy, the enrollment expert:</span><span>Yeah, for example, when I see that a participant is a returning customer, I apply a discount. Or when I see that a participant is a member of a woodworking association, I apply a discount as well. And so on.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2">Us:</span><span>So it&#x27;s only about discounts?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2">Tommy, the enrollment expert:</span><span>Of course not. If there&#x27;s no room for more people in a training and a enrolling customer attended at least 5 courses in the past, I might move a completely new customer for the next training of the same type but the date cannot be longer than 2 weeks.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2">Us:</span><span>Two weeks? Why so?</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2">Tommy, the enrollment expert:</span><span>There&#x27;s a very strict law on this so if we don&#x27;t comply, he or she could sue us. Mike, our legal expert, wouldn&#x27;t like it.</span></div></span><span class="text-white"> </span><span class="text-white"><div class="mb-4"><span class="italic font-bold mr-2">Us:</span><span>Yeah, doesn&#x27;t sound nice.</span></div></span></div><p>It sounded a little bit easier than that, isn&#x27;t it?</p><p>The more we interviewed Tommy, the more we realized that the process of enrollment is not that simple.</p><p>Interestingly, he also mentioned that we should have a chat with Jim.</p><p>Jim is building the portfolio of courses but does not much about organizing trainers and course faciliators.</p><p>This comes from Kathy, who&#x27;s responsible for organizing woodworking experts.</p><p>Our job is to build a system, an application or applications, that will help them to manage their processes.</p><p>But let&#x27;s start from the beginning.</p><h3 id="what-does-it-all-mean"><a href="#what-does-it-all-mean" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What does it all mean?</h3><p>You might wonder, dear Reader, what the hell we just went through.</p><p>Ok, absolute basics.</p><p>You might already know dear Reader that I like start with the definitions, just to see the roots of things.</p><p>As our main goal is to create an application for our fellow training company, let&#x27;s see what the word &quot;application&quot; means.</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">an application - a definition</div><div class="pb-2 px-3"><div class="break-words"><p>an act of applying; an act of putting something to use</p></div></div></div><p>All those words...</p><p>Definitions (by their definition) are created to serve as generic, context-free explanations.</p><p>And we all know that the context is so the king, right?</p><p>Even though in the domain of IT, the word &quot;application&quot; is used to describe a software system, it&#x27;s still a bit ambiguous.</p><p>As we interviewed Tommy, we realized that the word &quot;application&quot; might mean something different.</p><p>If one listened carefully, one might notice that Tommy <strong>applied</strong> his knowledge to build participant lists.</p><p>Day by day, he used all his experience and put it to use to manage the enrollment process, create those lists and collaborate with other experts.</p><p>Let&#x27;s move for more &quot;active&quot; perspective of &quot;an application&quot;, as a word.</p><h3 id="to-apply-or-not-to-apply"><a href="#to-apply-or-not-to-apply" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>To apply or not to apply?</h3><p>Our next step is to get a verb - &quot;to apply&quot; and see what it means.</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">to apply (something) - a definition</div><div class="pb-2 px-3"><div class="break-words"><p>to put into operation or effect; to put to use especially for some practical purpose</p></div></div></div><p>It adds up too - the knowledge Tommy has is put into operation and is used in a practical sense.</p><p>As he is an enrollment process expert, he applies his know-how all the time.</p><p>We are engineers, architects - how would we apply this knowledge? (pun intended).</p><p>We could take the process of enrollment and analyze it from more &quot;abstract&quot; perspective.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-application-woodworking-processing.png" class="max-h-[40rem]"/></div><div class="italic mx-24">Enrollment request processing pipeline.</div></div><p>There are two interacting parties - a customer and an enrollment expert.</p><p>Each of them collaborate using documents: an enrollment request and a participant list.</p><p>But wait - does Tommy keep all the details of the requesting customer? What about details of the courses? Past enrollments?</p><p>Tommy knows a lot, that&#x27;s for sure. His knowledge is applied to build participant lists - he knows how to apply discounts, how to move customers to other trainings, how to comply with the law, etc.</p><p>Application of Tommy&#x27;s knowledge also includes interaction with other experts and includes using appliances, tools, and other existing documents.</p><p>Obvious thing - he is the enrollment <strong>process</strong> expert!</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-application-woodworking-processing-collaborators.png" class="max-h-[40rem]"/></div><div class="italic mx-24">Other parties providing details for Tommy to manage a participants list.</div></div><h3 id="the-ambiguity-of-application"><a href="#the-ambiguity-of-application" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The ambiguity of application</h3><p>So, what&#x27;s the point of all this?</p><p>I hear you, dear Reader: &quot;Damian, people exchanging documents and talking to each other, applying knowledge - what&#x27;s the big deal?&quot;.</p><p>Being a non-native English speaker can be a point of insightful moments.</p><p>It blew my mind when I became aware that &quot;an application&quot;, as a noun, comes from &quot;to apply something&quot; - and I asked myself - what is this &quot;something&quot;?</p><p>Isn&#x27;t it that we are applying the representation (curated, useful models) of the knowledge (concepts/ideas, living in the given area of human/business activities) to provide a solution to a particular &quot;use case&quot;?!</p><p>Or in other words: aren&#x27;t we trying to represent the knowledge by using various models and apply them in certain context?</p><p>As we already discussed that in <a href="https://talesfrom.dev/blog/the-ambiguity-of-code">The ambiguity of code</a>, &quot;the code&quot; is just a vessel to express the knowledge.</p><p>Maybe I am bending and twisting the English language too much, but I think might give an interesting perspective on how we understand what we are doing in our day to day work.</p><p>Let&#x27;s go further with our journey and let&#x27;s make an application a central part of our considerations.</p><h3 id="the-inside-and-the-outside"><a href="#the-inside-and-the-outside" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The inside and the outside</h3><p>We saw <a href="https://talesfrom.dev/blog/the-ambiguity-of-application#to-apply-or-not-to-apply">before</a> that Tommy and his knowledge application were in the center of the entire enrollment process.</p><p>His <strong>experience</strong> and <strong>knowledge</strong> make the process.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-application-ports-and-adapters-knowledge.png" class="max-h-[25rem]"/></div><div class="italic mx-24">The inside and the outside.</div></div><p>It seems very similar to Ports and Adapters architecture where application is the core of the system, isn&#x27;t it?</p><p>&quot;The outside&quot; is there &quot;just&quot; to provide all required pieces for the application to provide its own capabilities and provide solutions to certain use cases.</p><h3 id="using-models"><a href="#using-models" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Using models</h3><p>Let&#x27;s change the representation of what we explored in <a href="https://talesfrom.dev/blog/the-ambiguity-of-application#to-apply-or-not-to-apply">&quot;to apply or not to apply?&quot;</a> part and let us turn all participants into boxes.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-application-woodworking-processing-collaborators-boxes.png" class="max-h-[40rem]"/></div><div class="italic mx-24">Interacting collaborators</div></div><p>Finally, some boundaries!</p><p>There&#x27;s visible &quot;inside&quot; - knowing when a specific provider needs to be interacted with, etc.</p><p>In the real &quot;application&quot; there might not be all Jims, Henrys and Tommys - we&#x27;ll encounter some abstract ideas <strong>representing</strong> those roles, isn&#x27;t it?</p><p>Possibly, one could bring <code>Enrollment</code> as a central concept, representing a process that we talk about for so long, during this tiny tale.</p><p>What about <code>ParticipantsList</code>? Should it be a central entity? (please note dear Reader, I try to be provocative here!)</p><p>One might get a feeling that is all about &quot;nouns&quot; that &quot;live&quot; in this area of human activities - as we listed some important concepts already.</p><p>Don&#x27;t get fooled, dear Reader - an application of the knowledge representation, in the form of the model, that is centered around rules, policies, decisions, steps and so on - is the most interesting part.</p><p>Details, information - one could name it all as &quot;data&quot; - is important, but is it the most important? (if you are interested in this topic, please check <a href="https://talesfrom.dev/blog/concepts-entities-data">Concepts, Entities, Data</a>)</p><p>It wouldn&#x27;t be a decent blog post if I didn&#x27;t use a cliche statement: &quot;all models are wrong, but some are useful&quot;.</p><p>I used it so now it is a decent blog post.</p><h3 id="whats-next"><a href="#whats-next" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What&#x27;s next?</h3><p>&quot;What are you, a damn philosopher?&quot; - you might ask, dear Reader.</p><p><a href="https://tenor.com/en-GB/view/michael-scott-am-ia-hero-hero-gif-27082688">Well, I can&#x27;t really say, but yes.</a></p><p>It&#x27;s nice to chat about those things and explore metaphors but how can we use this possible insights in our next task or project?</p><p>Isn&#x27;t that when we say &quot;web application&quot;, we apply knowledge from &quot;the web engineering domain&quot; and &quot;the representation of the business logic knowledge&quot; to serve certain use cases?</p><p>Even though is might sound a bit impractical, changing the way we think about certain &quot;obvious&quot; things is crucial for personal growth - and that&#x27;s actually really practical (in my mind, at least).</p><p>Next time, dear Reader, when doing a simple assignment from your backlog, or creating an architecture, ask yourself:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>What knowledge do I need to apply here? How should it be represented? What are the rules that need to be modeled?</p></div></div></div>]]></content:encoded>
    <pubDate>Sat, 24 Aug 2024 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>programming</category><category>paradigms</category><category>domain-driven design</category><category>problem-solving</category><category>language</category><category>abstraction</category><category>modeling</category><category>business logic</category><category>processes</category><category>model</category><category>code</category><category>representations</category><category>principles</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/dogmatic-engineers-and-a-product</guid>
    <title>Dogmatic engineers and a product</title>
    <link>https://talesfrom.dev/blog/dogmatic-engineers-and-a-product</link>
    <description>Why is it important to broaden our perspective?</description>
    <content:encoded><![CDATA[<div class="bg-slate-600 rounded-xl mb-6"><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Attention #1!</span></div><div class="pb-2 px-3"><div class="break-words"><p>Please remember to take a pinch of salt with you while going through this tale!</p></div></div></div> <div class="bg-slate-600 rounded-xl "><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Attention #2!</span></div><div class="pb-2 px-3"><div class="break-words"><p>This tale is based on <a href="https://en.wikipedia.org/wiki/Blind_men_and_an_elephant">Blind men and an elephant</a></p></div></div></div><h3 id="a-problem"><a aria-hidden="true" href="#a-problem" tabindex="-1"><span class="icon icon-link"></span></a>A problem</h3><p>A group of engineers met to provide a solution to a certain business problem.</p><p>One could say the need was to build a product for a specific area of human activity.</p><p>They started debating about the problem, solutions, loudly analyzing and providing opinions regarding them.</p><h3 id="domain-centric"><a aria-hidden="true" href="#domain-centric" tabindex="-1"><span class="icon icon-link"></span></a>Domain-centric</h3><p>The first engineer belonged to a &quot;Domain-Driven Church&quot; and immediately started voicing his perspective:</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div><span class="italic mr-2 text-yellow-500">Domain-centric Engineer:</span><span>This thing is full of the specific language - terms, concepts and words. It carries a specific meaning we need to discover. Maybe even invent, that&#x27;s the fact. Regarding facts, what are important events happening through its lifetime? When we will discuss all of those, we must constantly remind ourselves about boundaries - then we will be able to identify already mentioned language and design value objects, aggregates and sagas. When do we start Event Storming?</span></div></span></div><h3 id="data-centric"><a aria-hidden="true" href="#data-centric" tabindex="-1"><span class="icon icon-link"></span></a>Data-centric</h3><p>After this little speech, the second engineer that cared only about the data begun his turn:</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div><span class="italic mr-2 text-red-500">Data-centric Engineer:</span><span>This thing contains a massive amount of information, very granular details how we can describe it. What are relationships between all of those information? What contains what? As I sense it, some data is pretty stable and cold, other is very much ever-changing and hot. Let&#x27;s not forget about very important aspects like performance when storing or restoring information - are there any constraints we need to apply? Please remember about normalization and redundant details removal! What will be a database schema? Did anyone make Entity Relationship diagram?</span></div></span></div><h3 id="ui-centric"><a aria-hidden="true" href="#ui-centric" tabindex="-1"><span class="icon icon-link"></span></a>UI-centric</h3><p>The third engineer suddenly started screaming politely:</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div><span class="italic mr-2 text-purple-500">UI-centric Engineer:</span><span>This thing for sure is going to be used by real people, end users. What about them? We need to make their experience delightful and supportive. They shouldn&#x27;t spend time staring at loading screens full of spinners! What&#x27;s more, they should be guided through out the whole journey, all the confusion and doubts should cease to exist when looking at beautifully crafted user interfaces! To achieve so, we need to pick SPA and modern front-end tools. Do we have any low-fidelity wireframes and mock-ups? React or React?</span></div></span></div><h3 id="process-centric"><a aria-hidden="true" href="#process-centric" tabindex="-1"><span class="icon icon-link"></span></a>Process-centric</h3><p>The fourth engineer calmly stood and threw his speech:</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div><span class="italic mr-2 text-green-500">Process-centric Engineer:</span><span>This thing seems to have steps that take some time and occur in specific moments. All of these require integrating with various parties and collaboring with many downstream and upstream services. We should start modeling all of these before we actually write a single line of code. For sure there are off the shelf tools that will help generate code from our process models, so that we will be able spend more time on analyzing dependencies. Where are our BPMNs artifacts?</span></div></span></div><h3 id="platform-centric"><a aria-hidden="true" href="#platform-centric" tabindex="-1"><span class="icon icon-link"></span></a>Platform-centric</h3><p>The last, fifth engineer waited for his moment so when the time came he closed the whole discussion with the following words:</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div><span class="italic mr-2 text-blue-500">Platform-centric Engineer:</span><span>This thing, in order to run, requires hosting. Even though it might start as a tiny thing, it will grow. How do we provide enough resources to achieve so? What&#x27;s more, it needs to run in secure environment, but before that we need to have deployment and release pipelines, with full automation - having so, we will scale development and ensure development teams are focusing on building things that matter, and not delve into infrastructure details. Can we pre-decide how many nodes should be in our k8s cluster?</span></div></span></div><h3 id="a-solution"><a aria-hidden="true" href="#a-solution" tabindex="-1"><span class="icon icon-link"></span></a>A solution</h3><p>How easy it is to apply lenses and deeply focus on one particular aspect, when designing?</p><p>Designing is hard, difficult and effortful.</p><p>Solutions, serving the needs of the consumers, require time, thoughts, experiments, iterations and mistakes.</p><p>One could probably say that it&#x27;s a role of an architect to provide multiple perspectives and keep and equally visible.</p><p>Engineers should &quot;just&quot; do what engineers suppose to do - implement. Ain&#x27;t so, dear Reader?</p><p>Turns out things are more fluid and unpredictable when we organize human beings to conduct designing activities.</p><p>What was the first, an organization, a problem or a solution?</p><h3 id="epilogue"><a aria-hidden="true" href="#epilogue" tabindex="-1"><span class="icon icon-link"></span></a>Epilogue</h3><p>After hearing all of the perspectives, each engineer was both happy and sad.</p><p>Can you tell why, dear Reader?</p>]]></content:encoded>
    <pubDate>Fri, 26 Jul 2024 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>growing software</category><category>heuristics</category><category>mental models</category><category>software architecture</category><category>product engineering</category><category>architecting</category><category>perspectives</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/map-dont-ask</guid>
    <title>Map, don&#39;t ask</title>
    <link>https://talesfrom.dev/blog/map-dont-ask</link>
    <description>Why you shouldn&#39;t peek inside a...?</description>
    <content:encoded><![CDATA[<div class="bg-slate-600 rounded-xl "><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Attention!</span></div><div class="pb-2 px-3"><div class="break-words"><p>No, it is not an YAMT - Yet Another Monad Tutorial.</p>
<p>There will be no burritos, boxes...Or maybe there will be?</p></div></div></div><h3 id="finally-functional-programming"><a href="#finally-functional-programming" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Finally, functional programming</h3><p>Let&#x27;s imagine we attended a conference when someone was glorifying functional programming and all benefits it brings - purity, no poverity in the world, wealth to all the people, etc.</p><p>It sounded pretty impressive and someone from our team (yes, this person attended the conference too!) decided to grab one of the packages, from the ecosystem we &quot;live in&quot;, that brings &quot;functional powers&quot;.</p><p>(Yes dear Reader, there&#x27;s a tiny assumption that we don&#x27;t work with a functional-first language, but please bear with me)</p><p>Let&#x27;s say we work with .NET (avid Reader might spot that .NET = C#) and we can use <code>CSharpFunctionalExtensions</code> as our package of choice.</p><p>We check the docs and what we see? <code>Maybe</code> type.</p><h3 id="barbaric-nulls"><a href="#barbaric-nulls" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Barbaric nulls</h3><p>Can you feel this power too?</p><p>No more nulls!</p><p>No more problems!</p><p>No more poverty!</p><p>Let&#x27;s imagine we took one of our command handlers that worked with a repository in order to try to get active user with given identifier and then deactive that user.</p><p>Deactivating has a consequence on permissions which we need to take care of too.</p><p>Fortunately, we don&#x27;t have huge traffic and it should happen immediately - meaning that we can&#x27;t &quot;distribute&quot; handling this workflow.</p><p>Yes, no asynchronous processing this time.</p><p>Before &quot;functionalifying&quot;, dull, not functional and not impressive code looked as follows:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">DeactivateUserCommandHandler</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token function">DeactivateUserCommandHandler</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token class-name">ActiveUsersRepository</span> activeUsers<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">GroupPermissionsRepository</span> groupPermissions
</span><span class="code-line">    <span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        _activeUsers <span class="token operator">=</span> activeUsers<span class="token punctuation">;</span>
</span><span class="code-line">        _groupPermissions <span class="token operator">=</span> groupPermissions<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">Handle</span><span class="token punctuation">(</span><span class="token class-name">DeactivateUserCommand</span> command<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> userId <span class="token operator">=</span> command<span class="token punctuation">.</span>UserId<span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> activeUser <span class="token operator">=</span> <span class="token keyword">await</span> _activeUsers<span class="token punctuation">.</span><span class="token function">GetBy</span><span class="token punctuation">(</span>userId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">if</span><span class="token punctuation">(</span>activeUser <span class="token keyword">is</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">CannotDeactivateUser</span><span class="token punctuation">(</span>userId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">        activeUser<span class="token punctuation">.</span><span class="token function">Deactivate</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> userGroupPermissions <span class="token operator">=</span> <span class="token keyword">await</span> _groupPermissions<span class="token punctuation">.</span><span class="token function">GetFor</span><span class="token punctuation">(</span>userId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">if</span><span class="token punctuation">(</span>userGroupPermissions <span class="token keyword">is</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">CannotDeactivateUser</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;Cannot remove group permissions for user </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token language-csharp expression">userId</span><span class="token punctuation">}</span></span><span class="token string">&quot;</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">        userGroupPermissions<span class="token punctuation">.</span><span class="token function">Remove</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token keyword">await</span> _activeUsers<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>activeUser<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">await</span> _groupPermissions<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>userGroupPermissions<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>This <code>null</code> - pathetic.</p><p>Good that we have functional programming to take care of that pesky, barbaric null!</p><h3 id="finally-monads"><a href="#finally-monads" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Finally, monads!</h3><p>Imagine that we added a new overloaded method in our <code>ActiveUsersRepository</code> that expresses the effect of &quot;missingness&quot; of an active user.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">ActiveUsersRepository</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// ...other &quot;old&quot; methods</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>Maybe<span class="token punctuation">&lt;</span>ActiveUser<span class="token punctuation">&gt;</span><span class="token punctuation">&gt;</span></span> <span class="token function">GetBy</span><span class="token punctuation">(</span><span class="token class-name">UserId</span> userId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Now we are talking, our method is <strong>honest</strong> and tells the full story! (does it?)</p><p>Let&#x27;s make proper adjustments.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">DeactivateUserCommandHandler</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">IHandle<span class="token punctuation">&lt;</span>DeactivateUserCommand<span class="token punctuation">&gt;</span></span></span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token function">DeactivateUserCommandHandler</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token class-name">ActiveUsersRepository</span> activeUsers<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">GroupPermissionsRepository</span> groupPermissions
</span><span class="code-line">    <span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        _activeUsers <span class="token operator">=</span> activeUsers<span class="token punctuation">;</span>
</span><span class="code-line">        _groupPermissions <span class="token operator">=</span> groupPermissions<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">Handle</span><span class="token punctuation">(</span><span class="token class-name">DeactivateUserCommand</span> command<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> userId <span class="token operator">=</span> command<span class="token punctuation">.</span>UserId<span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> activeUser <span class="token operator">=</span> <span class="token keyword">await</span> _activeUsers<span class="token punctuation">.</span><span class="token function">GetBy</span><span class="token punctuation">(</span>userId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">if</span><span class="token punctuation">(</span>activeUser<span class="token punctuation">.</span>HasNoValue<span class="token punctuation">)</span> <span class="token comment">// 👈️ changed code!</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">CannotDeactivateUser</span><span class="token punctuation">(</span>userId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">        activeUser<span class="token punctuation">.</span>Value<span class="token punctuation">.</span><span class="token function">Deactivate</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 👈️ changed code!</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> userGroupPermissions <span class="token operator">=</span> <span class="token keyword">await</span> _groupPermissions<span class="token punctuation">.</span><span class="token function">GetFor</span><span class="token punctuation">(</span>userId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">if</span><span class="token punctuation">(</span>userGroupPermissions <span class="token keyword">is</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token comment">// ❌ here aren&#x27;t that functional yet 😥</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">CannotDeactivateUser</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;Cannot remove group permissions for user </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token language-csharp expression">userId</span><span class="token punctuation">}</span></span><span class="token string">&quot;</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">        userGroupPermissions<span class="token punctuation">.</span><span class="token function">Remove</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token keyword">await</span> _activeUsers<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>activeUser<span class="token punctuation">.</span>Value<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 👈️ changed code!</span>
</span><span class="code-line">        <span class="token keyword">await</span> _groupPermissions<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>userGroupPermissions<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>So much functional programming!</p><h3 id="lazy-anemic-folks"><a href="#lazy-anemic-folks" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Lazy, anemic folks</h3><p>I hope you already know it, dear Reader, that I like to talk to parts of the code I wrote, as if they were actors playing their roles on the scene. (you don&#x27;t know what I am talking about? Go ahead and check <a href="https://talesfrom.dev/blog/conversation-driven-design">Conversation-Driven Design</a>) or <a href="https://talesfrom.dev/blog/i-interface">I, interface</a>)</p><p>Should we talk to <code>DeactivateUserCommandHandler</code>?</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div><span class="italic mr-2 text-blue-500">Us:</span><span>Hey!</span></div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic mr-2 text-red-500">DeactivateUserCommandHandler:</span><span>Yo, how&#x27;s life?</span></div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic mr-2 text-blue-500">Us:</span><span>Quite nice. What&#x27;s on your end?</span></div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic mr-2 text-red-500">DeactivateUserCommandHandler:</span><span>Quite nice too. Any problems?</span></div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic mr-2 text-blue-500">Us:</span><span>We are wondering about your responsiblity - what do you do?</span></div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic mr-2 text-red-500">DeactivateUserCommandHandler:</span><span>I am responsible for handling user deactivation command. Typically I am asking for a snapshot of active user, then I am asking if such active user exists and then I am requesting deactivation. In case of such active user does not exist, I need to stop further handling.</span></div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic mr-2 text-blue-500">Us:</span><span>Why do you need to firstly ask if active user exists and then request deactivation?</span></div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic mr-2 text-red-500">DeactivateUserCommandHandler:</span><span>You know objects these days - they are lazy, one could say - pretty anemic. They have no responsibilities! Look at us, command handlers, we need to take care of everything...</span></div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic mr-2 text-blue-500">Us:</span><span>Yeah...That sucks...What would be the ideal scenario?</span></div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic mr-2 text-red-500">DeactivateUserCommandHandler:</span><span>Ideally, objects would take the responsibility of themselves - I would just say tell an object to deactivate and it will decide that to do.</span></div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic mr-2 text-blue-500">Us:</span><span>Thanks, that was helpful conversaion. It&#x27;s good to have a chat!</span></div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic mr-2 text-red-500">DeactivateUserCommandHandler:</span><span>This chat was great, I feel less miserable now. Need to go - another command comming...See ya!</span></div></span></div><p>Interesting, isn&#x27;t it?</p><p>In this little therapy session, <code>DeactivateUserCommandHandler</code> revealed interesting observation - it is quite overloaded.</p><p>It should take care of ensuring that the process of deactivation runs smoothly, one step after another, but now it seems that it has too much responsibilities.</p><p>Ok, even if we did hardcore functional programming, let&#x27;s get back to the roots.</p><p>Let&#x27;s turn our sight onto objects that collaborate and talk to each other in order to perform some activities.</p><h3 id="tell-dont-ask"><a href="#tell-dont-ask" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Tell, don&#x27;t ask</h3><p>&quot;In the old and good days&quot;, objects were fully responsible for themselves (at least that&#x27;s what our parents ought to say to us).</p><p>In our tiny tale, <code>DeactivateUserCommandHandler</code> know intimate and spicy details of summoned collaborators and needs to deal with them explicitly (is it a bad or a good thing?).</p><p>Those collaborators might not exist (checks for &quot;missingness&quot;) and then it needs to react appriopriately (throwing exceptions).</p><p>So our handler asks about the state (&quot;do you exist?&quot;) and then makes the decision.</p><p>Could we do something about it? Re-assign responsibilities so that <code>DeactivateUserCommandHandler</code> knows less?</p><p>Let&#x27;s &quot;just&quot; do some wishful thinking &quot;coding&quot; and write down how we would imagine this collaboration could look like.</p><p>Just so you know, dear Reader, I will drop the usage of newly added method:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">ActiveUsersRepository</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// ...other &quot;old&quot; methods</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>Maybe<span class="token punctuation">&lt;</span>ActiveUser<span class="token punctuation">&gt;</span><span class="token punctuation">&gt;</span></span> <span class="token function">GetBy</span><span class="token punctuation">(</span><span class="token class-name">UserId</span> userId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>In favor of &quot;old&quot;, barbaric &quot;object-oriented&quot; one, so it looks as follows:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">DeactivateUserCommandHandler</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">IHandle<span class="token punctuation">&lt;</span>DeactivateUserCommand<span class="token punctuation">&gt;</span></span></span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token function">DeactivateUserCommandHandler</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token class-name">ActiveUsersRepository</span> activeUsers<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">GroupPermissionsRepository</span> groupPermissions
</span><span class="code-line">    <span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        _activeUsers <span class="token operator">=</span> activeUsers<span class="token punctuation">;</span>
</span><span class="code-line">        _groupPermissions <span class="token operator">=</span> groupPermissions<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">Handle</span><span class="token punctuation">(</span><span class="token class-name">DeactivateUserCommand</span> command<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> userId <span class="token operator">=</span> command<span class="token punctuation">.</span>UserId<span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> activeUser <span class="token operator">=</span> <span class="token keyword">await</span> _activeUsers<span class="token punctuation">.</span><span class="token function">GetBy</span><span class="token punctuation">(</span>userId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        activeUser<span class="token punctuation">.</span><span class="token function">Deactivate</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 👈️ Look, no ifs!</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> userGroupPermissions <span class="token operator">=</span> <span class="token keyword">await</span> _groupPermissions<span class="token punctuation">.</span><span class="token function">GetFor</span><span class="token punctuation">(</span>userId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        userGroupPermissions<span class="token punctuation">.</span><span class="token function">Remove</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token keyword">await</span> _activeUsers<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>activeUser<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 👈️ Look, no ifs!</span>
</span><span class="code-line">        <span class="token keyword">await</span> _groupPermissions<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>userGroupPermissions<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><h3 id="ifs"><a href="#ifs" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Ifs?</h3><p>All experienced and smart people will probably immediately notice that &quot;there are no ifs&quot; is a complete lie.</p><p>And yes - that&#x27;s true - it is a lie.</p><p>They didn&#x27;t disappear, just changed places (&quot;Complexity does not disappear, it gets moved&quot;, remember?).</p><p>In our tiny tale&#x27;s problem area, there&#x27;s clearly a concept of an &quot;active user&quot;, so let&#x27;s inspect that.</p><p>What we know about it? Well, there&#x27;s a clear responsibility: be able to get itself deativated.</p><p>Let&#x27;s represent that capability:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">ICanBeDeactivated</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">void</span></span> <span class="token function">Deactivate</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Now comes the abstract concept of an user that is regarded as active.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">abstract</span> <span class="token keyword">class</span> <span class="token class-name">ActiveUser</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> ActiveUserId<span class="token punctuation">)</span> <span class="token punctuation">:</span> ICanBeDeactivated
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">protected</span> <span class="token class-name">Guid</span> ActiveUserId <span class="token operator">=</span> ActiveUserId<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">abstract</span> <span class="token class-name return-type"><span class="token keyword">void</span></span> <span class="token function">Deactivate</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>And finally - let&#x27;s make this &quot;concept&quot; responsible for itself by making it the owner of its &quot;missingness&quot; variant:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">NonExistingActiveUser</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> ActiveUserId<span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token function">ActiveUser</span><span class="token punctuation">(</span>ActiveUserId<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">override</span> <span class="token class-name return-type"><span class="token keyword">void</span></span> <span class="token function">Deactivate</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">CannotDeactivateUser</span><span class="token punctuation">(</span>ActiveUserId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Ok, now the &quot;happy path&quot;:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ExistingActiveUser</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> ActiveUserId<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">bool</span></span> IsActive<span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token function">ActiveUser</span><span class="token punctuation">(</span>ActiveUserId<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">private</span> <span class="token class-name"><span class="token keyword">bool</span></span> _isActive <span class="token operator">=</span> IsActive<span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">override</span> <span class="token class-name return-type"><span class="token keyword">void</span></span> <span class="token function">Deactivate</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span>_isActive<span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">CannotDeactivateUser</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;Cannot deactivate already deactivated user with id </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token language-csharp expression">ActiveUserId</span><span class="token punctuation">}</span></span><span class="token string">&quot;</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        _isActive <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>As you can see, dear Reader, we modelled two variants, or I should probably say, two cases of an active user.</p><p>In one of the cases, there&#x27;s no existing active user with a given id, whereas the another one represents the existing one.</p><p>How does this changed our design?</p><p>We are &quot;telling&quot; this abstract concept what we want it to do, without asking.</p><p>Each of its &quot;aspects&quot; clearly knows what to do.</p><p>But hey, there&#x27;s a strong requirement that this user groups permissions need to be removed as it gets deativated.</p><p>Shouldn&#x27;t we design the interface to enforce that?</p><h3 id="need-driven-design"><a href="#need-driven-design" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Need-Driven Design</h3><p>Let&#x27;s alter deactivating capability so that it expresses such requirement:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">ICanBeDeactivated</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">void</span></span> <span class="token function">Deactivate</span><span class="token punctuation">(</span><span class="token class-name">IRemoveUserGroupPermissions</span> andContinueWith<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>For now, we&#x27;re going to omit strangely named argument.</p><p>We&#x27;re focusing on (yet) non-existing capability but we clearly know what we want to achieve.</p><p>What will be the usage?</p><p>Let&#x27;s focus on that, rather than thinking how one could implement it.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">DeactivateUserCommandHandler</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">IHandle<span class="token punctuation">&lt;</span>DeactivateUserCommand<span class="token punctuation">&gt;</span></span></span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token function">DeactivateUserCommandHandler</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token class-name">ActiveUsersRepository</span> activeUsers<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">GroupPermissionsRepository</span> groupPermissions
</span><span class="code-line">    <span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        _activeUsers <span class="token operator">=</span> activeUsers<span class="token punctuation">;</span>
</span><span class="code-line">        _groupPermissions <span class="token operator">=</span> groupPermissions<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">Handle</span><span class="token punctuation">(</span><span class="token class-name">DeactivateUserCommand</span> command<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> userId <span class="token operator">=</span> command<span class="token punctuation">.</span>UserId<span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> activeUser <span class="token operator">=</span> <span class="token keyword">await</span> _activeUsers<span class="token punctuation">.</span><span class="token function">GetBy</span><span class="token punctuation">(</span>userId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">await</span> activeUser<span class="token punctuation">.</span><span class="token function">Deactivate</span><span class="token punctuation">(</span>
</span><span class="code-line">            <span class="token punctuation named-parameter">andContinueWith</span><span class="token punctuation">:</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">UserGroupPermissionsRemoval</span><span class="token punctuation">(</span>_groupPermissions<span class="token punctuation">)</span> <span class="token comment">// 👈️ here&#x27;s what has changed!</span>
</span><span class="code-line">        <span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">await</span> _activeUsers<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>activeUser<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>It looks strangely suspicious, isn&#x27;t it?</p><p>An object without any &quot;asynchronicity&quot; suddenly got &quot;awaited&quot;.</p><p>Smell-ish, right?</p><p>We can start thinking about our new collaborator - <code>UserGroupPermissionsRemoval</code>.</p><p>Based on its usage, I believe we can figure out how it might work:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token comment">// 👇 a new responsibility!</span>
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">IRemoveUserGroupPermissions</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name return-type">Task</span> <span class="token function">RemoveFor</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> userId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token comment">// 👇 a new collaborator that has this responsibility</span>
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">UserGroupPermissionsRemoval</span><span class="token punctuation">(</span><span class="token class-name">GroupPermissionsRepository</span> GroupPermissions<span class="token punctuation">)</span> <span class="token punctuation">:</span> IRemoveUserGroupPermissions
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">RemoveFor</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> userId<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> userGroupPermissions <span class="token operator">=</span> <span class="token keyword">await</span> GroupPermissions<span class="token punctuation">.</span><span class="token function">GetFor</span><span class="token punctuation">(</span>userId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        userGroupPermissions<span class="token punctuation">.</span><span class="token function">Remove</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">await</span> GroupPermissions<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>userGroupPermissions<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>As we changed the responsiblity for deactivating oneself, we need to ensure a specific aspect of the abstract concept - active user - also aligns to the new design!</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ExistingActiveUser</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> ActiveUserId<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">bool</span></span> IsActive<span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token function">ActiveUser</span><span class="token punctuation">(</span>ActiveUserId<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">private</span> <span class="token class-name"><span class="token keyword">bool</span></span> _isActive <span class="token operator">=</span> IsActive<span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">override</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">Deactivate</span><span class="token punctuation">(</span><span class="token class-name">IRemoveUserGroupPermissions</span> userGroupPermissionsRemoval<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span>_isActive<span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">CannotDeactivateUser</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;Cannot deactivate already deactivated user with id </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token language-csharp expression">ActiveUserId</span><span class="token punctuation">}</span></span><span class="token string">&quot;</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        _isActive <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">await</span> userGroupPermissionsRemoval<span class="token punctuation">.</span><span class="token function">RemoveFor</span><span class="token punctuation">(</span>ActiveUserId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>We will omit the details of how does <code>UserGroupPermissions</code> concept looks and works internally - one can derive the implementation based on what we did.</p><h3 id="functional-programming"><a href="#functional-programming" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Functional programming?</h3><p>I hear you dear Reader - we started with hardcore functional programming by introducing <code>CSharpFunctionalExtensions</code> and suddenly we wrote some objects - come on, what is that - an amateur hour?!</p><p>The collaborating objects showed one interesting attribute - the composition.</p><p><code>DeactivateUserCommandHandler</code> composed their powers together without controlling each and every &quot;step&quot; of each collaborator.</p><p>Instead of &quot;orchestrating&quot; lazy and anemic objects, we excelled their skills to the maximum of their ownership.</p><p>Before, the syntax haven&#x27;t changed that much as we procedurally checked for &quot;the missingness&quot;, either by using <code>is null</code> or <code>HasNoValue</code>.</p><p>Let&#x27;s try to do the same with <code>Maybe</code> type - <code>DeactivateUserCommandHandler</code> should focus on composition rather than asking for its &quot;internals&quot;!</p><p><strong>NOTE</strong>: if you are sensitive to ugly/unreadable code, either omit the next lines and rush to summary or please be forgiving.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">DeactivateUserCommandHandler</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">IHandle<span class="token punctuation">&lt;</span>DeactivateUserCommand<span class="token punctuation">&gt;</span></span></span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token function">DeactivateUserCommandHandler</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token class-name">ActiveUsersRepository</span> activeUsers<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">GroupPermissionsRepository</span> groupPermissions
</span><span class="code-line">    <span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        _activeUsers <span class="token operator">=</span> activeUsers<span class="token punctuation">;</span>
</span><span class="code-line">        _groupPermissions <span class="token operator">=</span> groupPermissions<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">Handle</span><span class="token punctuation">(</span><span class="token class-name">DeactivateUserCommand</span> command<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> userId <span class="token operator">=</span> command<span class="token punctuation">.</span>UserId<span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">(</span><span class="token keyword">await</span> _activeUsers
</span><span class="code-line">            <span class="token punctuation">.</span><span class="token function">GetBy</span><span class="token punctuation">(</span>userId<span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token punctuation">.</span><span class="token function">Map</span><span class="token punctuation">(</span>activeUser <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
</span><span class="code-line">                activeUser<span class="token punctuation">.</span><span class="token function">Deactivate</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">                <span class="token keyword">return</span> activeUser<span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token punctuation">}</span><span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token punctuation">.</span><span class="token function">ToResult</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;Cannot deactivate the user with id </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token language-csharp expression">userId</span><span class="token punctuation">}</span></span><span class="token string">&quot;</span></span><span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token punctuation">.</span><span class="token function">Bind</span><span class="token punctuation">(</span><span class="token keyword">async</span> <span class="token punctuation">(</span>activeUser<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> 
</span><span class="code-line">                <span class="token punctuation">(</span><span class="token keyword">await</span> _groupPermissions
</span><span class="code-line">                        <span class="token punctuation">.</span><span class="token function">GetFor</span><span class="token punctuation">(</span>userId<span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class="code-line">                        <span class="token punctuation">.</span><span class="token function">Map</span><span class="token punctuation">(</span>userGroupPermissions <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
</span><span class="code-line">                            userGroupPermissions<span class="token punctuation">.</span><span class="token function">Remove</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">                            <span class="token keyword">return</span> <span class="token punctuation">(</span>activeUser<span class="token punctuation">,</span> userGroupPermissions<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">                        <span class="token punctuation">}</span><span class="token punctuation">)</span>
</span><span class="code-line">                        <span class="token punctuation">.</span><span class="token function">ToResult</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;Cannot remove group permissions for user </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token language-csharp expression">userId</span><span class="token punctuation">}</span></span><span class="token string">&quot;</span></span><span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token punctuation">.</span><span class="token function">Match</span><span class="token punctuation">(</span>
</span><span class="code-line">                <span class="token punctuation named-parameter">onSuccess</span><span class="token punctuation">:</span> <span class="token keyword">async</span> <span class="token punctuation">(</span>activeUser<span class="token punctuation">,</span> userGroupPermissions<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
</span><span class="code-line">                    <span class="token keyword">await</span> _activeUsers<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>activeUser<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">                    <span class="token keyword">await</span> _groupPermissions<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>userGroupPermissions<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">                <span class="token punctuation">}</span><span class="token punctuation">,</span>
</span><span class="code-line">                <span class="token punctuation named-parameter">onFailure</span><span class="token punctuation">:</span> <span class="token keyword">async</span> <span class="token punctuation">(</span>error<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
</span><span class="code-line">                    <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">CannotDeactivateUser</span><span class="token punctuation">(</span>error<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">                <span class="token punctuation">}</span>
</span><span class="code-line">            <span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>(note dear Reader that this might not compile without additional type annotations - C# hasn&#x27;t that well type inference when combined with <code>CSharpFunctionalExtensions</code>)</p><p>I firmly believe that if you got &quot;Ok, what the hell just happened?&quot; reaction - you&#x27;re probably a healthy human being.</p><p>We went from &quot;procedural missingness checking&quot; into &quot;tell, don&#x27;t ask&quot;-ish way of handling it by passing behavior &quot;inside&quot; - to <code>Maybe</code> and to <code>Result</code>, later in the processing.</p><p>Of course, functional programming is &quot;all about expressions&quot; and this &quot;design&quot; expresses that.</p><p>Everything gets transformed along the way - from <code>Maybe</code> to <code>Result</code> - which summons a behemoth full of unreadable piece of code.</p><p>But please, don&#x27;t &quot;blame&quot; functional programming.</p><p>To fully benefit from &quot;sequential&quot; processing via &quot;monadic comprehension&quot;, that reduces boilerplate quite much, we would need to employ <a href="https://tyrrrz.me/blog/monadic-comprehension-via-linq">Monadic Comprehension Syntax via LINQ in C#</a> presented by <a href="https://tyrrrz.me/">Oleksii</a>.</p><p>It would probably looks something like this:</p><p><strong>NOTE #1</strong>: it&#x27;s based on the blog post mentioned above, so feel encouraged to read it first!</p><p><strong>NOTE #2</strong>: the syntax below is how I imagine it could look like - sounds like a nice exercise to implement, isn&#x27;t it?</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">DeactivateUserCommandHandler</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">IHandle<span class="token punctuation">&lt;</span>DeactivateUserCommand<span class="token punctuation">&gt;</span></span></span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token function">DeactivateUserCommandHandler</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token class-name">ActiveUsersRepository</span> activeUsers<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">GroupPermissionsRepository</span> groupPermissions
</span><span class="code-line">    <span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        _activeUsers <span class="token operator">=</span> activeUsers<span class="token punctuation">;</span>
</span><span class="code-line">        _groupPermissions <span class="token operator">=</span> groupPermissions<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">Handle</span><span class="token punctuation">(</span><span class="token class-name">DeactivateUserCommand</span> command<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> deactivationResult <span class="token operator">=</span>
</span><span class="code-line">            <span class="token keyword">await</span> <span class="token punctuation">(</span>
</span><span class="code-line">                <span class="token keyword">from</span> activeUser <span class="token keyword">in</span> activeUsers<span class="token punctuation">.</span><span class="token function">GetBy</span><span class="token punctuation">(</span>userId<span class="token punctuation">)</span>
</span><span class="code-line">                <span class="token keyword">let</span> deactivatedUser <span class="token operator">=</span> activeUser<span class="token punctuation">.</span><span class="token function">Deactivate</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">                <span class="token keyword">from</span> userGroupPermissions <span class="token keyword">in</span> groupPermissions<span class="token punctuation">.</span><span class="token function">GetFor</span><span class="token punctuation">(</span>userId<span class="token punctuation">)</span>
</span><span class="code-line">                <span class="token keyword">let</span> newUserGroupPermissions <span class="token operator">=</span> userGroupPermissions<span class="token punctuation">.</span><span class="token function">Remove</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">                <span class="token keyword">let</span> savingDeactivatedUser <span class="token operator">=</span> activeUsers<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>deactivatedUser<span class="token punctuation">)</span>
</span><span class="code-line">                <span class="token keyword">let</span> savingUserGroupPermissions <span class="token operator">=</span> groupPermissions<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>newUserGroupPermissions<span class="token punctuation">)</span>
</span><span class="code-line">                <span class="token keyword">select</span> <span class="token punctuation">(</span>Result<span class="token punctuation">.</span><span class="token function">Combine</span><span class="token punctuation">(</span>savingDeactivatedUser<span class="token punctuation">,</span> savingUserGroupPermissions<span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token punctuation">)</span>
</span><span class="code-line">        
</span><span class="code-line">        deactivationResult<span class="token punctuation">.</span><span class="token function">Match</span><span class="token punctuation">(</span>
</span><span class="code-line">            <span class="token punctuation named-parameter">onSuccess</span><span class="token punctuation">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
</span><span class="code-line">            <span class="token punctuation named-parameter">onFailure</span><span class="token punctuation">:</span> <span class="token punctuation">(</span>error<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
</span><span class="code-line">                <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">CannotDeactivateUser</span><span class="token punctuation">(</span>error<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token punctuation">}</span>
</span><span class="code-line">        <span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><h3 id="functional-tell-dont-ask"><a href="#functional-tell-dont-ask" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Functional &quot;tell, don&#x27;t ask&quot;?</h3><p>Even though this was a tiny, toy example, we explored an important trait of designing using &quot;tell, don&#x27;t ask&quot; approach - focusing on &quot;what&quot; and passing behavior around.</p><p>Expressing effects like &quot;missingness&quot; (via <code>Maybe</code>) or &quot;branching (with erroneous path)&quot; (via <code>Result</code>) might require thinking in terms of &quot;passing the behavior in&quot;, rather then trying to &quot;peek what&#x27;s inside&quot;.</p><p>We saw something similar in representing abstract concepts like an active user, covering two cases that existed in our tiny tale&#x27;s &quot;knowledge area&quot;.</p><p>Either functional or object oriented - we tried our best to manifest certain aspects, like missingness.</p><p>When working with <code>Maybe</code>, instead of &quot;peeking inside&quot;, we can &quot;tell&quot; it to perform a mapping (a transformation) by passing it a behavior that will be used <strong>if</strong> there&#x27;s something inside.</p><p>We want to keep the intimate details of &quot;the packaging&quot; and not obsessively have the control of everything.</p><p>We often talk about &quot;primitive obsession&quot;, maybe we should start talking about &quot;control obsession&quot;?</p><h3 id="dont-ask-the-effect-tell-it-about-transformations"><a href="#dont-ask-the-effect-tell-it-about-transformations" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Don&#x27;t ask the effect, tell it about transformations</h3><p>As authors of <a href="https://www.amazon.com/Growing-Object-Oriented-Software-Guided-Tests/dp/0321503627">GOOS</a> wrote:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>We have objects sending each other messages, so what do they say? Our experience is that the calling object should describe what it wants in terms of the role that its neighbor plays, and let the called object decide how to make that happen. This is commonly known as the “Tell, Don’t Ask” style or, more formally, the Law of Demeter.</p>
<p>Objects make their decisions based only on the information they hold internally or that which came with the triggering message; they avoid navigating to other objects to make things happen.</p></div></div></div><p><code>Maybe</code> or <code>Result</code> did something similar - they &quot;made decisions&quot; based on the information they held internally.</p><p>We didn&#x27;t want to &quot;obsessively control&quot; them - we trusted them that they &quot;are&quot; certain structures, having certain attributes and based on those motivations we could just describe transformations, and &quot;let them do the rest of the job&quot;.</p><p>And of course - they are not &quot;objects&quot;, so to speak. We are not &quot;sending messages to them&quot;, but what about behaviors?</p><p>Let&#x27;s jump back to <a href="https://www.amazon.com/Growing-Object-Oriented-Software-Guided-Tests/dp/0321503627">GOOS</a>:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>We find that by applying “Tell, Don’t Ask” consistently, we end up with a coding style where we tend <strong>to pass behavior (in the form of callbacks)</strong> into the system instead of pulling values up through the stack.</p></div></div></div><p>Well, callbacks.</p><p>Passing functions here and there.</p><p>Treating them as regular values - we know that, right?</p><h3 id="what-is-it-all-about"><a href="#what-is-it-all-about" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What is it all about?</h3><p>It is all about composition.</p><p>&quot;Ifs do not compose&quot;, one could say.</p><p>As with applying &quot;non existing&quot; aspect of an <code>ActiveUser</code> abstract concept (in the form of <code>NonExistingActiveUser</code>), which turned out to be a <a href="https://refactoring.guru/pl/introduce-null-object">Null Object</a> pattern, using <code>Maybe</code> and/or <code>Result</code> helped us by moving &quot;ifs&quot; somewhere else.</p><p>It gave us powers to compose functions together, working with &quot;effects&quot; explicitly.</p><p>Instead of procedurally control everything, everytime, we could &quot;trust&quot; the promises provided by the &quot;algebraic structures&quot; that <code>Maybe</code> and <code>Result</code> types are.</p><p>Even though objects and monads are different, they tend to provide solutions to similar set of problems.</p><p>For object, this magic happened if we started treating objects as units of behavior, rather than &quot;structures&quot;.</p><p>Those solutions tend to orbit around passing behavior in and not focusing on the structure too much.</p><p>And such approaches favor composition (of functions or of objects) too.</p><p>Suddenly, when we employ &quot;wishful&quot; designing, which in fact might be understood as a declarative way of representing intensions and providing promises, the holy grail of composition naturally emerges either from the collaboration of objects or from the set of effectful transformations.</p><p>So next time dear Reader, either tell your objects to do their job or transform your effects into new ones.</p><p>But don&#x27;t ask.</p><p>Well, at least most of the times.</p>]]></content:encoded>
    <pubDate>Sun, 30 Jun 2024 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>functional programming</category><category>object-oriented programming</category><category>design patterns</category><category>growing object-oriented software</category><category>heuristics</category><category>mental models</category><category>composition</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/the-law-of-eventual-composition</guid>
    <title>The law of eventual composition</title>
    <link>https://talesfrom.dev/blog/the-law-of-eventual-composition</link>
    <description>What happens when we split things up?</description>
    <content:encoded><![CDATA[<div class="bg-slate-600 rounded-xl "><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Attention!</span></div><div class="pb-2 px-3"><div class="break-words"><p>&quot;A law&quot; might be perceived as very strict and formal description of the observation I made.</p>
<p>And that&#x27;s possibly correct. I can&#x27;t prove anything except telling a tale or two.</p></div></div></div><h3 id="can-you-help-me"><a href="#can-you-help-me" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Can you help me?&quot;</h3><p>One day I was asked by a colleague if I can help him.</p><p>Let&#x27;s say his name was Kyle.</p><p>Kyle said that I have an engineering background (I am a control engineer by heart), which made me curious even more.</p><p>I followed up with a question - &quot;Ok, but what do you want me to help with?&quot;</p><p>&quot;I want to get help with reading how much energy we have produced by solar panels&quot;.</p><p>That made be a bit suspicious - &quot;You can read, right? So what&#x27;s the real problem?&quot;, I laughed.</p><p>&quot;Yeah, yeah, I can but you know - I thought I might use your engineering skills&quot;, Kyle replied almost instantly.</p><p>Weird.</p><p>Still, I love helping people so why not trying to jump into it?</p><h3 id="ok-listen-because-i-will-not-repeat"><a href="#ok-listen-because-i-will-not-repeat" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Ok, listen because I will not repeat&quot;</h3><p>Equipped with a pen and a piece of paper, we went into his basement to solve his problem - with reading the measurements of how much energy was produced.</p><p>There was an electric box with a tiny LCD that enabled viewing some information about controller, as well as measurements.</p><div class="flex justify-center items-center flex-col"><div><img class="max-h-[35rem]" src="https://talesfrom.dev/static/images/the-law-of-eventual-composition-electric-box-1.png"/></div><div>An electric box related to solar panels</div></div><p>&quot;Well, what is the problem then?&quot;, I asked myself.</p><p>&quot;Ok, I will read it aloud and you will note it down&quot;, Kyle continued.</p><p>And then he started.</p><h3 id="again"><a href="#again" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Again?&quot;</h3><p>I prepared and waited to get values.</p><p>&quot;35.9, 42.4, 39.7, 12.1, 22.6&quot;, he said.</p><p>I noted everything with a great precision.</p><p>But then I started wondering - &quot;what the hell did I just write down?&quot;</p><p>&quot;Job is done, let&#x27;s go upstairs.&quot;, Kyle stated.</p><p>&quot;Kyle, wait. I don&#x27;t know what I put on the paper. You didn&#x27;t say what are you reading.&quot;, I stopped him with this statement.</p><p>Oh gee, again.</p><p>&quot;I was reading how the consecutive values appear. What&#x27;s the problem?&quot;, he continued.</p><p>&quot;What do they mean? I don&#x27;t know how to label them!&quot;, I almost yelled back.</p><p>&quot;Ah, I see&quot;, Kyle stated.</p><p>Then he started reading the next batch but this time putting the label before giving any number.</p><p>&quot;T 1.8.1 35.9, T 2.8.2 42.4, T 3.1.3 39.7, G 1.1 12.1, G 2.1 22.6&quot;, he said. (those labels and values were different, it does not matter that much)</p><p>&quot;All good. What now?&quot;, I asked.</p><p>&quot;Yeah, now we&#x27;re going back upstairs&quot;, Kyle replied.</p><h3 id="analysis"><a href="#analysis" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Analysis?&quot;</h3><p>As we finished reading measurements, we went back and Kyle pulled a notebook, where he kept all previous measurements.</p><p>We sat behind the table and Kyle transferred the latest measurements into the notebook.</p><p>&quot;Wait, you have previous measurements - so you have been doing what we did today, right?!&quot;, I was amazed while I asked so.</p><p>Kyle looked at me with a humble face, took a deep breath and started opening.</p><p>&quot;Yeah, I collected all of them by myself although I wasn&#x27;t feeling skilled enough to analyze all the results. I also noted past weather measurements like temperature, humidity and if it was a cloudy day back then.&quot;</p><p>&quot;So you didn&#x27;t want me to help you gathering today&#x27;s measurements but rather analyze the results with you?&quot;, I was shocked.</p><p>&quot;Pretty much, yes&quot;, Kyle smiled innocently.</p><p>We took all the data that he collected and we opened Excel to analyze it, together.</p><h3 id="what-will-be-rendered"><a href="#what-will-be-rendered" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What will be rendered?</h3><p>Let&#x27;s change a topic.</p><p>Imagine that we have a React component that is responsible for presenting a bigger piece of UI - couple of buttons, some block of text and some fields (form) - <code>&lt;AddNewDevice /&gt;</code>.</p><p>Because we are decent engineers, we sliced and diced this big thingy into a smaller thingies.</p><p>Inside of this big component, there&#x27;s an icon, telling what type of device the user is currently adding:</p><ul><li>a peripheral device,</li><li>a distributed device,</li><li>or a simulated device.</li></ul><p>Turns out that the logic is quite complex for determining what type of the device we should use and each time we touch related code, specifications for this entire component break down.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token comment">// inside of `&lt;AddNewDevice /&gt;` component specs</span>
</span><span class="code-line"><span class="token function">it</span><span class="token punctuation">(</span><span class="token string">&quot;should render a simulated device icon when a test mode is turned on or a user belongs to support group&quot;</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// correct test here.</span>
</span><span class="code-line"><span class="token punctuation">}</span><span class="token punctuation">)</span>
</span></code></pre></div></div><p>So even though we have a nice piece of React component encapsulating icon presentation, the consumer&#x27;s specification is affected.</p><p>That looks easy fix - let&#x27;s specify how <code>NewDeviceIcon</code> component should behave instead of making specs for the &quot;main&quot; component be responsible for that! (btw. do you remember, dear Reader, that <a href="https://talesfrom.dev/blog/simple-isnt-easy">Simple isn&#x27;t easy</a>?)</p><p>In fact, it&#x27;s just moving the spec from <code>AddNewDevice.spec.tsx</code> to <code>NewDeviceIcon.spec.tsx</code>.</p><p>That was easy.</p><h3 id="new-feature-new-bug"><a href="#new-feature-new-bug" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>New feature, new bug</h3><p>Let&#x27;s imagine that someone else, from the team, jumped into this component to do some new development.</p><p>He was in a bit hurry mode so we didn&#x27;t collaborate on it, so he worked solo.</p><p>Turns out that he took a part of <code>&lt;AddNewDevice /&gt;</code> component and surrounded it with a if statement.</p><p>By the sheer coincidence, he removed usage of <code>NewDeviceIcon</code> from the <code>&lt;AddNewDevice /&gt;</code> component.</p><p>PR, LGTM, CICD, ship it.</p><p>Hello bug my old friend.</p><p>Users reported there&#x27;s no icon when adding a new device.</p><p>We are decent engineers, so we started with a test that would verify the hypothesis.</p><p>But wait, we have the test already, isn&#x27;t it?!</p><p>Yup, it verifies the behavior of <code>NewDeviceIcon</code> but we decomposed the behavior into many components, along with their specs, without covering &quot;if they integrate well with each other&quot;.</p><p>We test if <code>NewDeviceIcon</code> works as it should (and it works), so it must be something with <code>&lt;AddNewDevice /&gt;</code> main component.</p><p>What can we expect from <code>&lt;AddNewDevice /&gt;</code> that is not covered by <code>&lt;NewDeviceIcon /&gt;</code>?</p><p>Let&#x27;s try with a simple thing:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token comment">// inside of `&lt;AddNewDevice /&gt;` component specs</span>
</span><span class="code-line"><span class="token function">it</span><span class="token punctuation">(</span><span class="token string">&quot;should render any new device icon&quot;</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// here we just check if there&#x27;s any icon available</span>
</span><span class="code-line"><span class="token punctuation">}</span><span class="token punctuation">)</span>
</span></code></pre></div></div><p>Of course, the test does not pass. Using <code>&lt;NewDeviceIcon /&gt;</code> in a correct place, inside of <code>&lt;AddNewDevice /&gt;</code> fixes the problem.</p><p>The world is saved.</p><p>Again.</p><h3 id="what-is-the-expected-contract"><a href="#what-is-the-expected-contract" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What is the expected contract?</h3><p>Another topic switch.</p><p>Let&#x27;s imagine we are working with a team mate on building a new feature - as we have web application written in TS with React and API written in TS using express, we need to coordinate.</p><p>We analyze the requirements, define a plan and rush into implementation.</p><p>Web app part is taken by our colleague and we take the backend.</p><p>Hours pass, commit number grows, increments happen.</p><p>Eventually, we are ready to &quot;meet in the middle&quot; and see if everything matches.</p><p>First attempt, fail.</p><p>FAIL - First Attempt In Learning, right?</p><p>Turns out that our team mate assumed that we will return a JSON object (yes, we do REST) having the following structure:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    type<span class="token operator">:</span> <span class="token string">&quot;THIS&quot;</span> <span class="token operator">|</span> <span class="token string">&quot;THAT&quot;</span><span class="token punctuation">,</span>
</span><span class="code-line">    details<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token comment">// only when &quot;type&quot; is &quot;THAT&quot;, if &quot;type&quot; is &quot;THIS&quot; then there should be no details - so empty collection</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Unfortunately, our API returns <code>null</code> when <code>type</code> is <code>THIS</code> and the whole application breaks down with a crappy, broken UI.</p><p>Of course, we fixed it within minutes but we double checked that another endpoint&#x27;s contract is correctly aligned with both sides understanding.</p><p>We saved the world.</p><p>Again.</p><h3 id="why-all-of-that"><a href="#why-all-of-that" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Why all of that?</h3><p>You might wonder, dear Reader: &quot;what the hell has just happened?&quot;</p><p>A mixture of cautionary tales, IT anecdotes and day-to-day struggles - what&#x27;s the point?</p><p>It turns out that all there have something in common.</p><p>In the first one, it turned out that segregting the responsibilities so that one party reads and another one writes require them to agree on the contract.</p><p>Both need to align and understand what they are promising.</p><p>In the second one, even though we made original specifications less brittle, we broke the promise to the end users (by not presenting the icon).</p><p>Finally, in the third one, we divided the work among two people which required them to be in the good dialogue.</p><p>This commonality is <em>the act of decomposition</em>.</p><div class="flex justify-center items-center flex-col"><div><img class="max-h-[65rem]" src="https://talesfrom.dev/static/images/the-law-of-eventual-composition-decomposition.png"/></div><div>The act of decomposition</div></div><p>It does not matter if the reason behind decomposition is hidden agenda (a need to get help with the analysis), managing the complexity, or trying to speed things up when it comes to software development.</p><p>Any time we decompose one thing into smaller ones, one might say we trade one problem to another.</p><div class="flex justify-center items-center flex-col"><div><img class="max-h-[40rem]" src="https://talesfrom.dev/static/images/the-law-of-eventual-composition-composing-decomposed.png"/></div><div>The need for composition</div></div><p>So what is a new problem?</p><p>Now we need to compose those things back.</p><p>Is it really a problem? We got some other qualities back, isn&#x27;t it?</p><p>As we saw in our tiny tales, we need to ensure that decomposed parts are joining forces to provide the behavior we expect.</p><p>This brings other (interesting) challenges, e.g. in terms of satisfying the contract (and notifying about changes).</p><p>But wait, what happens when things are &quot;far from each other&quot;? (we explored this topic too, in <a href="https://talesfrom.dev/blog/modularity-uncertainty-heuristic">Modularity Uncertainty Heuristic</a>)</p><p>It seems as if we need to compose back the capabilities provided by the decomposed parts - even though they might be &quot;physically&quot; separated, the primary behavior, provided before decomposition, needs to be provided by integrating them back.</p><p>As in the scenario with my friend - he was capable of both reading and noting down the measurements.</p><p>He decided to distribute those responsibilities across two actors - me and himself - which required controlling the contract to provide exactly the same outcome as he previously delivered by himself alone.</p><p>(did he assigned responsibilities correctly?)</p><h3 id="the-law-of-eventual-composition"><a href="#the-law-of-eventual-composition" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The law of eventual composition</h3><p>What about a well-recognizable architectural pattern which are microservices?</p><p>We also decompose &quot;stuff&quot;, physically, to achieve certain qualities (hopefully it is done purposefully).</p><p>But as we saw, eventually we need to compose things back (or &quot;integrate&quot; if you wish to use enterprise lingo) and that&#x27;s the place (and time) where dragons live.</p><p>Whether we decompose a role into responsibilities or one giant service into smaller ones - beware the eventual composition!</p><p>One might say: &quot;yeah, it&#x27;s all about coupling, what&#x27;s the point?&quot;.</p><p>Yeah, that sounds reasonable - coupling.</p><p>But wouldn&#x27;t it mean that whenever we decouple something (in order to achieve something else? See <a href="https://talesfrom.dev/blog/the-ambiguity-of-software-architecture">The ambiguity of software architecture</a>) we must follow up with some activity to ensure it provides the same set of functionality as before &quot;decoupling&quot;?</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">The law of eventual composition</div><div class="pb-2 px-3"><div class="break-words"><p>When we decompose something into subparts and distribute responsibilities, we will need to compose back subparts&#x27; responsibilities eventually, so that the original capability is still provided.</p></div></div></div><p>Yeah, it might sound a bit intimidating.</p><p>If we push it through &quot;sloganify&quot; process, it might get distilled version:</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">Slogan version of the law of eventual composition</div><div class="pb-2 px-3"><div class="break-words"><p>Anything decomposed will need to be eventually composed back.</p></div></div></div><p>Obvious obviousness, right?</p><h3 id="you-cant-touch-gravity"><a href="#you-cant-touch-gravity" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>You can&#x27;t touch gravity</h3><p>Even though it might sound anecdotically, like &quot;the iron, when turned on, is hot&quot;, it might help us make some decisions more intentionally.</p><p>Splitting the work among team members, slicing the process into steps, or making two actors collaboratively solve a task - aren&#x27;t they leading to similar problems?</p><p>Of course, now it means we can&#x27;t do anything until we carefully analyze decomposition-composition.</p><p>Not.</p><p>I like to employ this kind of perspective when I am designing something.</p><p>The urge to &quot;slice and dice stuff&quot; is strong but I try (and sometimes fail) to <a href="https://talesfrom.dev/blog/slow-down">Slow down</a>, take some time (and space) to let the boundaries emerge.</p><p>What might be helpful?</p><p>Outside-In TDD might counterbalance that act - decomposing too early.</p><p>Scratchpad-oriented development also might be useful - keeping things together, e.g. in a single file, until they &quot;find their place&quot; (or we feel the pain of cognitive overload).</p><p>Don&#x27;t be afraid to write &quot;ugly things&quot; (isn&#x27;t ugliness in the eye of the beholder?)</p><p>Encapsulation might give us options to reverse our decisions - &quot;what you hide, you can change&quot;.</p><p>Nothing new, one might say.</p><p>Next time, dear Reader, when designing or developing something, try asking yourself a question:</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>What would be needed for decomposed parts to be integrated back, giving the same result as before decomposition?</p></div></div></div>]]></content:encoded>
    <pubDate>Wed, 15 May 2024 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>design thinking</category><category>system thinking</category><category>modeling</category><category>domain-driven design</category><category>patterns</category><category>software architecture</category><category>software design</category><category>interfaces</category><category>responsibilities</category><category>responsibility-driven design</category><category>coding</category><category>encoding</category><category>representation</category><category>laws</category><category>heuristics</category><category>perspectives</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/the-ambiguity-of-code</guid>
    <title>The ambiguity of code</title>
    <link>https://talesfrom.dev/blog/the-ambiguity-of-code</link>
    <description>How do we understand &quot;the code&quot;?</description>
    <content:encoded><![CDATA[<div class="bg-slate-600 rounded-xl "><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Attention!</span></div><div class="pb-2 px-3"><div class="break-words"><p>Dear Reader, for the purpose of this tiny tale, domains and business areas, that were used as examples, I excavated from a nice chat with ChatGPT.</p>
<p>Bear that in mind while reading - I am not an expert in those areas!</p></div></div></div><h3 id="just-code-stuff"><a href="#just-code-stuff" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Just code stuff?</h3><p>Imagine that we were challenged with fixing couple of bugs and adding a new capability to already built system (legacy?) that we weren&#x27;t contributing to before.</p><p>Clothing production - sounds so interesting!</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><span class="italic"><span class="text-[#d783eb]">Scrum master</span>: The architect estimated the work for 8 story points.</span></span><span class="text-white"> </span><span class="text-white"><span class="italic"><span class="text-[#4a60f1]">We</span>: Story points?</span></span><span class="text-white"> </span><span class="text-white"><span class="italic"><span class="text-[#d783eb]">Scrum master</span>: Ah, in T-Shirt sizes it will be L or XL.</span></span><span class="text-white"> </span><span class="text-white"><span class="italic"><span class="text-[#4a60f1]">We</span>: How did he know?</span></span><span class="text-white"> </span><span class="text-white"><span class="italic"><span class="text-[#d783eb]">Scrum master</span>: In his opinion, it was some copy and paste work with minor tweaks. Tickets are well-ellaborated in Jira so they are up for grabs.</span></span></div><p>Some time passed, sprints were not sprints but rather slow walks, and eventually we were diving into the &quot;code&quot;.</p><p>&quot;The code&quot; was having all the required design patterns - there were factories, template methods and various other approaches.</p><p>We tried to hook into some services, adapters, and other cool technical shinies - still it wasn&#x27;t enough.</p><p>While being vastly interesting, turned out that clothing production, as area of human activity, is quite complex too.</p><p>Somehow it wasn&#x27;t that easy to grasp what some part of &quot;the code&quot; do.</p><p>It should supposed to be &quot;just code&quot;, right?</p><h3 id="only-hero-can-save-us"><a href="#only-hero-can-save-us" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Only hero can save us!</h3><p>But imagine we had a great luck - during lunch we chatted with an clothing production expert.</p><p>Jeff, that was his name, knew everything about this business as he worked in this area for almost 30 years.</p><p>Imagine we asked for a 2 hour intro and that&#x27;s what Jeff did - he invited to a room with a whiteboard where all the magic happened.</p><p>Jeff wrote the following:</p><ul><li><code>Textile Manufacturing</code></li><li><code>Pattern Making and Design</code></li><li><code>Garment Construction</code></li><li><code>Quality Control and Assurance</code></li><li><code>Supply Chain Management</code></li><li><code>Sustainable Practices</code></li><li><code>Technology and Innovation</code></li><li><code>Fashion Forecasting and Trends</code></li><li><code>Customization and Personalization</code></li><li><code>E-commerce and Retail</code></li></ul><p>The more we went into the discussion, the more unknown terms and lingo started becoming familiar.</p><p>One of the bugs was related to incorrect mapping of seams and stitches.</p><p>The &quot;aha&quot; moment came.</p><p>&quot;<code>Garment Construction</code>!&quot;, we yelled.</p><p>We scared Jeff a bit but after a while we described our Eureka time.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><span class="italic"><span class="text-[#40d053]">Jeff</span>: By the way, what are other &quot;bugs&quot; you said?</span></span><span class="text-white"> </span><span class="text-white"><span class="italic"><span class="text-[#4a60f1]">We</span>: Something is wrong with &quot;grading rules&quot;.</span></span><span class="text-white"> </span><span class="text-white"><span class="italic"><span class="text-[#40d053]">Jeff</span>: Ah, <code>Pattern Making and Design</code>. That&#x27;s my favorite one. I started my journey as a designer. What&#x27;s wrong with it?</span></span><span class="text-white"> </span><span class="text-white"><span class="italic"><span class="text-[#4a60f1]">We</span>: Turns out that for some customers pattern grading logic is incorrectly working.</span></span><span class="text-white"> </span><span class="text-white"><span class="italic"><span class="text-[#40d053]">Jeff</span>: Sounds like <code>Customization and Personalization</code> problem? I think you should ask Henry, he knows a lot regarding that area.</span></span></div><p>Those were very intense three hours.</p><p>We didn&#x27;t touch &quot;the code&quot;, which feels a bit weird.</p><p>Just talking, we hope no one would accuse us of not wasting time.</p><h3 id="code"><a href="#code" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Code?</h3><p>Somehow when we came back to the screen and keyboard, it wasn&#x27;t perfect but we could relate to the terms and language used in the code.</p><p>Not in all the places &quot;the code&quot; was super &quot;clean&quot; (what does it really mean?), and of course there were moments when we needed to &quot;focus&quot; and understand what part of the given subdomain was supposed to be represented.</p><p>Nevertheless, we found the place where stitches and seams mapping was mainly done.</p><p>It turned out that &quot;it was just a wrong if&quot; - fabrics-related logic had wrong argument passed. The method looked as follows:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>Stitch<span class="token punctuation">&gt;</span></span> <span class="token function">SelectStitchByFabric</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> fabric<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span> <span class="token comment">/*...*/</span> <span class="token punctuation">}</span>
</span></code></pre></div></div><p>Fix itself was very trivial, knowing what subarea of business we work in currently.</p><p>We even consulted Jeff.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><span class="italic"><span class="text-[#4a60f1]">We</span>: Regarding selecting stitch by fabric.</span></span><span class="text-white"> </span><span class="text-white"><span class="italic"><span class="text-[#40d053]">Jeff</span>: Yes?</span></span><span class="text-white"> </span><span class="text-white"><span class="italic"><span class="text-[#4a60f1]">We</span>: Can a fabric be any string?</span></span><span class="text-white"> </span><span class="text-white"><span class="italic"><span class="text-[#40d053]">Jeff</span>: No, no. You do not understand this. The fabric is made of &quot;tiny, thin strings&quot;. If you want to have cotton combined with polyester, you must use such &quot;strings&quot;.</span></span><span class="text-white"> </span><span class="text-white"><span class="italic"><span class="text-[#4a60f1]">We</span>: I was thinking more about how it is represented in the code. How do you represent cotton?</span></span><span class="text-white"> </span><span class="text-white"><span class="italic"><span class="text-[#40d053]">Jeff</span>: Depends on the system, as an example let&#x27;s take <code>COTN#080#B</code> - this means that we&#x27;re dealing with cotton, having thinckness 0.8mm, having density B.</span></span><span class="text-white"> </span><span class="text-white"><span class="italic"><span class="text-[#4a60f1]">We</span>: (...silence...)</span></span></div><p>We got a bit confident with our understanding so we refactored &quot;the code&quot; from:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>Stitch<span class="token punctuation">&gt;</span></span> <span class="token function">SelectStitchByFabric</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> fabric<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span> <span class="token comment">/*...*/</span> <span class="token punctuation">}</span>
</span></code></pre></div></div><p>to:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>Stitch<span class="token punctuation">&gt;</span></span> <span class="token function">SelectStitchByFabric</span><span class="token punctuation">(</span><span class="token class-name">Fabric</span> fabric<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span> <span class="token comment">/*...*/</span> <span class="token punctuation">}</span>
</span></code></pre></div></div><p>From now on, a concept of a <code>Fabric</code> has started to be used by other people too.</p><p>Suddenly, glitches in other parts of the system happened as this little <code>Fabric</code> caused great thread (pun intended) on coding fabrics.</p><p>As for grading rules and customer problems - Jeff was right - it was mainly related to configuration of available grading rules, not applying them.</p><p>As Jeff advised, this time we consulted Henry.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><span class="italic"><span class="text-[#4a60f1]">We</span>: What are the rules for grading logic for some customers?</span></span><span class="text-white"> </span><span class="text-white"><span class="italic"><span class="text-[#ffe749]">Henry</span>: For a platinum customers we offer a default premium grading configuration - they are adjusted based on trends and predictions so they don&#x27;t need to waste time doing it by themselves.</span></span><span class="text-white"> </span><span class="text-white"><span class="italic"><span class="text-[#4a60f1]">We</span>: Trends? Does it mean we need to check with other department?</span></span><span class="text-white"> </span><span class="text-white"><span class="italic"><span class="text-[#ffe749]">Henry</span>: I believe you should ask for premium default configurations, not just default configurations.</span></span><span class="text-white"> </span><span class="text-white"><span class="italic"><span class="text-[#4a60f1]">We</span>: Premium defaults?</span></span><span class="text-white"> </span><span class="text-white"><span class="italic"><span class="text-[#ffe749]">Henry</span>: Didn&#x27;t you know that?</span></span><span class="text-white"> </span><span class="text-white"><span class="italic"><span class="text-[#4a60f1]">We</span>: (...silence...)</span></span></div><p>Grading rules configuration was coded like this:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">record</span> <span class="token class-name">GradingRuleConfiguration</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> Id<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">string</span></span> CustomerId<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">string</span></span> SizePatterns<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">bool</span></span> IsDefault<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">bool</span></span> IsPremium<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre></div></div><p>With usage in a ConfigurationService:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ConfigurationService</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">private</span> <span class="token class-name">GradingRuleConfigurationRepository</span> _rulesRepository<span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token function">ConfigurationService</span><span class="token punctuation">(</span><span class="token class-name">GradingRuleConfigurationRepository</span> rulesRepository<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        _rulesRepository <span class="token operator">=</span> rulesRepository<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">ConfigureGradingRuleConfigurations</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> customerId<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">string</span></span> customerTier<span class="token punctuation">,</span> <span class="token class-name">List<span class="token punctuation">&lt;</span>GradingRuleConfiguration<span class="token punctuation">&gt;</span></span> incomingRules<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> defaults <span class="token operator">=</span> <span class="token keyword">await</span> _rulesRepository<span class="token punctuation">.</span><span class="token function">QueryAsync</span><span class="token punctuation">(</span>rule <span class="token operator">=&gt;</span> rule<span class="token punctuation">.</span>IsDefault<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// ❌ can you see a bug?</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> finalRules <span class="token operator">=</span> incomingRules<span class="token punctuation">.</span><span class="token function">Concat</span><span class="token punctuation">(</span>defaults<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">await</span> _rulesRepository<span class="token punctuation">.</span><span class="token function">UpdateAsync</span><span class="token punctuation">(</span>finalRules<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>We understand the problem now.</p><p>There are defaults and premium defaults.</p><p>The fix is easy now:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ConfigurationService</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">private</span> <span class="token class-name">GradingRuleConfigurationRepository</span> _rulesRepository<span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token function">ConfigurationService</span><span class="token punctuation">(</span><span class="token class-name">GradingRuleConfigurationRepository</span> rulesRepository<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        _rulesRepository <span class="token operator">=</span> rulesRepository<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">ConfigureGradingRuleConfigurations</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> customerId<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">string</span></span> customerTier<span class="token punctuation">,</span> <span class="token class-name">List<span class="token punctuation">&lt;</span>GradingRuleConfiguration<span class="token punctuation">&gt;</span></span> incomingRules<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> defaults <span class="token operator">=</span> <span class="token keyword">await</span> _rulesRepository<span class="token punctuation">.</span><span class="token function">QueryAsync</span><span class="token punctuation">(</span>rule <span class="token operator">=&gt;</span> rule<span class="token punctuation">.</span>IsDefault <span class="token operator">&amp;&amp;</span> rule<span class="token punctuation">.</span>IsPremium<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 👈️ easy fix!</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> finalRules <span class="token operator">=</span> incomingRules<span class="token punctuation">.</span><span class="token function">Concat</span><span class="token punctuation">(</span>defaults<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">await</span> _rulesRepository<span class="token punctuation">.</span><span class="token function">UpdateAsync</span><span class="token punctuation">(</span>finalRules<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Probably it should be enough to close one Jira ticket but we wanted to confirm it with Henry.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><span class="italic"><span class="text-[#4a60f1]">We</span>: Is it ever possible that platinum customers will not get other defaults than premium ones?</span></span><span class="text-white"> </span><span class="text-white"><span class="italic"><span class="text-[#ffe749]">Henry</span>: Platinum customers should always get premium defaults. That&#x27;s the whole point of premium default - they are curated and prepared for platinum customers.</span></span><span class="text-white"> </span><span class="text-white"><span class="italic"><span class="text-[#4a60f1]">We</span>: 👍️</span></span></div><p>It&#x27;s clear - we understood the logic there.</p><p>Code-wise, it was so easy.</p><p>Fix applied, move on, right?</p><p>It&#x27;s very tempting to leave it as it is right now - avoiding &quot;overengineering&quot;.</p><p>But we learned something, didn&#x27;t we?</p><p>At least now we have the understanding that there are platinum customers which always get premium defaults. But when we look at &quot;the code&quot; - this understanding isn&#x27;t there.</p><p>Yeah, the system behaves as expected, but it feels under the skin that something is missing.</p><p>Now we <strong>know</strong> what this code means but what will happen in the future?</p><p>Ok, let&#x27;s <a href="https://talesfrom.dev/blog/slow-down">Slow down</a>.</p><p>Let&#x27;s introduce something that will represent premium default rules:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">record</span> <span class="token class-name">PremiumDefaultGradingRuleConfigurations</span><span class="token punctuation">(</span><span class="token class-name">IReadOnlyList<span class="token punctuation">&lt;</span>GradingRuleConfiguration<span class="token punctuation">&gt;</span></span> Rules<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre></div></div><p>We <strong>know</strong> that when configuring rules for platinum customer, those need to be included in incoming premium rules:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">record</span> <span class="token class-name">IncomingPlatinumGradingRuleConfigurations</span><span class="token punctuation">(</span><span class="token class-name">IReadOnlyList<span class="token punctuation">&lt;</span>GradingRuleConfiguration<span class="token punctuation">&gt;</span></span> Rules<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">PlatinumGradingRuleConfigurations</span> <span class="token function">IncludeDefaultRules</span><span class="token punctuation">(</span><span class="token class-name">PremiumDefaultGradingRuleConfigurations</span> defaults<span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
</span><span class="code-line">        PlatinumGradingRuleConfigurations<span class="token punctuation">.</span><span class="token function">CreateFrom</span><span class="token punctuation">(</span>defaults<span class="token punctuation">.</span>Rules<span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span>Rules<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>So revisting our little service:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ConfigurationService</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">private</span> <span class="token class-name">GradingRuleConfigurationRepository</span> _rulesRepository<span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token function">ConfigurationService</span><span class="token punctuation">(</span><span class="token class-name">GradingRuleConfigurationRepository</span> rulesRepository<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        _rulesRepository <span class="token operator">=</span> rulesRepository<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">ConfigureGradingRuleConfigurations</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> customerId<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">string</span></span> customerTier<span class="token punctuation">,</span> <span class="token class-name">IncomingPlatinumGradingRuleConfigurations</span> incomingRules<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> defaults <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">PremiumDefaultGradingRuleConfigurations</span><span class="token punctuation">(</span><span class="token keyword">await</span> _rulesRepository<span class="token punctuation">.</span><span class="token function">QueryAsync</span><span class="token punctuation">(</span>rule <span class="token operator">=&gt;</span> rule<span class="token punctuation">.</span>IsDefault <span class="token operator">&amp;&amp;</span> rule<span class="token punctuation">.</span>IsPremium<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> finalRules <span class="token operator">=</span> incomingRules<span class="token punctuation">.</span><span class="token function">IncludeDefaultRules</span><span class="token punctuation">(</span>defaults<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">await</span> _rulesRepository<span class="token punctuation">.</span><span class="token function">UpdateAsync</span><span class="token punctuation">(</span>finalRules<span class="token punctuation">.</span><span class="token function">ToList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Yey, it&#x27;s working as previously! (we have tests, right?!).</p><p>But wait, when getting rules using a repository, do we care at this point how they are retrieved?</p><p>Hm, no. We are interested in a specific capability - getting premium defaults.</p><p>We should require &quot;someone&quot; who knows how to provide them.</p><p>Let&#x27;s introduce a responsibility (what do I mean by that? If you&#x27;re curious, please check <a href="https://talesfrom.dev/blog/the-ambiguity-of-interfaces">The ambiguity of interfaces</a>):</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">IProvidePremiumDefaultGradingRuleConfigurations</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>PremiumDefaultGradingRuleConfigurations<span class="token punctuation">&gt;</span></span> <span class="token function">Provide</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Now, time to introduce our new friend:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ConfigurationService</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">private</span> <span class="token class-name">GradingRuleConfigurationRepository</span> _rulesRepository<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">private</span> <span class="token class-name">IProvidePremiumDefaultGradingRuleConfigurations</span> _premiumDefaultGradingRuleConfigurationsProvider<span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token function">ConfigurationService</span><span class="token punctuation">(</span><span class="token class-name">GradingRuleConfigurationRepository</span> rulesRepository<span class="token punctuation">,</span> <span class="token class-name">IProvidePremiumDefaultGradingRuleConfigurations</span> premiumDefaultGradingRuleConfigurationsProvider<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        _rulesRepository <span class="token operator">=</span> rulesRepository<span class="token punctuation">;</span>
</span><span class="code-line">        _premiumDefaultGradingRuleConfigurationsProvider <span class="token operator">=</span> premiumDefaultGradingRuleConfigurationsProvider<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">ConfigureGradingRuleConfigurations</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> customerId<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">string</span></span> customerTier<span class="token punctuation">,</span> <span class="token class-name">IncomingPlatinumGradingRuleConfigurations</span> incomingRules<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token class-name">PremiumDefaultGradingRuleConfigurations</span> defaults <span class="token operator">=</span> <span class="token keyword">await</span> _premiumDefaultGradingRuleConfigurationsProvider<span class="token punctuation">.</span><span class="token function">Provide</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token class-name">PlatinumGradingRuleConfigurations</span> finalRules <span class="token operator">=</span> incomingRules<span class="token punctuation">.</span><span class="token function">IncludeDefaultRules</span><span class="token punctuation">(</span>defaults<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">await</span> _rulesRepository<span class="token punctuation">.</span><span class="token function">UpdateAsync</span><span class="token punctuation">(</span>finalRules<span class="token punctuation">.</span><span class="token function">ToList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>It seems like &quot;the code&quot; expresses our current state of the knowledge about this problem.</p><p>Of course, during the review process, we got &quot;accussed&quot; of overengineering and building citadels of too many classes (or records).</p><p>For sure, there is more code.</p><p>One might say it&#x27;s pointless to be that specific as it might change - then we will have so much work to do!</p><h3 id="what-agile-and-waterfall-have-in-common"><a href="#what-agile-and-waterfall-have-in-common" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What &quot;Agile&quot; and &quot;Waterfall&quot; have in common?</h3><p>&quot;Can&#x27;t you just code stuff?&quot; - have you ever heard something similar, dear Reader?</p><p>&quot;I just want to code stuff&quot; - or this?</p><p>I had this kind of mindset - &quot;a glorified typist&quot;.</p><p>We could put &quot;just coding stuff&quot; in a single axis.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-code-stuff-1.png" class="max-h-[20rem]"/></div><div class="italic mx-24">A spectrum</div></div><p>It forms a spectrum with &quot;Agile&quot;-like and &quot;Big Up Front Design&quot;-like extremas on sides.</p><p>We could highlight &quot;the common&quot; part.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-code-stuff-2.png" class="max-h-[20rem]"/></div></div><h3 id="stuff"><a href="#stuff" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Stuff?</h3><p>I like definitions.</p><p>Not because I can boast during a party, but because I can enrich my understanding by chopping stuff until I find the deeper meaning.</p><p>Let&#x27;s look at the meaning of &quot;code&quot;:</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">a code - definition</div><div class="pb-2 px-3"><div class="break-words"><p>a system of words, letters, figures, or symbols used to <strong>represent</strong> others, especially for the purposes of secrecy.</p></div></div></div><p>According to this definition, it helps <strong>representing</strong> &quot;a thing&quot; by &quot;other things&quot;.</p><p>Of course, it is one of the perspectives that one might have on &quot;the code&quot;.</p><p>It&#x27;s quite typical to say &quot;coding&quot; but it&#x27;s more fun to say &quot;representing a thing by other things&quot;, right?</p><p>Ok, what are those things then?</p><p>During our tiny tale, to complete the bug fixes, we were lacking one precious resource - the knowledge.</p><p>The understanding.</p><p>The context.</p><p>We of course could apply some semi-random moves and apply &quot;fixes&quot;.</p><p>Sometimes there is no other way (due to various reasons).</p><p>But as we saw, meeting Jeff and Henry enabled building the understanding.</p><p>And as you saw, dear Reader, after each fix, we spend some time on &quot;refactoring the code&quot;, right?</p><p>We often hear that term, e.g. when we want to clean thing up after some sketchy work.</p><p>In our tiny tale, we grew our understanding and eventually we decided to <strong>represent that knowledge using code</strong>.</p><p>Sometimes &quot;it&#x27;s just a class&quot; and sometimes it might require introducing much &quot;more code&quot;.</p><h3 id="the-representation-of-knowledge"><a href="#the-representation-of-knowledge" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The representation of knowledge</h3><p>If we get back to our spectrum for a while.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-code-stuff-3.png" class="max-h-[20rem]"/></div></div><p>We were able to represent our understanding of underlying...Yeah, what exactly?</p><p>We had discussions both with Jeff and Henry, which eventually made us aware of certain concepts living in the area of clothing production business.</p><p>Some say those are &quot;just words&quot; or &quot;this is just a language&quot;.</p><p>From one perspective - yeah, that might be true.</p><p>Words and language convey the meaning.</p><p>The meaning carries rules whenever it goes.</p><p>When we don&#x27;t pay enough attention, it might hurt us later.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-code-stuff-4.png" class="max-h-[20rem]"/></div></div><p>The spectrum might indicate that there is no single representation.</p><p>&quot;The code&quot;, &quot;architecture&quot; and similar concepts (from the IT area of human activities) also have the meaning encapsulated (you might be interested in <a href="https://talesfrom.dev/blog/the-ambiguity-of-encapsulation">The ambiguity of encapsulation</a>) and details abstracted away (you might be interested in <a href="https://talesfrom.dev/blog/the-ambiguity-of-abstraction">The ambiguity of abstraction</a>).</p><p>They are (just) representations.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>A code is one of the representations of our understanding of the concepts and ideas living inside of a certain context.</p></div></div></div><h3 id="code-fetish"><a href="#code-fetish" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Code fetish</h3><p>The central part of software engineering work is the activity of coding - using &quot;the code&quot; to represent the understanding we acquired or grew through time about &quot;something&quot;.</p><p>It reminds me the first sentence from the great book, written by Craig Larman, &quot;Applying UML and Patterns&quot; (paraphrasing):</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Programming is fun, but building maintainable software is hard.</p></div></div></div><p>But when taken as a goal itself, one might lose the purpose of using code as a tool for representing the knowledge of a particular problem.</p><p>It is vastly important to know what is the context we operate in and what are problems we are supposed to deal with.</p><p>This whole journey, as we saw in our tiny tale, might lead us <a href="https://talesfrom.dev/blog/from-concepts-to-architecture">From concepts to architecture</a>.</p><p>One could say that we organized the ideas living in the area of clothing production (what do I mean by &quot;organizing&quot;? See <a href="https://talesfrom.dev/blog/the-ambiguity-of-software-architecture">The ambiguity of software architecture</a>).</p><p>When we start representing our understanding, we might eventually land up with much more &quot;things&quot; getting created (e.g. in the form of the code).</p><p>&quot;More code&quot; might look not simple but remember that <a href="https://talesfrom.dev/blog/simple-isnt-easy">Simple isn&#x27;t easy</a>.</p><p>So instead of treating it as a &quot;my code is better than yours&quot; kind of a fetish, we should orient our thinking into &quot;understanding fetish&quot;.</p><p>Breath it.</p><p>Speak it.</p><h3 id="whats-next"><a href="#whats-next" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What&#x27;s next?</h3><p>Of course I am exaggerating a bit when it comes to putting &quot;understanding representation&quot; in the central place.</p><p>We might eventually get onto the right side of the visited spectrum, which might not be the desirable state.</p><p>Next time, dear Reader, when someone says &quot;let&#x27;s jump into coding&quot;, expand details abstracted away with the concept of &quot;coding&quot;, and counter it with &quot;you mean we should jump into representing the understanding of the given problem using code, right?&quot;.</p><p>Fun time ahead!</p><p>It might anchor you back into the question &quot;do we know what we do?&quot; kind of a state.</p><p>Do you have enough understanding?</p><p>Do you know how to represent it?</p><p>What is the representation level we should utilize? (levels? You might be interested in <a href="https://talesfrom.dev/blog/modeling-maturity-levels">Modeling Maturity Levels</a>)</p><p>Nevertheless, everything starts with understanding, not with the representation.</p>]]></content:encoded>
    <pubDate>Sat, 06 Apr 2024 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>paradigms</category><category>design thinking</category><category>modeling</category><category>domain-driven design</category><category>patterns</category><category>knowledge working</category><category>software architecture</category><category>software design</category><category>interfaces</category><category>responsibilities</category><category>responsibility-driven design</category><category>coding</category><category>encoding</category><category>representation</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/the-ambiguity-of-interfaces</guid>
    <title>The ambiguity of interfaces</title>
    <link>https://talesfrom.dev/blog/the-ambiguity-of-interfaces</link>
    <description>How does need-driven thinking shape the way we design?</description>
    <content:encoded><![CDATA[<h3 id="you-had-one-job"><a href="#you-had-one-job" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>You had one job</h3><p>Imagine that we were challenged to implement a new functionality in our application.</p><p>A typical assignment - read some data, make a decision, do some actions, eventually record a decision.</p><p>Turns out that we already have some system up and running.</p><p>Thank God that someone already thought about dependency injection (following the best practices, right?) and we have a bunch of &quot;injectables&quot;.</p><p>We need to compose powers of <code>IApplicationConfigurationService</code>, <code>IDocumentProcessingServiceClient</code> and <code>IDocumentRepository</code>.</p><p>Of course, this is a toy example and we don&#x27;t see such code in real life.</p><p>But please bear with me, dear Reader.</p><p>There will be fun moments, I promise.</p><h3 id="configuration"><a href="#configuration" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Configuration?</h3><p>Let&#x27;s start with our lovely <code>IApplicationConfigurationService</code> collaborator.</p><p>It provides an application configuration based on partner identifier.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">IApplicationConfigurationService</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>ApplicationConfiguration<span class="token punctuation">&gt;</span></span> <span class="token function">Get</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> partnerId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>And here we have configuration:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ApplicationConfiguration</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">ConfigurationA</span> ConfigurationA <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">ConfigurationB</span> ConfigurationB <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">ConfigurationC</span> ConfigurationC <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">ConfigurationD</span> ConfigurationD <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token comment">/* much more configuration */</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ConfigurationD</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">int</span></span> ParameterX <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> ParameterY <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">double</span></span> ParameterZ <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">bool</span></span> UseDocumentProcessing <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Pretty straightforward configuration with many possible knobs for tuning the application.</p><p>We know that the configuration is stored in CosmosDB so we have <code>CosmosDBApplicationConfigurationService</code>.</p><p>Not bad, huh?</p><h3 id="more-processing"><a href="#more-processing" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>More processing?</h3><p>To use additional processing power we are going to utilize a separate document processing API.</p><p>To achieve so we need to have a client, right?</p><p>So <code>IDocumentProcessingServiceClient</code> will be implemented, believe me or not, by <code>DocumentProcessingServiceClient</code>.</p><p>No one would have guessed!</p><p>Here&#x27;s the interface definition:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> IDocumentProcessingServiceClient
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>ImportantDocument<span class="token punctuation">&gt;</span></span> <span class="token function">Process</span><span class="token punctuation">(</span><span class="token class-name">ImportantDocument</span> document<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>You probably can imagine, dear Reader, how the implementation looks like.</p><p>There&#x27;s a <code>HttpClient</code> involved, and some other typical code for interacting with a web API.</p><p>Let&#x27;s move on.</p><h3 id="processing-result"><a href="#processing-result" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Processing result?</h3><p>Time to store result of our processing - a processed document.</p><p>Whatever it means, actually.</p><p>But for our little tale it does not really matter.</p><p>The process level logic is that we need to keep it.</p><p>We use CosmosDB, as one could guess it, so <code>IDocumentRepository</code> will be implemented by <code>CosmosDBDocumentRepository</code>.</p><p>The interface itself, looks as follows:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">IDocumentRepository</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>ImportantDocument<span class="token punctuation">&gt;</span></span> <span class="token function">GetBy</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> partnerId<span class="token punctuation">,</span> <span class="token class-name">Guid</span> importantDocumentId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">Task</span> <span class="token function">Save</span><span class="token punctuation">(</span><span class="token class-name">ImportantDocument</span> importantDocument<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">public</span> Task<span class="token operator">&lt;</span><span class="token class-name return-type">IEnumerable<span class="token punctuation">&lt;</span>ImportantDocument<span class="token punctuation">&gt;</span></span> <span class="token function">GetBrokenImportantDocuments</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> partnerId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">public</span> Task<span class="token operator">&lt;</span><span class="token class-name return-type">IEnumerable<span class="token punctuation">&lt;</span>ImportantDocument<span class="token punctuation">&gt;</span></span> <span class="token function">GetActiveImportantDocuments</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> partnerId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>I leave it to you, dear Reader, to imagine how the implementation might look like.</p><h3 id="important-documents-command-handler"><a href="#important-documents-command-handler" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Important documents command handler</h3><p>We are modern, we use CQRS.</p><p>This means we have our command handler <code>ProcessImportantDocumentCommandHandler</code> that will implement our new feature - store important document with possible additional processing.</p><p>For now, our business logic is choosing whether the processing is needed, based on partner&#x27;s configuration.</p><p>And then store the document.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ProcessImportantDocumentCommandHandler</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token function">ProcessImportantDocumentCommandHandler</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token class-name">IApplicationConfigurationService</span> applicationConfigurationService<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">IDocumentProcessingServiceClient</span> documentProcessingServiceClient<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">IDocumentRepository</span> documentRepository
</span><span class="code-line">    <span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        _applicationConfigurationService <span class="token operator">=</span> applicationConfigurationService<span class="token punctuation">;</span>
</span><span class="code-line">        _documentProcessingServiceClient <span class="token operator">=</span> documentProcessingServiceClient<span class="token punctuation">;</span>
</span><span class="code-line">        _documentRepository <span class="token operator">=</span> documentRepository<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">Handle</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> partnerId<span class="token punctuation">,</span> <span class="token class-name">ImportantDocument</span> importantDocument<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> applicationConfiguration <span class="token operator">=</span> <span class="token keyword">await</span> _applicationConfigurationService<span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span>partnerId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">if</span><span class="token punctuation">(</span>applicationConfiguration<span class="token punctuation">.</span>ConfigurationD<span class="token punctuation">.</span>UseDocumentProcessing<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token class-name"><span class="token keyword">var</span></span> processedImportantDocument <span class="token operator">=</span> <span class="token keyword">await</span> _documentProcessingServiceClient<span class="token punctuation">.</span><span class="token function">Process</span><span class="token punctuation">(</span>importantDocument<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token keyword">await</span> _documentRepository<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>processedImportantDocument<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">        <span class="token keyword">else</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">await</span> _documentRepository<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>importantDocument<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Isn&#x27;t that difficult, right?</p><p>Typical, boring, enterprise level.</p><p>The feature got implemented, everyone is happy.</p><p>So happy.</p><p>Let&#x27;s dance.</p><h3 id="first-change"><a href="#first-change" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>First change</h3><p>Turns out that during one of our team discussions we decided to move <code>UseDocumentProcessing</code> flag from <code>ConfigurationD</code> to <code>ConfigurationA</code>.</p><p>Just because it makes much more sense.</p><p>We learned something new - let&#x27;s do so.</p><p>Easy change.</p><p>Tiny work inside of <code>ApplicationConfiguration</code> class causes change within <code>ProcessImportantDocumentCommandHandler</code>.</p><p>This is expected, as <code>ProcessImportantDocumentCommandHandler</code> depends on the configuration, right?</p><p>But this requires also changing some of the tests (not many, but still).</p><p>Everything adjusted, we are ready to move on.</p><h3 id="second-change"><a href="#second-change" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Second change</h3><p>Due to various reasons, the service for processing important documents needs to be inlined - architects said we too much roundtrips and it is not that hard to integrate Ruby code in C#.</p><p>This simply pays off.</p><p>Hm, but wait.</p><p><code>IDocumentProcessingServiceClient</code> expresses that it is a client for a separate service and now we will inline this responsiblity.</p><p>What this thing will become?</p><p>We could have an implementation, let&#x27;s say <code>InMemoryDocumentProcessingServiceClient</code> but this does not sound well.</p><p>Is this a client?</p><p>We could rename it to <code>InMemoryDocumentProcessingService</code> and it would make sense too, right?</p><p>Of course, then we would need to remove the <code>Client</code> suffix from our lovely interface - <code>IDocumentProcessingServiceClient</code>, so it becomes <code>IDocumentProcessingService</code>.</p><p>Wasn&#x27;t that painful.</p><h3 id="third-change"><a href="#third-change" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Third change</h3><p>Change, change never changes.</p><p>Requirements hit you hard.</p><p>We got feedback that we need to check if an incoming important document does not belong to already active documents.</p><p>We need to alter behavior.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ProcessImportantDocumentCommandHandler</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token function">ProcessImportantDocumentCommandHandler</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token class-name">IApplicationConfigurationService</span> applicationConfigurationService<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">IDocumentProcessingService</span> documentProcessingServiceClient<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">IDocumentRepository</span> documentRepository
</span><span class="code-line">    <span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        _applicationConfigurationService <span class="token operator">=</span> applicationConfigurationService<span class="token punctuation">;</span>
</span><span class="code-line">        _documentProcessingService <span class="token operator">=</span> documentProcessingService<span class="token punctuation">;</span>
</span><span class="code-line">        _documentRepository <span class="token operator">=</span> documentRepository<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">Handle</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> partnerId<span class="token punctuation">,</span> <span class="token class-name">ImportantDocument</span> importantDocument<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> activeImportantDocuments <span class="token operator">=</span> <span class="token keyword">await</span> _documentRepository<span class="token punctuation">.</span><span class="token function">GetActiveImportantDocuments</span><span class="token punctuation">(</span>partnerId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">if</span><span class="token punctuation">(</span>activeImportantDocuments<span class="token punctuation">.</span><span class="token function">Any</span><span class="token punctuation">(</span>activeDocument <span class="token operator">=&gt;</span> activeDocument<span class="token punctuation">.</span>Id <span class="token operator">==</span> importantDocument<span class="token punctuation">.</span>Id<span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">CannotProcessAlreadyActiveDocument</span><span class="token punctuation">(</span>importantDocument<span class="token punctuation">.</span>Id<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> applicationConfiguration <span class="token operator">=</span> <span class="token keyword">await</span> _applicationConfigurationService<span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span>partnerId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">if</span><span class="token punctuation">(</span>applicationConfiguration<span class="token punctuation">.</span>ConfigurationA<span class="token punctuation">.</span>UseDocumentProcessing<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token class-name"><span class="token keyword">var</span></span> processedImportantDocument <span class="token operator">=</span> <span class="token keyword">await</span> _documentProcessingService<span class="token punctuation">.</span><span class="token function">Process</span><span class="token punctuation">(</span>importantDocument<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token keyword">await</span> _documentRepository<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>processedImportantDocument<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">        <span class="token keyword">else</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">await</span> _documentRepository<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>importantDocument<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Simple, transparent and straightforward.</p><p>But here comes the next change.</p><p>Turns out that the information about active important documents will no longer be available in our CosmosDB instance.</p><p>Due to various reasons, active important documents are going to be stored in Azure Blob Storage as blobs.</p><p>Well, it&#x27;s just another...Wait.</p><p>Another what?</p><p>Our implementation of the <code>IDocumentRepository</code> interface is named as <code>CosmosDBDocumentRepository</code>.</p><p>We could just inject <code>AzureBlobStorageClient</code> and replace implementation of the relevant method - <code>GetActiveImportantDocuments</code>.</p><p>Then <code>CosmosDBDocumentRepository</code> wouldn&#x27;t sound well...</p><p>What options do we have?</p><p>Wouldn&#x27;t <code>DocumentRepository</code> be enough? It could accept two dependencies: <code>CosmosClient</code> and <code>AzureTableStorageClient</code>.</p><p>Consumers of <code>DocumentRepository</code> wouldn&#x27;t notice the change of the structure and the behavior is going to be the same.</p><p>Profit?</p><h3 id="have-you-ever-talked-to-a-command-handler"><a href="#have-you-ever-talked-to-a-command-handler" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Have you ever talked to a command handler?</h3><p>Let&#x27;s imagine that we have a quick chat with a command handler.</p><p>Yes.</p><p>Command handler.</p><p>No, I am not kidding.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div><span class="italic mr-2 text-yellow-500">Us:</span><span>Hey!</span></div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic mr-2 text-red-500">ProcessImportantDocumentCommandHandler:</span><span>yo, long time no see.</span></div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic mr-2 text-yellow-500">Us:</span><span>We were wondering about your task.</span></div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic mr-2 text-red-500">ProcessImportantDocumentCommandHandler:</span><span>And?</span></div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic mr-2 text-yellow-500">Us:</span><span>What do you need to get your job done?</span></div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic mr-2 text-red-500">ProcessImportantDocumentCommandHandler:</span><span>Well, I need someone who provides information about all active important docs. Hmmm, someone who can provide information whether additional processing is required. Then of course someone who does the additional processing. And finally, someone who knows how to save a new important document.</span></div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic mr-2 text-yellow-500">Us:</span><span>A tiny question - you said &quot;someone who provides information about all active important docs&quot; - do you really need that much?</span></div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic mr-2 text-red-500">ProcessImportantDocumentCommandHandler:</span><span>When you asked me very explicitly I would say no, I don&#x27;t need that much information. I need someone to check if an incoming important document is already active. That&#x27;s it.</span></div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic mr-2 text-yellow-500">Us:</span><span>Cool, it&#x27;s awesome we could help!</span></div></span></div><p>We got some nice feedback from the command handler.</p><p>We could now try to be explicit in the needs and try to embed each required capability in the form of an interface.</p><p>So <code>ProcessImportantDocumentCommandHandler</code> needs collaborators that can:</p><ul><li>check incoming important document activeness</li><li>check additional processing requirement</li><li>process incoming important document</li><li>save incoming important document.</li></ul><p>One could say that each collaborator will be responsible for each of those capabilities.</p><p>We could name each one a responsibility.</p><p>Let&#x27;s enter playful mood and represent those responsibilities as interfaces.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">ICheckImportantDocumentactiveness</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span><span class="token keyword">bool</span><span class="token punctuation">&gt;</span></span> <span class="token function">IsActive</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> partnerId<span class="token punctuation">,</span> <span class="token class-name">ImportantDocument</span> importantDocument<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">ICheckAdditionalProcessingRequirement</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>booL<span class="token punctuation">&gt;</span></span> <span class="token function">IsRequired</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> partnerId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">IProcessImportantDocument</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">Task</span> <span class="token function">Process</span><span class="token punctuation">(</span><span class="token class-name">ImportantDocument</span> importantDocument<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">ISaveImportantDocument</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">Task</span> <span class="token function">Save</span><span class="token punctuation">(</span><span class="token class-name">ImportantDocument</span> importantDocument<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>They might look a bit weird.</p><p>Verbs in the name - yuck.</p><p>Time to provide those capabilities to our friend, <code>ProcessImportantDocumentCommandHandler</code>.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ProcessImportantDocumentCommandHandler</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token function">ProcessImportantDocumentCommandHandler</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token class-name">ICheckImportantDocumentactiveness</span> importantDocumentactiveness<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">ICheckAdditionalProcessingRequirement</span> additionalProcessingRequirement<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">IProcessImportantDocument</span> importantDocumentAdditionalProcessing<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">ISaveImportantDocument</span> ImportantDocuments
</span><span class="code-line">    <span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        _importantDocumentactiveness <span class="token operator">=</span> importantDocumentactiveness<span class="token punctuation">;</span>
</span><span class="code-line">        _additionalProcessingRequirement <span class="token operator">=</span> additionalProcessingRequirement<span class="token punctuation">;</span>
</span><span class="code-line">        _importantDocumentAdditionalProcessing <span class="token operator">=</span> importantDocumentAdditionalProcessing<span class="token punctuation">;</span>
</span><span class="code-line">        _importantDocuments <span class="token operator">=</span> ImportantDocuments<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">Handle</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> partnerId<span class="token punctuation">,</span> <span class="token class-name">ImportantDocument</span> importantDocument<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token keyword">await</span> _importantDocumentactiveness<span class="token punctuation">.</span><span class="token function">IsActive</span><span class="token punctuation">(</span>importantDocument<span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">CannotProcessAlreadyActiveDocument</span><span class="token punctuation">(</span>importantDocument<span class="token punctuation">.</span>Id<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">        <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token keyword">await</span> _additionalProcessingRequirement<span class="token punctuation">.</span><span class="token function">IsRequired</span><span class="token punctuation">(</span>partnerId<span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token class-name"><span class="token keyword">var</span></span> processedImportantDocument <span class="token operator">=</span> <span class="token keyword">await</span> _importantDocumentAdditionalProcessing<span class="token punctuation">.</span><span class="token function">Process</span><span class="token punctuation">(</span>importantDocument<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token keyword">await</span> _importantDocuments<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>processedImportantDocument<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">        <span class="token keyword">else</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">await</span> _importantDocuments<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>importantDocument<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Not much changes, right?</p><p>Code-wise, it&#x27;s even worse!</p><p>Our fellow handler accepts additional dependency (but let&#x27;s call it a collaborator) so more stuff to mock, right?</p><p>But let&#x27;s look closer.</p><p>In this round, we didn&#x27;t take <strong>our perspective</strong> (God-like creature, looking from &quot;above&quot;) on what the command handler requires to work.</p><p>We asked it explicitly and the handler <strong>expressed it needs</strong> very clearly.</p><p>So we&#x27;ve been able to note down responsibilities of its collaborators to be provided so that it could do its job.</p><p>In fact, who owns the contract for those needed responsibilities? (or should we name them as services?).</p><p>It&#x27;s our handler!</p><p>The command handler is &quot;the service taker&quot; and it expresses the contracts.</p><p><code>ICheckImportantDocumentactiveness</code>, <code>ICheckAdditionalProcessingRequirement</code>, <code>IProcessImportantDocument</code> and <code>ISaveImportantDocument</code> capabilities will be satisfied by someone else, somewhere.</p><p>From handler&#x27;s perspective, it does not matter, as long as service contracts are satisfied!</p><h3 id="service-providers"><a href="#service-providers" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Service providers</h3><p>Turns out that our existing &quot;dependencies&quot; - but let&#x27;s stop naming them as such - they are &quot;living&quot; things - we can talk to them so give them little respect!</p><p>Existing collaborators might play certain roles of services providers and eventually deliver those capabilities.</p><p>How?</p><p>Imagine the following:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> ApplicationConfigurationAdditionalProcessingRequirement <span class="token punctuation">:</span> ICheckAdditionalProcessingRequirement
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token function">ApplicationConfigurationAdditionalProcessingRequirement</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token class-name">ApplicationConfigurationService</span> applicationConfigurationService
</span><span class="code-line">    <span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        _applicationConfigurationService <span class="token operator">=</span> applicationConfigurationService<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span><span class="token keyword">bool</span><span class="token punctuation">&gt;</span></span> <span class="token function">IsRequired</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> partnerId<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> applicationConfiguration <span class="token operator">=</span> <span class="token keyword">await</span> _applicationConfigurationService<span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span>partnerId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">return</span> applicationConfiguration<span class="token punctuation">.</span>ConfigurationA<span class="token punctuation">.</span>UseDocumentProcessing<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Similarily for checking document activeness:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> AzureBlobStorageimportantDocumentactiveness <span class="token punctuation">:</span> ICheckImportantDocumentactiveness
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name">AzureBlobStorageClient</span> _azureBlobStorageClient<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token function">AzureBlobStorageimportantDocumentactiveness</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token class-name">AzureBlobStorageClient</span> azureBlobStorageClient
</span><span class="code-line">    <span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        _azureBlobStorageClient <span class="token operator">=</span> azureBlobStorageClient<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span><span class="token keyword">bool</span><span class="token punctuation">&gt;</span></span> <span class="token function">IsActive</span><span class="token punctuation">(</span><span class="token class-name">ImportantDocument</span> importantDocument<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">/* implementation */</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>What about additional processing?</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">DocumentProcessingWebService</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">IProcessImportantDocument</span></span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name">HttpClient</span> _httpClient<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token function">DocumentProcessingWebService</span><span class="token punctuation">(</span><span class="token class-name">HttpClient</span> httpClient<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        _httpClient <span class="token operator">=</span> httpClient<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">Process</span><span class="token punctuation">(</span><span class="token class-name">ImportantDocument</span> importantDocument<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">/* implementation */</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>We can name the collaborator accordingly, based on the provided capabilities.</p><h3 id="capabilities-responsibilities-and-roles"><a href="#capabilities-responsibilities-and-roles" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Capabilities, responsibilities and roles</h3><p>Isn&#x27;t it that I made some fancy new ways to inject dependencies, breaking the convention of using interfaces?</p><p>Isn&#x27;t it that this tiny toy example allows that and in the big pile of code it won&#x27;t be that easy?</p><p>Might be.</p><p><a href="https://www.amazon.com/Interface-Oriented-Design-Kenneth-Pugh/dp/0976694050">Interface-oriented design</a> might mean something different than using <code>interface</code> keyword.</p><p>It is a mental model, a way of thinking.</p><p>Instead of focusing on &quot;doers&quot; (<code>-ers</code> suffix), we directed our magnifying glass to &quot;capabilities&quot; or simply - &quot;behaviors&quot;.</p><p>At some point &quot;a doer&quot; might and probably should appear. But it does not mean it&#x27;s required from the start.</p><p>As we explored &quot;weird .NET convention&quot; on putting &quot;I&quot;, before each interface&#x27;s name, in <a href="https://talesfrom.dev/blog/i-interface">I, interface</a>, we are able to amplify the essence of each &quot;object&quot; - behavior.</p><p>This might make our thinking oriented towards treating &quot;objects&quot; more like &quot;units of behavior&quot; rather than &quot;bags of data with some methods attached&quot;.</p><p>And that&#x27;s why <code>interface</code> keyword might be really dangerous.</p><p>Why?</p><p>Typically a new interface gets created from God-like perspective - a designer.</p><p>And this comes with a risk, for an interface, getting polluted by this overarching knowledge.</p><p>But wait, what we really want to express through <code>interface</code>?</p><p>An ability to &quot;mock&quot; it later?</p><h3 id="need-driven-design"><a href="#need-driven-design" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Need-driven design</h3><p>Imagine that there&#x27;s a magical language that allows doing this:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token class-name return-type">responsibility</span> ISaveImportantDocument
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">Task</span> <span class="token function">Save</span><span class="token punctuation">(</span><span class="token class-name">ImportantDocument</span> importantDocument<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>As there is a need to save important document, loading might be also relevant:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token class-name return-type">responsibility</span> ILoadImportantDocument
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>Result<span class="token punctuation">&lt;</span>ImportantDocument<span class="token punctuation">,</span> LoadingDocumentError<span class="token punctuation">&gt;</span><span class="token punctuation">&gt;</span></span> <span class="token function">Load</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> partnerId<span class="token punctuation">,</span> <span class="token class-name">Guid</span> documentId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>There are high chances that those capabilities might be assigned to <strong>a specific role</strong>:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token class-name">role</span> ImportantDocumentsRepository
</span><span class="code-line">    <span class="token punctuation">:</span> ISaveImportantDocument<span class="token punctuation">,</span> ILoadImportantDocument
</span><span class="code-line"><span class="token punctuation">{</span><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Everything is living in the conceptual plane and there&#x27;s no such language, of course.</p><p>But no one can stop us, dear Reader, from having different way of thinking about what we do, right?</p><p>Implementation-wise, we would use <code>interface</code>.</p><p>Also, we dropped conventional <code>I</code> prefix for this <code>role</code> description.</p><p>Not having this convention in place might feel weird but there&#x27;s a potential benfit - we would need to name someone who is going to play this role accordingly.</p><p>So instead of having <code>ImportantDocumentsRepository</code> implementing <code>IImportantDocumentsRepository</code>, we would have <code>ImportantDocumentsCosmosDbRepository</code> <strong>playing</strong> a <code>role</code> of <code>ImportantDocumentsRepository</code>.</p><p>Worth noting is that now we are operating on very granular responsibilties when we need to.</p><h3 id="beyond-interfaces"><a href="#beyond-interfaces" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Beyond interfaces</h3><p><code>interface</code> is just a keyword in various languages we use.</p><p>Focusing on behaviors, capabilities, responsibilities and roles, required by a particular services takers, &quot;decouple&quot; service providers, playing those roles, from the context they are acting in.</p><p>This might eventually lead to <strong>more</strong> code.</p><p>Code should serve the purpose and should deserve its existence.</p><p>If it is there <strong>to capture the knowledge</strong>, to enchant the understanding - it&#x27;s totally worth it.</p><p>Even though it initially might remind ourselves about <a href="https://talesfrom.dev/blog/the-cost-of-modeling">The cost of modeling</a>.</p><p>By being very explicit on what is needed by a specific collaborator, we were able to shuffle those responsibilities and assign them differently, without making much changes in &quot;the consumers of these capabilities&quot; (service takers).</p><p>This is one of the positive aspects of &quot;Outside-In approach&quot; - it is &quot;consumer-driven&quot; so we should pay attention to requirements stated by the &quot;service takers&quot;.</p><p>When dealing with <code>interface</code>, we shouldn&#x27;t focus on &quot;object&quot;-side of it.</p><p>Look beyond that, dear Reader, think of the consumers, of the &quot;users&quot; - what do they really need?</p><p>What capabilities they ask for so that they can do their job in the best way?</p><p>Next time, dear Reader, when working with either existing interface or interface to-happen, try to &quot;replace&quot; <code>interface</code> keyword with <code>responsibility</code> or <code>role</code> - how does it sound?</p><p>&quot;By sheer coincidence&quot;, this will make our &quot;interfaces&quot; smaller, much more well-defined, and serve the right purpose - the recipient&#x27;s needs.</p><p>Almost as if we &quot;followed&quot; one of &quot;the principles&quot; - Interface Segregation Principle.</p><p>But not religiously following - knowing what eventually it might yield - a very specific way of thinking!</p><p>And remember, dear Reader - we always can talk to command handlers (and not only to them!), use this great option to learn about their needs.</p><p>It will pay off.</p>]]></content:encoded>
    <pubDate>Sun, 10 Mar 2024 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>paradigms</category><category>design thinking</category><category>modeling</category><category>domain-driven design</category><category>patterns</category><category>knowledge working</category><category>software architecture</category><category>software design</category><category>interfaces</category><category>responsibilities</category><category>responsibility-driven design</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/inverse-bruce-lee-maneuver</guid>
    <title>Inverse Bruce Lee maneuver</title>
    <link>https://talesfrom.dev/blog/inverse-bruce-lee-maneuver</link>
    <description>How many kicks should an engineer know?</description>
    <content:encoded><![CDATA[<h3 id="its-just-a-status"><a href="#its-just-a-status" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;It&#x27;s just a status&quot;</h3><p>Imagine the following scenario - you are exploring a new case in the area of business that you work in.</p><p>It eventually needs to be covered with software and by the premise of Alberto Brandolini&#x27;s ingenious observation - &quot;software development is a learning process; working code is a side-effect&quot; - you need to build your understanding.</p><p>The team stands up and heads to the meeting room with a loooong wall, perfect for Event Storming.</p><p>And then you hear a statement: &quot;Well, isn&#x27;t it just a new status?&quot;.</p><p>Everyone stopped walking and looked like frozen statues.</p><p>&quot;A new status?&quot;, asked someone from the crew.</p><p>Few message exchanges after, you already know how it&#x27;s gonna end - yet another status in the database.</p><p>&quot;That was too easy&quot;, said a senior.</p><p>&quot;I like those easy solutions&quot;, a junior added.</p><h3 id="oh-no-another-status"><a href="#oh-no-another-status" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Oh no, another status?!&quot;</h3><p>Couple of months later you sit in the war room.</p><p>People are nervous because a critical bug stops customers from using the product your team builds.</p><p>The team analyzes status columns - 4 in total.</p><p>&quot;And don&#x27;t forget the flag for completion!&quot;, a senior added.</p><p>&quot;Did you include information from a &#x27;Packages&#x27; column? You need to take count of them into account!&quot;, another senior yelled.</p><p>Eventually, the bug got fixed.</p><p>Turned out that 4 status columns, 3 flag columns (boolean status) and 2 implicit status columns, needed to be synchronized.</p><p>Who&#x27;d have guessed!</p><p>&quot;Maybe we should add another column that will be an outcome of all other statuses? Something like final status?&quot;, a principal engineer added.</p><p>You initially felt it might not be a good idea but it&#x27;s democracy - people voted and new, shiny column <code>FinalStatus</code> landed.</p><h3 id="visitor-you-must-be-kidding"><a href="#visitor-you-must-be-kidding" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Visitor? You must be kidding!&quot;</h3><p>In one assignment you paired with a senior to provide a solution to a problem that characterizes with strong variability on both ends - behaviors and targets of these behaviors.</p><p>At the beginning, there is only one behavior and there are two targets of it.</p><p>You both code it with a simple pattern matching on type - works like a charm.</p><p>In the next sprint, there&#x27;s a new behavior and three targets.</p><p>The service method grows - it looks a bit scary but hey - complexity means that smart people are working here, right?</p><p>In the sprint after, you land with 7 behaviors and at least 10 targets.</p><p>&quot;Maybe we should use a Visitor pattern?&quot;, you suggest gently.</p><p>&quot;No one uses design patterns. They are sooo lame and oldfashioned!&quot;, your companion answers.</p><p>&quot;And additionally, the level of indirection will kill us - it&#x27;s one of the most complex patterns in the wild!&quot;, he added.</p><p>You looked at the service method length and nesting - you need a drink, immediately.</p><h3 id="how-many-kicks-do-you-know"><a href="#how-many-kicks-do-you-know" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>How many kicks do you know?</h3><p>As a child, I heard about Bruce Lee.</p><p>His attitude, teachings and movie roles he played became an inspiration that shaped the way of thinking of young me.</p><p>Bruce has many famous quotes and one of them is the following:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>“I fear not the man who has practiced 10,000 kicks once, but I fear the man who has practiced one kick 10,000 times.”</p></div></div></div><p>My interpretation of it might be similar to yours, dear Reader - it&#x27;s worth to be greatly experienced with a single method, instead just knowing many methods not covered with practice.</p><p>And it makes sense.</p><p>&quot;Single kick fighter&quot;, equipped with countless hours of mastering it, might be a deadly opponent.</p><p>We might find analogies in other contexts too.</p><p>What if, just as a thought experiment, we try to map this quote into software engineering realm and treat it a bit metaphorically?</p><p>With high chances, we could say that a kick might be thought of as a technique one knows.</p><p>Then, a technique might represent a knowledge or an approach in IT context.</p><p>So, how many &quot;kicks&quot; do you know, dear Reader?</p><p>How many of them did you &quot;practice&quot;?</p><p>How many of them are you still &quot;practicing&quot;?</p><p>I know that Bruce Lee mentioned &quot;practice&quot; and it would be hard to practice everything of what we read or know.</p><p>But by reading all the articles about microservices, we don&#x27;t need to &quot;practice them&quot; to figure out that in our 4 person team might not benefit from this deployment architecture.</p><p>One could say that in the knowledge working industries, the awareness of something is a good enough starter.</p><p>Almost like in Matrix, when Morpheus verified Neo&#x27;s &quot;I know karate&quot;, we can analytically &quot;practice&quot; (or &quot;simulate&quot;) the application of a given &quot;kick&quot;.</p><p>It does not translate 1:1 with real practice, of course.</p><p>Nevertheless, should we, IT professionals, practice only a single kick countless times?</p><h3 id="inverse-bruce-lee-maneuver"><a href="#inverse-bruce-lee-maneuver" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Inverse Bruce Lee maneuver</h3><p>I believe it makes sense to broaden our horizon by exploring other methods, techniques or tools.</p><p>We have the possibility to do a small exercise, write a &quot;TODO app&quot; or try to apply the given solution to a toy problem.</p><p>We could have a &quot;100days&quot; approach and test out single &quot;kick&quot;, necessarily followed by reflective time to get the essence - lessons learned.</p><p>Even if it isn&#x27;t a &quot;production grade&quot; experience, pointers to the knowledge are something that we might use quite easily by almost doing what Neo got - &quot;I know karate&quot; kind of experience.</p><p>It will take time, no doubt.</p><p>One could say that as engineers, we should study various &quot;kicks&quot; so that we have the &quot;know-how&quot;.</p><p>It&#x27;s worth having a toolbelt with various appliances and tools hanging, ready to be used.</p><p>That&#x27;s why it&#x27;s so important to read and explore other programming paradigms, other ways of modelling and representing information.</p><p>Hardening the skill of a &quot;single kick&quot; might feel neat but it is all about the knowledge.</p><p>Do you use C# on daily basis? Try out F#.</p><p>Are you F# afficionado? Check Elixir.</p><p>Are you using statuses and booleans in your React app? Read about state machines.</p><p>It might feel like a worthless act of &quot;reading&quot; and not building - but we all need to start somewhere.</p><h3 id="patterns-be-aware-but-beware"><a href="#patterns-be-aware-but-beware" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Patterns: be aware but beware</h3><p>There are recurring tides of &quot;hate&quot; on OOP, FP, DDD, TDD, Design Patterns, UML, put-your-favorite-thing-here, etc.</p><p>It&#x27;s all knowledge.</p><p>I firmly believe that studying all of them might be beneficial for understanding and getting those 10000 kicks that Bruce was mentioning.</p><p>As Gerald Weinberg stated in <a href="https://www.amazon.com/Rethinking-Systems-Analysis-Design-Weinberg/dp/0932633080">Rethinking Systems Analysis &amp; Design</a>:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Study for understanding, not for criticism</p></div></div></div><p>Often, it&#x27;s about patterns - the language we use to communicate, not a particular implementation.</p><p>And &quot;loading&quot; concepts into our heads enables next level thinking about the problem - and the solution.</p><p>Of course, there&#x27;s a trap.</p><p>When one reads about &quot;Aggregate&quot; or &quot;Domain model&quot;, he or she might look for cases to try it out - and we all know that quickly we jump into &quot;when you have a hammer everything looks like a nail&quot; kind of bias.</p><p>So it really makes sense to be aware of the &quot;patterns&quot; or &quot;models&quot; but beware of applying them blindly.</p><p>That&#x27;s the core intention behind designing. As Gerald Weinberg concluded in <a href="https://www.amazon.com/Rethinking-Systems-Analysis-Design-Weinberg/dp/0932633080">Rethinking Systems Analysis &amp; Design</a>:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Learning to design is learning to generate and evaluate models.</p></div></div></div><p>So we, engineers, should be able to use various models - check if they match our needs, evaluate their usefulness and pick the suitable ones.</p><p>To achieve so we have to &quot;know and practice those 10000 kicks&quot;.</p><h3 id="know-how-vs-know-when"><a href="#know-how-vs-know-when" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;know-how&quot; vs &quot;know-when&quot;?</h3><p>So &quot;Inverse Bruce Lee maneuver&quot; should guide us toward being open and exploratory in our efforts.</p><p>We need to have expertise to be productive and have preferred tools - especially when deadlines are tight or the area of problem/business acitivity is not trivial.</p><p>One could say that this might lead to overengineering the solution pretty quickly - and what about underengineering?</p><p>Know your context, the king of kings.</p><p>So it&#x27;s about timing? As in the great quote from Gerald Weinberg&#x27;s <a href="https://www.amazon.com/Rethinking-Systems-Analysis-Design-Weinberg/dp/0932633080">Rethinking Systems Analysis &amp; Design</a>:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>&#x27;The trick to problem solving is not just &quot;know-how&quot; but &quot;know-when&quot;-which let&#x27;s you adapt the solution method to the problem, and vice versa.&#x27;</p></div></div></div><p>So it&#x27;s about <strong>knowing</strong> &quot;patterns&quot; and approaches but also about &quot;evaluating&quot; the situation, the conditions, the driving forces.</p><p>And also about <strong>knowing the timing</strong> of their application.</p><p>It has dual nature though - there is no &quot;know-when&quot; when there is no &quot;know-how&quot;.</p><p>We need to have the knowledge - shallow or not, this opens possibilities for development and further practice.</p><p>Look beyond a single kick, dear Reader.</p><p>Remember that there are punches too.</p><p>And the head is one of the most deadly weapons we have.</p>]]></content:encoded>
    <pubDate>Thu, 29 Feb 2024 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>paradigms</category><category>programming models</category><category>design thinking</category><category>modelling</category><category>domain-driven design</category><category>patterns</category><category>knowledge working</category><category>software architecture</category><category>software design</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/systems-by-with-for-people</guid>
    <title>Systems: by, with, for people</title>
    <link>https://talesfrom.dev/blog/systems-by-with-for-people</link>
    <description>Does a design mean anything without people?</description>
    <content:encoded><![CDATA[<h3 id="system"><a href="#system" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>System?</h3><p>Imagine that you are working on a software product that is supposed to conquer the world with its innovation and ingenious possibilities.</p><p>Maybe such experience is a bread and butter for you, dear Reader, and each day consists of similar feelings.</p><p>We like to dive into details, either technical or &quot;domain&quot; ones.</p><p>It releases dopamine.</p><p>It transfers into &quot;the zone&quot; where we don&#x27;t feel the urge of time.</p><p>But eventually, what is the meaning of this software product?</p><p>Yeah, of course, we can say it must make money (either by saving it due to costs reduction or by increased revenue) through value delivery.</p><p>That&#x27;s just one of the views, isn&#x27;t it?</p><p>We design the product to, actually, why we do so?</p><p>The sooner we realize the answer is <strong>&quot;people&quot;</strong>, the more design forces we might take into account.</p><h3 id="by-people"><a href="#by-people" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>By people</h3><p>Believe me or not, software products are imagined, designed and grown by human beings.</p><p>This means that a system is being produced (please not I do not scope it only to &quot;software&quot; system) in the context of all biases humans are accounted for.</p><p>We might be tired, frustrated, happy and motivated - this all affects the way we do our efforts.</p><p>Either we want it or not, we seem to be far less logical and rational than we think of ourselves.</p><p>Many intelligent and observant people already found out that we suck at complexity exposure, as a whole.</p><p>Hence, we need to put things within imaginary (also known as &quot;logical&quot;) boundaries to manage it - the complexity.</p><p>Of course, it matters, if we do so in order to pump up our ego so that we can think of ourselves as &quot;highly skilled professionals&quot;.</p><p>But let&#x27;s face it - we should look through the utilization and check the benefits that some ways of organizing stuff gives us. (wayf of organizing stuff? you might be interested in <a href="https://talesfrom.dev/blog/the-ambiguity-of-software-architecture">The ambiguity of software architecture</a>)</p><p>We are getting paid thanks to the system that grew - either in experience points or in money.</p><p>Probably, one could imagine that as at least one human being is involved in the process of growing the system - this system carries the echo of its author.</p><p><a href="https://talesfrom.dev/blog/easy-becomes-complex">Easy becomes complex</a> and as an author of a system, you should take care of future yourself and spend time wisely leaving breadcrumbs and tracks on why some things were organized in this way (whether we talk about names of the concepts/abstractions or variety of software components).</p><p>So your design might reinforce, amplify and contribute for better understanding and loading &quot;the model into the head&quot; so that the system can grow more &quot;organically&quot;.</p><p>Certain structures (think of them as &quot;communication structures&quot;) attract certain attributes and qualities, so don&#x27;t be scared by <a href="https://talesfrom.dev/blog/the-cost-of-modeling">the cost of modeling</a>.</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>How are you going to interact with the system?</p></div></div></div><h3 id="with-people"><a href="#with-people" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>With people</h3><p>You probably not work alone, dear Reader.</p><p>There are other IT folks that try to keep the ball running, either by growing the systems from inside or by trying to help from outside - either by operating it or by selling it, or by doing any other activity that makes the system &quot;live&quot;.</p><p>It would be great if all share the understanding about the &quot;whys&quot;, the goals and the limitations of the system.</p><p>&quot;The code&quot; does not solve all problems and sometimes a piece of documentation might be good fit for making other people&#x27;s life easier.</p><p>The perfect match would be if &quot;the code&quot; bakes the documentation, but hey - there&#x27;s no free lunch.</p><p>Sometimes shouting out on your-favorite-communication tool regarding the isse you found makes it easier to bear the harsh part of the system&#x27;s reality.</p><p>It is tough or even impossible to state &quot;the best practices&quot; about keeping other people, involved in working on and with the system, updated with all the nitty-gritties.</p><p>But it&#x27;s worth keeping that in mind constantly - whether you write your class or a new function - there is another human being that will read it and he or she will try to comprehend - &quot;what did the author think?&quot;.</p><p>This does not mean that we can&#x27;t introduce new ways of thinking (= mental models), but at least have the empathy to &quot;warn&quot; fellow team mates about it.</p><p>Have a chat, or discussion, or a zoom call.</p><p>Put things visually.</p><p>Show it and stop making it being invisible.</p><p>This means that how we design the system matters for the people that are impacted by - those who stand in the first, second, third and further lines from the &quot;system&#x27;s center&quot;.</p><p>With all the automation, tooling and fancy stuff one aspect of design does not change - empathy.</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>How other people, that you work with, are going to interact with the system?</p></div></div></div><h3 id="for-people"><a href="#for-people" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>For people</h3><p>Intentially left as a cherry on top of the cake - the end users, the bussines stakeholders.</p><p>People that would eventually benefit from the running system.</p><p>Some human beings had problems that our system is trying to tackle - and yet again, &quot;the code&quot; does not mean to be an answer all the time.</p><p>Sometimes an innovation comes with the process which might be slightly &quot;accelerated&quot; by composing it with software.</p><p>Constantly having this group of people in mind unblocks and gives substantial perspectives on why we are putting some structures in place.</p><p>And this does not mean that everything must be pixel perfect from day 0 - ugly looking page, reducing a customer&#x27;s employee time by days, so that it take hours if not minutes, delivers infinitely more than perfectly organized software components.</p><p>The primary attribute of used software is that it&#x27;s going to be a subject of change.</p><p>And it is going to be used by, wait for it, people.</p><p>Business stakeholders would probably like to feel the confindence while demoing the product.</p><p>And feel pride when selling it to the next customer.</p><p>Getting delightful opinions about the system is also one of the way we might &quot;get paid&quot;.</p><p>Flattering words do not pay bills - of course.</p><p>Still, somehow they strangely attract the money.</p><p>User-centered design shapes the system in the so profound way that none of the dead architecture diagrams would ever do.</p><p>Of course, all the focus and the obssession on the people we deliver software for, shouldn&#x27;t discard the professional attitude toward our work.</p><p>We are hired to use our technical excellence so that &quot;things happen&quot; - but not to satisfy the ego of oneself.</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>How the end users are going to interact with the system?</p></div></div></div><h3 id="communication"><a href="#communication" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Communication</h3><p>Systems we build, grow and operate, are consequences of the communication.</p><p>The communication between the people.</p><p>And with empathy, with egolessness and with psychological safety, it thrives and blooms like a flower.</p><p>Don&#x27;t make other peoples think - here meaning - assume.</p><p>Clarity is what we we all need.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>What do I communicate with this decision or this action?</p></div></div></div>]]></content:encoded>
    <pubDate>Thu, 22 Feb 2024 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>programming</category><category>modularity</category><category>perspectives</category><category>domain-driven design</category><category>systems thinking</category><category>systems</category><category>programming</category><category>design</category><category>human-oriented design</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/psst-wanna-solid-options</guid>
    <title>Psst, wanna solid options?</title>
    <link>https://talesfrom.dev/blog/psst-wanna-solid-options</link>
    <description>Can you design without options?</description>
    <content:encoded><![CDATA[<h3 id="whats-up-boss"><a href="#whats-up-boss" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What&#x27;s up, boss?</h3><p>Imagine that we were challenged by our stakeholders to provide a software solution for ordering process.</p><p>Pretty standard problem in some areas of human activity, one might say.</p><p>Of course, we went through an Event Storming session, identified all the events, established commands - and we understand the entire process.</p><p>Ah, understanding.</p><p>Nothing is better than understanding, even without working software.</p><p>Simply, we nailed it.</p><p>Let&#x27;s add confirming order to our system.</p><p>It&#x27;s pretty straightforward.</p><p>To confirm an order we need to get order identifier and partner details: id and email.</p><p>It is very important that partner identifier has specific structure and email - is just an email.</p><p>When we verified with success that those details are correct, we can retrieve the order and confirm it.</p><p>After that, we can safely send order confirmation email.</p><p>And, it&#x27;s all.</p><p>But hey, we are not paid for mere talking!</p><p>Talking is fun, but coding is funnier, isn&#x27;t it?</p><h3 id="i-say-command-you-say-handler"><a href="#i-say-command-you-say-handler" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>I say command, you say handler</h3><p>Of course, we are using CQRS.</p><p>Let&#x27;s imagine we have the following command and its symmetric handler:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">record</span> <span class="token class-name">ConfirmOrderCommand</span><span class="token punctuation">(</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">string</span></span> OrderId<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">string</span></span> PartnerId<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">string</span></span> PartnerEmail
</span><span class="code-line"><span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">ICommand</span></span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ConfirmOrderCommandHandler</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">ICommandHandler<span class="token punctuation">&lt;</span>ConfirmOrderCommand<span class="token punctuation">&gt;</span></span></span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">private</span> <span class="token class-name">IOrderRepository</span> _orderRepository<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">private</span> <span class="token class-name">ISendEmail</span> _emailSender<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">private</span> <span class="token class-name">IValidator<span class="token punctuation">&lt;</span>ConfirmOrderCommand<span class="token punctuation">&gt;</span></span> _confirmOrderCommandValidator<span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token function">ConfirmOrderCommandHandler</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token class-name">IOrderRepository</span> orderRepository<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">ISendEmail</span> emailSender<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">IValidator<span class="token punctuation">&lt;</span>ConfirmOrderCommand<span class="token punctuation">&gt;</span></span> _confirmOrderCommandValidator
</span><span class="code-line">    <span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        _orderRepository <span class="token operator">=</span> orderRepository<span class="token punctuation">;</span>
</span><span class="code-line">        _emailSender <span class="token operator">=</span> emailSender<span class="token punctuation">;</span>
</span><span class="code-line">        _confirmOrderCommandValidator <span class="token operator">=</span> confirmOrderCommandValidator<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">Handle</span><span class="token punctuation">(</span><span class="token class-name">ConfirmOrderCommand</span> command<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token class-name">ValidationResult</span> result <span class="token operator">=</span> 
</span><span class="code-line">            <span class="token keyword">await</span> _confirmOrderCommandValidator<span class="token punctuation">.</span><span class="token function">ValidateAsync</span><span class="token punctuation">(</span>command<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span>result<span class="token punctuation">.</span>IsValid<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">FailedValidationOf<span class="token punctuation">&lt;</span>ConfirmOrderCommand<span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span>result<span class="token punctuation">.</span>Errors<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token class-name">Order</span> order <span class="token operator">=</span> <span class="token keyword">await</span> _orderRepository<span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span>command<span class="token punctuation">.</span>OrderId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        order<span class="token punctuation">.</span><span class="token function">Confirm</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">await</span> _orderRepository<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>order<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">await</span> _emailSender<span class="token punctuation">.</span><span class="token function">Send</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name constructor-invocation">OrderConfirmationEmail</span><span class="token punctuation">(</span>command<span class="token punctuation">.</span>OrderId<span class="token punctuation">,</span> command<span class="token punctuation">.</span>PartnerId<span class="token punctuation">,</span> command<span class="token punctuation">.</span>PartnerEmail<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Looks like a very solid piece of code.</p><p>Probably most of us, including you, dear Reader, saw this kind of lines, either in tutorials on in your daily codebase.</p><p>Nothing fancy, isn&#x27;t it?</p><p>To complete the picture, here are some &quot;technical&quot; interfaces that someone could wonder about:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">ICommand</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">ICommandHandler<span class="token punctuation">&lt;</span>TCommand<span class="token punctuation">&gt;</span></span> <span class="token keyword">where</span> <span class="token class-name">TCommand</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">ICommand</span></span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name return-type">Task</span> <span class="token function">Handle</span><span class="token punctuation">(</span><span class="token class-name">TCommand</span> command<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">ValidationResult</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name return-type"><span class="token keyword">bool</span></span> IsValid <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token class-name return-type">IEnumerable<span class="token punctuation">&lt;</span><span class="token keyword">string</span><span class="token punctuation">&gt;</span></span> Errors <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">IValidator<span class="token punctuation">&lt;</span>T<span class="token punctuation">&gt;</span></span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>ValidationResult<span class="token punctuation">&gt;</span></span> <span class="token function">ValidateAsync</span><span class="token punctuation">(</span><span class="token class-name">T</span> input<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">FailedValidationOf<span class="token punctuation">&lt;</span>TCommand<span class="token punctuation">&gt;</span></span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">Exception</span></span> <span class="token keyword">where</span> <span class="token class-name">TCommand</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">ICommand</span></span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token function">FailedValidationOf</span><span class="token punctuation">(</span><span class="token class-name">IEnumerable<span class="token punctuation">&lt;</span><span class="token keyword">string</span><span class="token punctuation">&gt;</span></span> errors<span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token keyword">base</span><span class="token punctuation">(</span><span class="token string">&quot;Here&#x27;s some exception aggregating all validation errors&quot;</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span></code></pre></div></div><p>Now everything should be crystal clear.</p><p>Probably hundreds, if not thousands, or even hundreds of thousands of handlers of such structure were written and make money (hopefully) each day.</p><p>Ah, yes, structure.</p><p>Let&#x27;s try to work on the structure but keep behavior the same.</p><p>Sounds like a goal of a process called refactoring, isn&#x27;t it?</p><p>For a while, let&#x27;s imagine we put our curiosity to the highest levels and try to see what concepts we have in our little handler. (concepts? You might be interested in <a href="https://talesfrom.dev/blog/from-concepts-to-architecture">From concepts to architecture</a>)</p><h3 id="validation---valid-or-invalid-idea"><a href="#validation---valid-or-invalid-idea" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Validation - valid or invalid idea?</h3><p><a href="https://blog.ploeh.dk/2020/12/14/validation-a-solved-problem/">Validation looks like a solved problem</a> and probably is.</p><p>But validation, especially in IT or programming tribes, has a very special meaning.</p><p>In real life, when humans deal with &quot;invalid&quot; information, they actually don&#x27;t use any kind of statuses or boolean flags.</p><p>Code-wise, those are pretty standard and often happening constructs - what&#x27;s more, they are useful too!</p><p>But <a href="https://talesfrom.dev/blog/bool-considered-harmful">can bool be considered harmful?</a> I mean on the conceptual plane.</p><p>When we actually try to inspect ideas, explore them and understand how they work.</p><p>Let&#x27;s try to apply this kind of thinking on our tiny example - will it change the structure?</p><p>Ok, back to the code.</p><p>Our handler - it accepts <code>ConfirmOrderCommand</code> which later requires validation - this responsibility got assigned to <code>IValidator</code>.</p><p><code>IValidator</code> looks like a pretty technical construct.</p><p>I know we are pretty familiar with it and it does not look suspiciously.</p><p>&quot;It does the job&quot;, one might say.</p><p>Yes, that&#x27;s true - no doubts.</p><p>Again, let&#x27;s enter this playful mode.</p><p>Of course, none of the stakeholders told us anything about <code>IValidator</code> but as DDD experts we still need to be pragmatic - and require our code (and handlers) doing the job.</p><h3 id="alwayssometimes-valid-domain-model"><a href="#alwayssometimes-valid-domain-model" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Always...Sometimes valid domain model</h3><p>There&#x27;s a concept of &quot;always valid domain model&quot; - it basically means that when a thing gets created it must be in correct, coherent state so that others, when collaborating with it, won&#x27;t act and play defensively.</p><p>In our scenario its quite opposite.</p><p>From the command handler&#x27;s perspective, the responsibility for ensuring that its dealing with valid model remains in its hands.</p><p>Additionally, the concept of validation is imperatively stated inside this handler.</p><p>Could we act differently?</p><p>Imagine we talk to our command handler (YES! Aren&#x27;t you talking to your code? If your curious, please look at <a href="https://talesfrom.dev/blog/conversation-driven-design">Conversation-Driven Design</a>):</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div><span class="italic mr-2">Us:</span><span>Hey!</span></div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic mr-2 text-red-500">ConfirmOrderCommandHandler:</span><span>Hey, what&#x27;s up?</span></div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic mr-2">Us:</span><span>Why are you checking that incoming command is valid?</span></div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic mr-2 text-red-500">ConfirmOrderCommandHandler:</span><span>You know, all those commands these days...They don&#x27;t communicate if they are valid - we, poor handlers, need to do this duty which might not be in our hands, to be honest...</span></div></span></div><p>What if, just if, command handlers didn&#x27;t want to do this job?</p><p>Should we directly express in the code the concept of valid domain model?</p><p>Of course, it might incurr <a href="https://talesfrom.dev/blog/the-cost-of-modeling">The cost of modeling</a>, but hey, we are playing right now.</p><p>One might also say &quot;Domain model? Damian, it&#x27;s just validation!&quot;.</p><p>Fellow human beings know the idea of information integrity.</p><p>Unspoken ideas are as good as spoken ones.</p><p>Expressing them explicitly might make our thinking much clearer too!</p><h3 id="self-validating-concept"><a href="#self-validating-concept" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Self validating concept?</h3><p>Ok, let&#x27;s do a silly move.</p><p>Let&#x27;s make our command validating itself.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">record</span> <span class="token class-name">ConfirmOrderCommand</span><span class="token punctuation">(</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">string</span></span> OrderId<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">string</span></span> PartnerId<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">string</span></span> PartnerEmail
</span><span class="code-line"><span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">ICommand</span></span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">Task</span> <span class="token function">ValidateUsing</span><span class="token punctuation">(</span><span class="token class-name">IValidator<span class="token punctuation">&lt;</span>ConfirmOrderCommand<span class="token punctuation">&gt;</span></span> validator<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token class-name">ValidationResult</span> result <span class="token operator">=</span> 
</span><span class="code-line">            <span class="token keyword">await</span> _confirmOrderCommandValidator<span class="token punctuation">.</span><span class="token function">ValidateAsync</span><span class="token punctuation">(</span>command<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span>result<span class="token punctuation">.</span>IsValid<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">FailedValidationOf<span class="token punctuation">&lt;</span>ConfirmOrderCommand<span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span>result<span class="token punctuation">.</span>Errors<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token punctuation">}</span> 
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Then our handler gets a bit leaner.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ConfirmOrderCommandHandler</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">ICommandHandler<span class="token punctuation">&lt;</span>ConfirmOrderCommand<span class="token punctuation">&gt;</span></span></span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">private</span> <span class="token class-name">IOrderRepository</span> _orderRepository<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">private</span> <span class="token class-name">ISendEmail</span> _emailSender<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">private</span> <span class="token class-name">IValidator<span class="token punctuation">&lt;</span>ConfirmOrderCommand<span class="token punctuation">&gt;</span></span> _confirmOrderCommandValidator<span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token function">ConfirmOrderCommandHandler</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token class-name">IOrderRepository</span> orderRepository<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">ISendEmail</span> emailSender<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">IValidator<span class="token punctuation">&lt;</span>ConfirmOrderCommand<span class="token punctuation">&gt;</span></span> _confirmOrderCommandValidator
</span><span class="code-line">    <span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        _orderRepository <span class="token operator">=</span> orderRepository<span class="token punctuation">;</span>
</span><span class="code-line">        _emailSender <span class="token operator">=</span> emailSender<span class="token punctuation">;</span>
</span><span class="code-line">        _confirmOrderCommandValidator <span class="token operator">=</span> confirmOrderCommandValidator<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">Handle</span><span class="token punctuation">(</span><span class="token class-name">ConfirmOrderCommand</span> command<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">await</span> command<span class="token punctuation">.</span><span class="token function">ValidateUsing</span><span class="token punctuation">(</span>_confirmOrderCommandValidator<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token class-name">Order</span> order <span class="token operator">=</span> <span class="token keyword">await</span> _orderRepository<span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span>command<span class="token punctuation">.</span>OrderId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        order<span class="token punctuation">.</span><span class="token function">Confirm</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">await</span> _orderRepository<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>order<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">await</span> _emailSender<span class="token punctuation">.</span><span class="token function">Send</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name constructor-invocation">OrderConfirmationEmail</span><span class="token punctuation">(</span>command<span class="token punctuation">.</span>OrderId<span class="token punctuation">,</span> command<span class="token punctuation">.</span>PartnerId<span class="token punctuation">,</span> command<span class="token punctuation">.</span>PartnerEmail<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Now, there&#x27;s no if.</p><p>At least from the command handler perspective.</p><p>Still, it needs to tell <code>ConfirmOrderCommand</code> to validate itself.</p><p>Some might say that no one, especially nowadays, complicates code that much.</p><p>In the previous version, everything was visible and explicit - now, it&#x27;s hidden, convoluted and nothing is straightforward.</p><p>Ok, let&#x27;s try to put emotions aside and ask ourselves - what attributes does our alternative yield?</p><p>From the command handler perspective, less code to inspect and browse (inside).</p><p>In case of testing this handler, nothing really - still we need to control the <code>IValidator</code>.</p><p>Cognitively, current alternative abstracted away some details - which might be viewed as a nice thing (I like abstracting the details, what about you, dear Reader? Btw. you might be interested in <a href="https://talesfrom.dev/blog/the-ambiguity-of-abstraction">The ambiguity of abstraction</a>)</p><p>What other attributes are conjured through using this solution, dear Reader?</p><p>Could we do something else?</p><h3 id="create-not-validate"><a href="#create-not-validate" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Create, not validate?</h3><p>Ok, let&#x27;s do some blasphemy here.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">record</span> <span class="token class-name">ConfirmOrderCommand</span><span class="token punctuation">(</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">string</span></span> OrderId<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">string</span></span> PartnerId<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">string</span></span> PartnerEmail
</span><span class="code-line"><span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">ICommand</span></span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>ConfirmOrderCommand<span class="token punctuation">&gt;</span></span> <span class="token function">ValidateUsing</span><span class="token punctuation">(</span><span class="token class-name">IValidator<span class="token punctuation">&lt;</span>ConfirmOrderCommand<span class="token punctuation">&gt;</span></span> validator<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token class-name">ValidationResult</span> result <span class="token operator">=</span> <span class="token keyword">await</span> _confirmOrderCommandValidator<span class="token punctuation">.</span><span class="token function">ValidateAsync</span><span class="token punctuation">(</span>command<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span>result<span class="token punctuation">.</span>IsValid<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">FailedValidationOf<span class="token punctuation">&lt;</span>ConfirmOrderCommand<span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span>result<span class="token punctuation">.</span>Errors<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span> 
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Our <code>ConfirmOrderCommand</code>, after validating itself, returns itself.</p><p>Crazy, isn&#x27;t it?</p><p>Well, validation should not return anything except the result of validation, right?</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ConfirmOrderCommandHandler</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">ICommandHandler<span class="token punctuation">&lt;</span>ConfirmOrderCommand<span class="token punctuation">&gt;</span></span></span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">private</span> <span class="token class-name">IOrderRepository</span> _orderRepository<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">private</span> <span class="token class-name">ISendEmail</span> _emailSender<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">private</span> <span class="token class-name">IValidator<span class="token punctuation">&lt;</span>ConfirmOrderCommand<span class="token punctuation">&gt;</span></span> _confirmOrderCommandValidator<span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token function">ConfirmOrderCommandHandler</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token class-name">IOrderRepository</span> orderRepository<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">ISendEmail</span> emailSender<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">IValidator<span class="token punctuation">&lt;</span>ConfirmOrderCommand<span class="token punctuation">&gt;</span></span> _confirmOrderCommandValidator
</span><span class="code-line">    <span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        _orderRepository <span class="token operator">=</span> orderRepository<span class="token punctuation">;</span>
</span><span class="code-line">        _emailSender <span class="token operator">=</span> emailSender<span class="token punctuation">;</span>
</span><span class="code-line">        _confirmOrderCommandValidator <span class="token operator">=</span> confirmOrderCommandValidator<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">Handle</span><span class="token punctuation">(</span><span class="token class-name">ConfirmOrderCommand</span> command<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token class-name">ConfirmOrderCommand</span> validConfirmOrderCommand <span class="token operator">=</span>
</span><span class="code-line">            <span class="token keyword">await</span> command<span class="token punctuation">.</span><span class="token function">ValidateUsing</span><span class="token punctuation">(</span>_confirmOrderCommandValidator<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token class-name">Order</span> order <span class="token operator">=</span> <span class="token keyword">await</span> _orderRepository<span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span>validConfirmOrderCommand<span class="token punctuation">.</span>OrderId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        order<span class="token punctuation">.</span><span class="token function">Confirm</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">await</span> _orderRepository<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>order<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">await</span> _emailSender<span class="token punctuation">.</span><span class="token function">Send</span><span class="token punctuation">(</span>
</span><span class="code-line">            <span class="token keyword">new</span> <span class="token class-name constructor-invocation">OrderConfirmationEmail</span><span class="token punctuation">(</span>
</span><span class="code-line">                validConfirmOrderCommand<span class="token punctuation">.</span>OrderId<span class="token punctuation">,</span>
</span><span class="code-line">                validConfirmOrderCommand<span class="token punctuation">.</span>PartnerId<span class="token punctuation">,</span>
</span><span class="code-line">                validConfirmOrderCommand<span class="token punctuation">.</span>PartnerEmail
</span><span class="code-line">                <span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>We know, because we are god-like creatures in this little world we&#x27;re now creating, that <code>CreateUsing</code> throws exception, so we can safely call the outcome of this action as <code>validConfirmOrderCommand</code>.</p><p>It&#x27;s a bit odd that an object of a given type returns exactly the same type.</p><p>What qualities does the current setup give?</p><p>It might look unreadable, leading to worse maintainability.</p><p>Probably, such construct might look unfamiliar to most of our colleagues.</p><p>This act of creating a new command out of previous command expresses something.</p><p>We can use informal notation of arrows and names of types to show steps in this little process:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="code-highlight"><span class="code-line">ValidateUsing = ConfirmOrderCommand -&gt; IValidator&lt;ConfirmOrderCommand&gt; -&gt; ConfirmOrderCommand
</span></code></pre></div></div><p>No information about the exception being thrown, but let&#x27;s forget for a while about it.</p><p>Reading it aloud, one might hear: &quot;<code>ValidateUsing</code> is a process that uses <code>ConfirmOrderCommand</code> and uses <code>IValidator</code> of <code>ConfirmOrderCommand</code> and gives <code>ConfirmOrderCommand</code> back.&quot;</p><p>Can&#x27;t we say, dear Reader, that the effect of applying <code>ValidateUsing</code> to <code>ConfirmOrderCommand</code> is that we know it is valid?</p><p>It <strong>is</strong> valid.</p><p>Before it wasn&#x27;t, but now it is.</p><p>Magic?</p><p>Or maybe, there&#x27;s unspoken, unrevealed concept that is missing?</p><p>Let&#x27;s express it clearly!</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">record</span> <span class="token class-name">ValidatedConfirmOrderCommand</span><span class="token punctuation">(</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">string</span></span> OrderId<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">string</span></span> PartnerId<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">string</span></span> PartnerEmail
</span><span class="code-line"><span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">ICommand</span></span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">record</span> <span class="token class-name">ValidatedConfirmOrderCommand</span><span class="token punctuation">(</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">string</span></span> OrderId<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">string</span></span> PartnerId<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">string</span></span> PartnerEmail
</span><span class="code-line"><span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">ICommand</span></span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>ValidatedConfirmOrderCommand<span class="token punctuation">&gt;</span></span> <span class="token function">CreateFrom</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token class-name">UnvalidatedConfirmOrderCommand</span> command<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">IValidator<span class="token punctuation">&lt;</span>UnvalidatedConfirmOrderCommand<span class="token punctuation">&gt;</span></span> @<span class="token keyword">using</span>
</span><span class="code-line">    <span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token class-name">ValidationResult</span> result <span class="token operator">=</span> <span class="token keyword">await</span> @<span class="token keyword">using</span><span class="token punctuation">.</span><span class="token function">ValidateAsync</span><span class="token punctuation">(</span>command<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span>result<span class="token punctuation">.</span>IsValid<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">FailedValidationOf<span class="token punctuation">&lt;</span>UnvalidatedConfirmOrderCommand<span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span>result<span class="token punctuation">.</span>Errors<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">ValidatedConfirmOrderCommand</span><span class="token punctuation">(</span>command<span class="token punctuation">.</span>OrderId<span class="token punctuation">,</span> command<span class="token punctuation">.</span>PartnerId<span class="token punctuation">,</span> command<span class="token punctuation">.</span>PartnerEmail<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span> 
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>First thing, we changed <code>ValidateUsing</code> to <code>CreateFrom</code>.</p><p>Why?</p><p>Now we are dealing with two concepts: <code>UnvalidatedConfirmOrderCommand</code> and <code>ValidatedConfirmOrderCommand</code>.</p><p>Our process transforms one into another.</p><p>We might say that &quot;<code>UnvalidatedConfirmOrderCommand</code> becomes <code>ValidatedConfirmOrderCommand</code>&quot;. (you might be interested in <a href="https://talesfrom.dev/blog/modeling-maturity-levels">Modeling Maturity Levels</a>)</p><p>How does it affect the handler?</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ConfirmOrderCommandHandler</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">ICommandHandler<span class="token punctuation">&lt;</span>UnvalidatedConfirmOrderCommand<span class="token punctuation">&gt;</span></span></span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">private</span> <span class="token class-name">IOrderRepository</span> _orderRepository<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">private</span> <span class="token class-name">ISendEmail</span> _emailSender<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">private</span> <span class="token class-name">IValidator<span class="token punctuation">&lt;</span>UnvalidatedConfirmOrderCommand<span class="token punctuation">&gt;</span></span> _confirmOrderCommandValidator<span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token function">ConfirmOrderCommandHandler</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token class-name">IOrderRepository</span> orderRepository<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">ISendEmail</span> emailSender<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">IValidator<span class="token punctuation">&lt;</span>UnvalidatedConfirmOrderCommand<span class="token punctuation">&gt;</span></span> _confirmOrderCommandValidator
</span><span class="code-line">    <span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        _orderRepository <span class="token operator">=</span> orderRepository<span class="token punctuation">;</span>
</span><span class="code-line">        _emailSender <span class="token operator">=</span> emailSender<span class="token punctuation">;</span>
</span><span class="code-line">        _confirmOrderCommandValidator <span class="token operator">=</span> confirmOrderCommandValidator<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">Handle</span><span class="token punctuation">(</span><span class="token class-name">UnvalidatedConfirmOrderCommand</span> command<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token class-name">ValidatedConfirmOrderCommand</span> validConfirmOrderCommand <span class="token operator">=</span>
</span><span class="code-line">            <span class="token keyword">await</span> ValidatedConfirmOrderCommand
</span><span class="code-line">                <span class="token punctuation">.</span><span class="token function">CreateFrom</span><span class="token punctuation">(</span>command<span class="token punctuation">,</span> @<span class="token keyword">using</span><span class="token punctuation">:</span> _confirmOrderCommandValidator<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token class-name">Order</span> order <span class="token operator">=</span> <span class="token keyword">await</span> _orderRepository<span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span>validConfirmOrderCommand<span class="token punctuation">.</span>OrderId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        order<span class="token punctuation">.</span><span class="token function">Confirm</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">await</span> _orderRepository<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>order<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">await</span> _emailSender<span class="token punctuation">.</span><span class="token function">Send</span><span class="token punctuation">(</span>
</span><span class="code-line">            <span class="token keyword">new</span> <span class="token class-name constructor-invocation">OrderConfirmationEmail</span><span class="token punctuation">(</span>
</span><span class="code-line">                validConfirmOrderCommand<span class="token punctuation">.</span>OrderId<span class="token punctuation">,</span>
</span><span class="code-line">                validConfirmOrderCommand<span class="token punctuation">.</span>PartnerId<span class="token punctuation">,</span>
</span><span class="code-line">                validConfirmOrderCommand<span class="token punctuation">.</span>PartnerEmail
</span><span class="code-line">                <span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Well, our handler explicitly collaborates with <code>ValidatedConfirmOrderCommand</code> to create it from incoming unvalidated command and using <code>IValidator</code>.</p><p>Also, the handler accepts <code>UnvalidatedConfirmOrderCommand</code> instead of <code>ConfirmOrderCommand</code> - this concept kind of disappeared and turned into two, separate ones.</p><p>What qualities did we get by doing so?</p><p>One might say we are too expressive and we wrote even more code and achieved little, when it comes to behavior.</p><p>If someone looked from outside, well - handler does exactly the same but now works with <code>UnvalidatedConfirmOrderCommand</code> and still has the responsibilty for do something with it.</p><p>Wait, wait.</p><p>Let&#x27;s ask our command handler about one thing.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><div><span class="italic mr-2">Us:</span><span>Wouldn&#x27;t it be better if you dealt with an already valid command?</span></div></span><span class="text-white"> </span><span class="text-white"><div><span class="italic mr-2 text-red-500">ConfirmOrderCommandHandler:</span><span>Are you serious? I am waiting entire life for that moment...</span></div></span></div><p>When our handler requires an outside collaborator to provide an already valid command, it stops being concerned about validation!</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ConfirmOrderCommandHandler</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">ICommandHandler<span class="token punctuation">&lt;</span>ValidatedConfirmOrderCommand<span class="token punctuation">&gt;</span></span></span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">private</span> <span class="token class-name">IOrderRepository</span> _orderRepository<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">private</span> <span class="token class-name">ISendEmail</span> _emailSender<span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token function">ConfirmOrderCommandHandler</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token class-name">IOrderRepository</span> orderRepository<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">ISendEmail</span> emailSender<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        _orderRepository <span class="token operator">=</span> orderRepository<span class="token punctuation">;</span>
</span><span class="code-line">        _emailSender <span class="token operator">=</span> emailSender<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">Handle</span><span class="token punctuation">(</span><span class="token class-name">ValidatedConfirmOrderCommand</span> validConfirmOrderCommand<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token class-name">Order</span> order <span class="token operator">=</span> <span class="token keyword">await</span> _orderRepository<span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span>validConfirmOrderCommand<span class="token punctuation">.</span>OrderId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        order<span class="token punctuation">.</span><span class="token function">Confirm</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">await</span> _orderRepository<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>order<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">await</span> _emailSender<span class="token punctuation">.</span><span class="token function">Send</span><span class="token punctuation">(</span>
</span><span class="code-line">            <span class="token keyword">new</span> <span class="token class-name constructor-invocation">OrderConfirmationEmail</span><span class="token punctuation">(</span>
</span><span class="code-line">                validConfirmOrderCommand<span class="token punctuation">.</span>OrderId<span class="token punctuation">,</span>
</span><span class="code-line">                validConfirmOrderCommand<span class="token punctuation">.</span>PartnerId<span class="token punctuation">,</span>
</span><span class="code-line">                validConfirmOrderCommand<span class="token punctuation">.</span>PartnerEmail
</span><span class="code-line">                <span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>It got leaner - less code in <code>Handle</code> method and we decreased the number of collaborators to two - no need to work with <code>IValidator</code>!</p><p>What are the pros and cons of such alternative?</p><p>In case of writing tests for handler&#x27;s behavior, we don&#x27;t need to have those cases when validation is unsuccessful.</p><p>Also, our handler does not change when anything regarding validation changes.</p><p>Could we say it got decoupled from validation process?</p><p>But is it all butter and flowers?</p><p>Nope, unfortunately by decoupling the handler from validation, we decreased understandability.</p><p>We might have raised readability because its cleaner (less too read) and very explicit that validation already took place.</p><p>It might not be that familiar (depending on the culture, tribe and so on) but hey, we are playing.</p><p>About validation, where should we move it?</p><h3 id="a-new-place"><a href="#a-new-place" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>A new place</h3><p>If we think in terms of layers, the next &quot;upper&quot; layer is controller - another type of handler - http request handlers category.</p><p>It is an option, probably a good one as we have entire structure prepared and it won&#x27;t be a problem to inject <code>IValidator&lt;UnvalidatedConfirmOrderCommand&gt;</code> and move the validation responsiblity onto the http request handler.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line">app<span class="token punctuation">.</span><span class="token function">MapPost</span><span class="token punctuation">(</span><span class="token string">&quot;/orders/{orderId}/confirm/by-partner/{partnerId}&quot;</span><span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token keyword">async</span> <span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">FromServices</span></span><span class="token punctuation">]</span> <span class="token class-name">IValidator<span class="token punctuation">&lt;</span>UnvalidatedConfirmOrderCommand<span class="token punctuation">&gt;</span></span> validator<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">FromServices</span></span><span class="token punctuation">]</span> <span class="token class-name">IDispatchCommands</span> dispatcher<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">string</span></span> orderId<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">string</span></span> partnerId<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">FromQuery</span></span><span class="token punctuation">]</span> <span class="token class-name"><span class="token keyword">string</span></span> partnerEmail
</span><span class="code-line">    <span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">await</span> dispatcher<span class="token punctuation">.</span><span class="token function">Send</span><span class="token punctuation">(</span>
</span><span class="code-line">            <span class="token keyword">await</span> ValidatedConfirmOrderCommand<span class="token punctuation">.</span><span class="token function">CreateFrom</span><span class="token punctuation">(</span>
</span><span class="code-line">                <span class="token keyword">new</span> <span class="token class-name constructor-invocation">UnvalidatedConfirmOrderCommand</span><span class="token punctuation">(</span>orderId<span class="token punctuation">,</span> partnerId<span class="token punctuation">,</span> partnerEmail<span class="token punctuation">)</span><span class="token punctuation">,</span>
</span><span class="code-line">                @<span class="token keyword">using</span><span class="token punctuation">:</span> validator
</span><span class="code-line">            <span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">)</span>
</span></code></pre></div></div><p>Does not look fancy.</p><p>We shuffled it a bit but now everything works!</p><p>The command handler is free from validation concern, we express the language and concepts in the more precise way.</p><p>But what about qualities?</p><p>What problems do you foresee, dear Reader?</p><p>HTTP request handler, knows how to perform validation.</p><p>It stopped being a mere router but a collaborator that takes part in validation and dispatching a command somewhere else.</p><p>Can we do something else?</p><h3 id="going-one-level-down-again"><a href="#going-one-level-down-again" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Going one level down, again</h3><p>Should we try with yet another handler that will work with <code>UnvalidatedConfirmOrderCommand</code>?</p><p>Its main responsibility will be, no shock please, validation.</p><p>Yes.</p><p>I know that no one writes production code like that and my overengineering skills are boiling your brain, dear Reader, but hey, it&#x27;s my blog and I can do what I want to.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ValidatingConfirmOrderCommandHandler</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">ICommandHandler<span class="token punctuation">&lt;</span>UnvalidatedConfirmOrderCommand<span class="token punctuation">&gt;</span></span></span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">private</span> <span class="token class-name">ICommandHandler<span class="token punctuation">&lt;</span>ValidatedConfirmOrderCommand<span class="token punctuation">&gt;</span></span> _commandHandler<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">private</span> <span class="token class-name">IValidator<span class="token punctuation">&lt;</span>UnvalidatedConfirmOrderCommand<span class="token punctuation">&gt;</span></span> _validator<span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token function">ValidatingConfirmOrderCommandHandler</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token class-name">ICommandHandler<span class="token punctuation">&lt;</span>ValidatedConfirmOrderCommand<span class="token punctuation">&gt;</span></span> commandHandler<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">IValidator<span class="token punctuation">&lt;</span>UnvalidatedConfirmOrderCommand<span class="token punctuation">&gt;</span></span> validator
</span><span class="code-line">    <span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        _commandHandler <span class="token operator">=</span> commandHandler<span class="token punctuation">;</span>
</span><span class="code-line">        _validator <span class="token operator">=</span> validator<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">Handle</span><span class="token punctuation">(</span><span class="token class-name">UnvalidatedConfirmOrderCommand</span> unvalidatedConfirmOrderCommand<span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
</span><span class="code-line">        <span class="token keyword">await</span> _commandHandler<span class="token punctuation">.</span><span class="token function">Handle</span><span class="token punctuation">(</span>
</span><span class="code-line">            <span class="token keyword">await</span> ValidatedConfirmOrderCommand<span class="token punctuation">.</span><span class="token function">CreateFrom</span><span class="token punctuation">(</span>
</span><span class="code-line">                <span class="token class-name">unvalidatedConfirmOrderCommand</span>
</span><span class="code-line">                @<span class="token keyword">using</span><span class="token punctuation">:</span> validator
</span><span class="code-line">            <span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>And our HTTP request handler again becomes a mere router:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line">app<span class="token punctuation">.</span><span class="token function">MapPost</span><span class="token punctuation">(</span><span class="token string">&quot;/orders/{orderId}/confirm/by-partner/{partnerId}&quot;</span><span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token keyword">async</span> <span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">FromServices</span></span><span class="token punctuation">]</span> <span class="token class-name">IDispatchCommands</span> dispatcher<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">string</span></span> orderId<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">string</span></span> partnerId<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">FromQuery</span></span><span class="token punctuation">]</span> <span class="token class-name"><span class="token keyword">string</span></span> partnerEmail
</span><span class="code-line">    <span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">await</span> dispatcher<span class="token punctuation">.</span><span class="token function">Send</span><span class="token punctuation">(</span>
</span><span class="code-line">            <span class="token keyword">new</span> <span class="token class-name constructor-invocation">UnvalidatedConfirmOrderCommand</span><span class="token punctuation">(</span>orderId<span class="token punctuation">,</span> partnerId<span class="token punctuation">,</span> partnerEmail<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">)</span>
</span></code></pre></div></div><p>We maxed this overengineering.</p><p>What are attributes that are yielded through such structures?</p><p>Better testability?</p><p>Better readability, worse understandability?</p><p>Clearer reasoning?</p><p>Too much small classes?</p><p>Too many &quot;layers&quot;?</p><p>Too much indirection?</p><p>One might think: &quot;haha, he just discovered Decorator pattern!&quot;.</p><p>The more we were decomposing by responsibility, the more &quot;design pattern-ish&quot; it started looking like.</p><p>Each &quot;thing&quot; does pretty much one job.</p><p>Of course, it does not come for free.</p><p>What we are paying with?</p><h3 id="designing-means-consciously-working-with-options"><a href="#designing-means-consciously-working-with-options" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Designing means (consciously) working with options</h3><p>Each step that we visited, either &quot;gave&quot; us something or &quot;took&quot; something from us.</p><p>This was a toy example but I believe we were able to go through various ways of organizing code. (ways of organizing? You might be interested in <a href="https://talesfrom.dev/blog/the-ambiguity-of-software-architecture">The ambiguity of software architecture</a>)</p><p>WAIT!</p><p>Can you notice what just slipped through?</p><p>&quot;Ways of organizing <strong>code</strong>&quot;, was it a <em>code</em> that we organized in different topologies?</p><p>I think it was more than just &quot;code&quot;.</p><p>&quot;Code&quot; is just a model, a way of representing something.</p><p>Through our journey we were decomposing, re-organizing stuff and assigning <strong>responsibilities</strong> in various configurations.</p><p><a href="https://talesfrom.dev/blog/the-ambiguity-of-composition">The ambiguity of composition</a> does not help too - there is no single way of composing &quot;things&quot; together.</p><p>We played with a variety of structures leaving the behavior unchanged.</p><p>At some point, each structure was working as a boundary for a particular responsibility: validation of an incoming order confirmation or processing a valid order confirmation.</p><p>Now, we even can give proper names for each step of the given flow - previously everything was molded together in an unnamed pulp (and this &quot;pulp&quot; was located in one gigantic-to-be command handler).</p><p>Don&#x27;t get me wrong, dear Reader - nothing is wrong with keeping everything together, in one gigantic pile - such organization of responsibilities also yields some qualities!</p><h3 id="designing-or-just-coding"><a href="#designing-or-just-coding" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Designing or just coding?</h3><p>In some languages, decomposition (and later composition) comes with a (little) higher price than in others.</p><p>The amount of so-called &quot;boilerplate&quot;, to form a proper structure, might require more effort - which does not encourage a fellow designer or a problem solver to make it happen.</p><p>Often, such process of forming a structure might be even called &quot;an overengineering&quot;.</p><p>What are criteria for such state?</p><p>Those are highly contextual and should be evaluated independently.</p><p>But there&#x27;s no time for evaluation - you just want to &quot;ship that sh*t.&quot;</p><p>Shipped sh*t has a very interesting quality - it attracts more sh*t.</p><p>If I were a functional programmer (what does it mean to you, dear Reader?) I could say that &quot;sh*t structure&quot; forms a monoid - you can append sh*t to sh*t, getting even bigger sh*t.</p><p>Code needs structure to support certain qualities - what qualities do we want to get from the &quot;code&quot; (think structure)?</p><p>Completing the ticket? Providing the feature to quick feedback and painless change later?</p><h3 id="no-options--no-designing"><a href="#no-options--no-designing" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>No options = no designing?</h3><p>It might sound like a bold expression: no options = no designing?</p><p>Yet again, &quot;always&quot; or &quot;never&quot; smoothly enters the game and destroys everything.</p><p>I don&#x27;t mean we need to sit and analyze all possibilities for each, even tiny feature.</p><p>My engineering mind wants options - and to get options I need to <strong>know</strong> ways of organizing stuff around.</p><p>Aggresively decomposing collaborators around (yes, each doing precisely one job - like an if expression or LINQ operations piped together) yields the understanding what responsibilities I might need to establish to get the job done.</p><p>We quickly might get the feeling where things should be coupled and to it intentionally - before decomposition, we might not even notice that (why? Please check <a href="https://talesfrom.dev/blog/modularity-uncertainty-heuristic">Modularity Uncertainty Heuristic</a>).</p><p>Still, we can&#x27;t avoid the law of eventual composition and all separated parts will need to integrated to deliver the whole experience.</p><p>Next time dear Reader, while &quot;coding&quot;, <a href="https://talesfrom.dev/blog/slow-down">Slow down</a>, and consider at least three options so that you start designing and stop coding, by asking yourself:</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>What structures and collaborator communication patterns would support desired qualities?</p></div></div></div>]]></content:encoded>
    <pubDate>Sat, 13 Jan 2024 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>programming</category><category>functional programming</category><category>object-oriented programming</category><category>design</category><category>designing</category><category>modularity</category><category>tdd</category><category>practices</category><category>composition</category><category>domain-driven design</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/from-concepts-to-architecture</guid>
    <title>From concepts to architecture</title>
    <link>https://talesfrom.dev/blog/from-concepts-to-architecture</link>
    <description>Does software architecture depend on the ideas?</description>
    <content:encoded><![CDATA[<h3 id="lets-play-a-board-game"><a href="#lets-play-a-board-game" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Let&#x27;s play a board game!</h3><p>Imagine that you and a bunch of friends of yours met, to play a new board game: <code>FSM: Fantasy, Sword and Magic</code>.</p><p>No one from the crew played before, as it&#x27;s a fresh thing in the board games market, each of you need to get the mechanics of it.</p><p>Probably, it&#x27;s not the first time any of you play a board game, so it should be easy.</p><p>Let&#x27;s say, after one hour of collaborative manual reading and exchanging opinions, you can play the game.</p><h3 id="not-that-easy-at-it-looks"><a href="#not-that-easy-at-it-looks" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Not that easy at it looks</h3><p>How does &quot;smooth jump&quot; differ from &quot;thief&#x27;s jump&quot;?</p><p>What is a &quot;power move&quot;?</p><p>What is a &quot;haze maze&quot; event?</p><p>These and many other questions appear both during the manual walkthrough and during the gameplay.</p><p>Words, words, words.</p><p>Of course, there&#x27;s a theme behind the game, so no doubt that there will be a specific language!</p><p>Nevertheless, after some more actions and mistakes, you all grasp the underlying concepts.</p><h3 id="or-maybe-it-is-easy"><a href="#or-maybe-it-is-easy" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Or maybe it is easy?</h3><p>Suddenly, it all makes sense!</p><p>The game was designed to support some interactions while discourage other ones.</p><p>Previously misunderstood rules, words and ideas compose more and more into a cohesive whole.</p><p>As players, you stop talking in a &quot;generic board game&quot; language and all discussions immerse into FSM lingo.</p><p>What&#x27;s more, people start getting creative with all the moves, jumps, spells, weapons, tactics and so on!</p><h3 id="it-all-starts-with-an-idea"><a href="#it-all-starts-with-an-idea" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>It all starts with an idea</h3><p>It might sound weird and a bit to philosophical-ish - but it all starts with an idea.</p><p>Some ideas are really old, like accounting or trading stuff, and some are new - like deploying serverless lambdas.</p><p>They were designed/created based on the needs - started as a mere concept, eventually getting materialized in the &quot;real world&quot;.</p><p>Then, each concept gave birth to more concepts, as the complexity and the needs of our worlds grew.</p><h3 id="why-bothering"><a href="#why-bothering" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Why bothering?</h3><p>When we are challenged to design a solution for a new functionality or grow existing one, we might feel the urge to jump into thinking about &quot;services&quot;, &quot;calling APIs&quot;, &quot;doing requests&quot; or &quot;writing a bunch of classes&quot;.</p><p>It might be that we say &quot;oh, it&#x27;s easy&quot; and just start implementing.</p><p>New class here, refactoring there, tests, configuration - boom! It&#x27;s all done.</p><p>But it already might be too late.</p><p>You might ask: why?</p><p>The feature is done.</p><p>Users are happy.</p><p>Stakeholders are happy.</p><p>We are happy!</p><p>Everyone are happy but Damian is moaning that it&#x27;s too late.</p><h3 id="too-late"><a href="#too-late" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Too late?</h3><p>Each area of human activity is full of such ideas.</p><p>Those ideas, interactions between them, and how they are organized, might imply certain ways of using them.</p><p>And exactly this impacts how could one model them properly within a specific context, creating solutions for business problems that aim at providing value.</p><p>The nature of the problem, the area in which our solution is going to operate and live, imposes certain qualities on us, designers.</p><p>When we jump immediately to &quot;solutioning&quot;, we might lost our chance to learn and name concepts.</p><p>And what gets named - can be discussed, controlled, measured, understood, and so on.</p><p>Typically, in the urge to finish stuff before deadlines, it might feel desirable to focus on what has already been built and utilize it for providing next solution(s).</p><p>But is this the right approach? (note that I didn&#x27;t add &quot;always&quot; to this question, although our mind immediately tries to generalize and implicitly puts that into &quot;always-ness&quot; context).</p><p>Shouldn&#x27;t we firstly think, name and make visible what is possible in the area of human activity, that we are currently working with?</p><p>&quot;Just&quot; note it.</p><p>Without special structure, treat this as a draft.</p><p>Not bind ourselves to classes, records, discriminated unions, functions, API calls, database schemas - a mere ideas that are worth knowing.</p><h3 id="guided-tours"><a href="#guided-tours" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Guided tours</h3><p>Imagine that we are working in a tourism industry.</p><p>We have built a solution for guides to improve the process of creating, managing and operating a tour.</p><p>To make things easier at the beginning, we started with a single day tours.</p><p>A <code>Tour</code>.</p><p>Maybe with a <code>Type</code> property.</p><p>Easy, clean and growth-enabling model.</p><p>Eventually, our stakeholders want to support something that they call &quot;period-based tours&quot;.</p><p>Existing structure attracts certain ways of handling this new requirement.</p><p>The easiest is to just add another value to the <code>Type</code> property and handle it using some ifs somewhere.</p><p>But we already know that <a href="https://talesfrom.dev/blog/simple-isnt-easy">Simple isn&#x27;t easy</a>.</p><p>Just for a while, let&#x27;s forget about the classes, types and properties.</p><p>Write down two distinct concepts.</p><p><code>Single day tour</code> and <code>Period-based tour</code>.</p><p>We could go further with exploration and try to understand &quot;why, who, what and when&quot; for each of them.</p><p>Eventually, we could learn that <code>Single day tour</code> typically involves single guide, single venue, whereas <code>Period-based tour</code> requires many guides, there are multiple cities and variety of venues.</p><p>How should we model it then?</p><p>Is this a &quot;single Tour&quot;?</p><h3 id="a-model-lives-to-be-useful-and-serve-a-purpose"><a href="#a-model-lives-to-be-useful-and-serve-a-purpose" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>A model lives to be useful and serve a purpose</h3><p>If above thinking process looks as a non-scientific, art-like-looking - you are perfectly right.</p><p>It&#x27;s just playing with ideas.</p><p>Working with concepts and terms.</p><p>We might still decide that a single <code>Tour</code> does the job, for now, and that it&#x27;s still the easiest way of building a working model.</p><p>What I am trying to emphasize here is that we should carefully, with full awareness, observe when our &quot;model&quot; induce friction.</p><p>I believe this would be the moment of &quot;going back to the whiteboard&quot; and bring the concepts in front of us (you might be interested in <a href="https://talesfrom.dev/blog/concept-maps">Concept maps</a>).</p><p>Ok, but where&#x27;s the architecture?</p><h3 id="from-concepts-to-architecture"><a href="#from-concepts-to-architecture" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>From concepts to architecture</h3><p>All the ideas (implicit or explicit) relate to each other and have specific interactions between them, at some point of time.</p><p>The &quot;architecture&quot; is overloaded term itself, but taking into account what we&#x27;ve explored in <a href="https://talesfrom.dev/blog/the-ambiguity-of-software-architecture">The ambiguity of software architecture</a>:</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">Software architecture</div><div class="pb-2 px-3"><div class="break-words"><p>A way of how we are organizing things to achieve or support X</p></div></div></div><p>The way we organize concepts, ideas, and terms, that thrive, live, and are used inside the context we&#x27;re working in, impose certain designs and solutions.</p><p>As in our tiny example - modeling two distinct concepts - &quot;running a single day tour&quot; and &quot;running a period-based tour&quot; - with a single &quot;entity&quot; eventually leads to creating single API, probably using single database table.</p><p>Of course, one might say that modeling them separately is speculative and has nothing to do with reality.</p><p>But then, what is reality?</p><p>Everything is a mere, pure idea.</p><p>I am more convinced that we would experience a model friction when we would have two separate models rather than a single one.</p><p>With a single <code>Tour</code>, we might eventually add more and more to it.</p><p>Look ma&#x27;, everyone is happy!</p><p>But the way we organize concepts, ideas, and terms, attracts/detracts or encourages/discourages certain ways of organizing technical components.</p><h3 id="planning"><a href="#planning" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Planning?</h3><p>Within our toy example, someone might decide that guided tour planning is a very important aspect to support.</p><p>At some point, an important stakeholder might decide to expand the market so that our software needs to support planning music events.</p><p>It&#x27;s so tempting to say that both of those human activities are related to planning.</p><p>And that&#x27;s right.</p><p>Even if it does not make any sense to clump them together, I firmly believe, dear Reader, that some people, in the name of reusability and generic solutions, would try to merge them.</p><p>And I think you could also find similar examples in your experience, dear Reader.</p><p>Representing two different concepts by the same thing - either it is a <code>Plan</code>, <code>Document</code>, <code>Tour</code>, <code>Order</code>, <code>Book</code> - imposes the architecture of software components that we&#x27;re going to build.</p><h3 id="the-lost-art-of-conceptualization"><a href="#the-lost-art-of-conceptualization" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The lost art of conceptualization</h3><p>I feel that the more technologically advanced we are, in terms of the IT capabilities, the more we lose intuition for growing software.</p><p>With so many shiny tools at our disposal, it&#x27;s easy to forget about how we organize all ideas/terms/concepts.</p><p>And organization organizes the ways we can build stuff.</p><p>How could one decompose and organize concepts so that it supports certain technical solutions and qualities?</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">David West, &quot;Object Thinking&quot;</div><div class="pb-2 px-3"><div class="break-words"><p>The Taoist butcher used but a single knife, without the need to sharpen it, during his entire career of many years. When asked how he accomplished this feat, he paused, then answered, &quot;I simply cut where the meat isn&#x27;t&quot;</p></div></div></div><p>Say hi to &quot;DDD&quot;.</p><p>And no, I am not talking about aggregates, value objects or domain services.</p><p>I am talking about focusing on the language, focusing on the area of human/business activities, that we are supposed to build solution to.</p><p>In my mind, the first and the most important step is to work on and with the ideas, living in the given context.</p><p>&quot;Cutting where the meat isn&#x27;t&quot; is where things are naturally become &quot;decomposable&quot;.</p><p>Of course, it doesn&#x27;t mean they are TOTALLY DECOUPLED.</p><p>Concepts and ideas collide, interact and throw parties too.</p><p>&quot;The law of eventual composition&quot; still applies (what&#x27;s that? I will soon publish an article on this topic).</p><p>Due to <a href="https://talesfrom.dev/blog/the-ambiguity-of-abstraction">The ambiguity of abstraction</a>, we might treat them immediately as technical things.</p><p>But they are ideas - or if you like - abstractions.</p><p>Nowadays, we drown in the abundance of tools and our it&#x27;s easy to pay attention to these.</p><p>But we have a scarcity of attention located in the software design.</p><p>If we take some books from &quot;the old ages and centuries&quot; (please note I am exaggerating), we might get interesting insights.</p><h3 id="prefactoring"><a href="#prefactoring" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Prefactoring&quot;</h3><p>Let&#x27;s start with <a href="https://www.amazon.com/Prefactoring-Ken-Pugh/dp/0596008740">Prefactoring</a> by Ken Pugh.</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">Ken Pugh, &quot;Prefactoring&quot;</div><div class="pb-2 px-3"><div class="break-words"><p>Create a clearly defined name for each concept in a system.</p></div></div></div><p>Then he follows:</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">Ken Pugh, &quot;Prefactoring&quot;</div><div class="pb-2 px-3"><div class="break-words"><p>Sometimes it is hard to determine whether you have two independent concepts or one. Try making up a one-line definition for a name. If it is difficult to create a simple definition, go ahead and use two names. Later on, if you find that the distinction was meaningless, you can always declare the two names to be synonyms.</p></div></div></div><p>Also, Ken discusses something that he calls &quot;Splitters Versus Lumpers&quot;:</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">Ken Pugh, &quot;Prefactoring&quot; - splitters vs lumpers</div><div class="pb-2 px-3"><div class="break-words"><p>It is easier to combine two concepts than it is to separate them. Splitters can be lumped more easily than lumpers can be split.</p></div></div></div><p>And <em>lumping</em> means:</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">Ken Pugh, &quot;Prefactoring&quot; - lumping definition</div><div class="pb-2 px-3"><div class="break-words"><p>Lumping involves using a single name for two different concepts. Lumping can hide relevant distinction between concepts.</p></div></div></div><p>Thanks to the separation, we eventually might notice that there&#x27;s a friction between two &quot;splitters&quot;.</p><p>What&#x27;s more, designing two &quot;splitters&quot; might eventually be labeled as &quot;duplication&quot;.</p><p>But if we remind ourselves <a href="https://talesfrom.dev/blog/modularity-uncertainty-heuristic">Modularity Uncertainty Heuristic</a>:</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">Modularity Uncertainty Heuristic</div><div class="pb-2 px-3"><div class="break-words"><p>(Re)Assigning responsibilities and noticing the high coupling in a system (here: between concepts) cannot be applied simultaneously with absolute ease</p></div></div></div><p>Of course, no one states that combining two concepts would be really easy (as there might be structure that grew around), but it becomes visible and explicit!</p><h3 id="99-bottles-of-oop"><a href="#99-bottles-of-oop" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;99 Bottles of OOP&quot;</h3><p>Now, let&#x27;s move to <a href="https://sandimetz.com/99bottles">99 Bottles of OOP</a> by Sandi Metz.</p><p>Just by searching for a word &quot;concept&quot; gives us so many results back. Here&#x27;s one that I find really interesting:</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">Sandi Metz, &quot;99 Bottles of OOP&quot;</div><div class="pb-2 px-3"><div class="break-words"><p>Combining many ideas into a small section of code makes it difficult to isolate and name any single concept.</p></div></div></div><p>We all are taught to avoid duplication, but in fact mindful duplication might be our friend:</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">Sandi Metz, &quot;99 Bottles of OOP&quot;</div><div class="pb-2 px-3"><div class="break-words"><p>Duplication is useful when it supplies independent, specific examples of a general concept that
you don&#x27;t yet understand.</p></div></div></div><p>As you might guess, I am advocating for total duplication. (yes, I am exaggerating.)</p><p>What I am trying to convey here is that thinking about concepts and ideas gives us space when exploring, analysing and then eventually modeling.</p><p>Knowledge duplication <em>might</em> make space for growing understanding by deferring lumping two concepts together.</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">Sandi Metz, &quot;99 Bottles of OOP&quot;</div><div class="pb-2 px-3"><div class="break-words"><p>By definition, future readers of your code know less than you know now. They are swimming in murky water, bumping into dimly perceived concepts, searching for clarity.</p></div></div></div><p>How verbose and explicit one needs to be to make the understanding clear for future oneself and others?</p><h3 id="essential-skills-for-the-agile-developer"><a href="#essential-skills-for-the-agile-developer" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Essential Skills For The Agile Developer&quot;</h3><p>And finally, let&#x27;s look into <a href="https://www.amazon.com/Essential-Skills-Agile-Developer-Programming-ebook/dp/B005HXMZ0S">Essential Skills For The Agile Developer</a> by Net Objectives.</p><p>One of the chapters and section names states that:</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">&quot;Essential Skills For The Agile Developer&quot;</div><div class="pb-2 px-3"><div class="break-words"><p>Using Nouns and Verbs as a Guide: Warning Danger Ahead</p></div></div></div><p>There might be various meanings but my interpretation, especially in the context of this tiny tale, is that we might firstly focus on what is primal - concepts, terms and ideas.</p><p>Based on their analysis, we eventually might suggest models and solutions.</p><p>Finally, <code>Commonality and Variability Analysis</code> (CVA shortly) gets introduced.</p><p>In my eyes, this is really interesting and profound &quot;method&quot; for looking at concepts, living in the area of business/human activity, we are currently working on.</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">&quot;Essential Skills For The Agile Developer&quot;</div><div class="pb-2 px-3"><div class="break-words"><p><a href="https://www.amazon.com/Multi-Paradigm-Design-C-James-Coplien/dp/0201824671/">Jim Coplien&#x27;s</a> work describes an approach to finding variations in the problem domain and identifying what is common across domain. Identify <em>where</em> things vary (&quot;Commonality Analysis&quot;) and then identify <em>how</em> they vary (&quot;Variability Analysis&quot;)</p></div></div></div><p>Then, they discuss &quot;Commonality Analysis&quot;:</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">&quot;Essential Skills For The Agile Developer&quot;</div><div class="pb-2 px-3"><div class="break-words"><p>According to Coplien, &quot;Commonality Analysis is the search for the common elements that helps us understand how family members are the same. By &quot;family members,&quot; Coplien means elements that are related to each other by <strong>the situation in which they appear</strong> or <strong>the function they perform</strong></p></div></div></div><p>Those &quot;common elements&quot; might lead to formulating a cohesive idea, concept or - abstraction if you will.</p><p>And, as it is suggested, we might explore the area by looking on what is the usage of underlying terms and what role they play.</p><p>Concluding on CVA:</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">&quot;Essential Skills For The Agile Developer&quot;</div><div class="pb-2 px-3"><div class="break-words"><p>Commonality-Variability Analysis offers a different way of decomposing the domain, resulting in decoupled concepts.</p></div></div></div><p>&quot;Decoupled concepts&quot; - we might not know <em>how</em> we are going to represent a given concept, but it is vastly important to reveal, to capture and to note the important ideas.</p><h3 id="it-all-ends-with-an-idea"><a href="#it-all-ends-with-an-idea" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>It all ends with an idea</h3><p>The way we are going to organize concepts and represent in our system matters.</p><p>The software architecture, the solution space - the way we organize technical components to achieve our goals and satisfy business requirements - seems definitely driven by the underlaying concepts.</p><p>And here we also have design decision power - we might overdesign or underdesign representation of all the ideas that we might, or might not, &quot;harvest&quot;.</p><p>It might not matter whether we are designing/specifying low-level classes/function or APIs, or processes - corrupted &quot;conceptualization&quot; will not help or make things easier to evolve.</p><p>We live in the <a href="https://en.wikipedia.org/wiki/VUCA">VUCA</a> world - <strong>V</strong>olatility, <strong>U</strong>ncertainty, <strong>C</strong>omplexity and <strong>A</strong>mbiguity - and exactly that&#x27;s why we need to have at least some stable ground to work as a good foundation to our technology and design choices.</p><p>We still might create new ideas, discover new concepts and bring new terms to life - and yet again this will drive our thinking and solutioning.</p><p>Not the way around.</p><p>We might eventually stop lumping <a href="https://talesfrom.dev/blog/concepts-entities-data">Concepts, Entities, Data</a> together and identify the ideas - just ideas.</p><p>Software architecture might become flawed, skewed and under-engineered because we didn&#x27;t put enough attention to ideas that precede any technological choices.</p><p>Next time, dear Reader, when working on a problem or trying to find a good solution, give yourself a playful moment and try to ask a question:</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>What are the ideas and concepts I am currently working with?</p></div></div></div>]]></content:encoded>
    <pubDate>Sat, 06 Jan 2024 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>systems thinking</category><category>programming</category><category>modeling</category><category>model</category><category>contexts</category><category>representations</category><category>mental models</category><category>heuristics</category><category>principles</category><category>patterns</category><category>design-thinking</category><category>concepts</category><category>decisions</category><category>software architecture</category><category>architecture</category><category>collaboration</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/fsm-functional-state-machines</guid>
    <title>FSM - Functional State Machines</title>
    <link>https://talesfrom.dev/blog/fsm-functional-state-machines</link>
    <description>What does make state machines functional?</description>
    <content:encoded><![CDATA[<div class="bg-slate-600 rounded-xl "><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Attention!</span></div><div class="pb-2 px-3"><div class="break-words"><p>This tale is a tiny contribution to the great <a href="https://sergeytihon.com/2023/10/28/f-advent-calendar-in-english-2023/">F# Advent Calendar 2023</a>.</p>
<p>Take your time and check other contributions too (of course, after reading this tale)!</p></div></div></div> <div class="bg-slate-600 rounded-xl mt-10"><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Kudos! 🙏🏻</span></div><div class="pb-2 px-3"><div class="break-words"><p>I wanted to thank <a href="https://twitter.com/Savlambda">borar</a> (again!) for (patiently) answering my (sometimes naive) questions and having good conversations, when it comes to functional topics.</p>
<p>Thanks, <a href="https://twitter.com/Savlambda">borar</a>!</p></div></div></div><h3 id="plan"><a href="#plan" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Plan?</h3><p>In my previous F# Advent Calendar blogpost, <a href="https://talesfrom.dev/blog/many-faces-of-ddd-aggregates-in-fsharp">Many faces of DDD Aggregates in F#</a>, we explored a &quot;tactical DDD&quot; building block called <em>Aggregate</em>.</p><p><a href="https://talesfrom.dev/blog/many-faces-of-ddd-aggregates-in-fsharp#solution-3-functional-state-machine-like-approach">One of the solutions</a> was something that I called functional, state machine-like approach.</p><p>In this tiny tale, we are going to explore state machines more.</p><p>Not just any state machines.</p><p>Functional ones.</p><p>What does this mean?</p><h3 id="functional-state-machine-like-approach"><a href="#functional-state-machine-like-approach" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Functional, State Machine-like approach</h3><p>Let&#x27;s refer to a type descriptions of a finite state machine (FSM) that we saw in <a href="https://talesfrom.dev/blog/many-faces-of-ddd-aggregates-in-fsharp#solution-3-functional-state-machine-like-approach">Functional, State Machine-like approach</a>:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">module</span> StateMachines <span class="token operator">=</span>
</span><span class="code-line">    <span class="token keyword">type</span> <span class="token class-name">FSM</span><span class="token operator">&lt;</span>&#x27;Input<span class="token punctuation">,</span> &#x27;Output<span class="token operator">&gt;</span> <span class="token operator">=</span> FSM <span class="token keyword">of</span> &#x27;Output
</span><span class="code-line">    <span class="token comment">//          \______ used  mostly for documentation - what input is possible</span>
</span><span class="code-line">    <span class="token keyword">type</span> <span class="token class-name">Evolve</span><span class="token operator">&lt;</span>&#x27;Input<span class="token punctuation">,</span> &#x27;Output<span class="token punctuation">,</span> &#x27;FSM<span class="token operator">&gt;</span> <span class="token operator">=</span> &#x27;Input <span class="token operator">-&gt;</span> &#x27;FSM <span class="token operator">-&gt;</span> &#x27;Output <span class="token operator">*</span> &#x27;FSM
</span><span class="code-line">    <span class="token keyword">type</span> <span class="token class-name">Aggregate</span><span class="token operator">&lt;</span>&#x27;Command<span class="token punctuation">,</span> &#x27;Event<span class="token punctuation">,</span> &#x27;State<span class="token operator">&gt;</span> <span class="token operator">=</span> FSM<span class="token operator">&lt;</span>&#x27;Command<span class="token punctuation">,</span> &#x27;Event list <span class="token operator">*</span> &#x27;State<span class="token operator">&gt;</span>
</span><span class="code-line">    <span class="token comment">//                           &#x27;Input   ____________/                \________ &#x27;Output with implicit state</span>
</span></code></pre></div></div><p>It captures the story behind our intentions - <code>Evolve&lt;&#x27;Input, &#x27;Output, &#x27;FSM&gt;</code> function expresses what we can do with a finite state machine (<code>FSM&lt;&#x27;Input, &#x27;Output&gt;</code>).</p><p>Imagine that we have a magical device that no one ever dreamed of - Func-o-meter.</p><p>Func-o-meter can measure and tell us how functional the given piece of code is.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/func-o-meter-intro.png" class="max-h-[30rem]"/></div><div class="italic mx-24">A device for measuring functional levels of a given piece of code</div></div><p>Regarding the symbols on the screen:</p><ul><li><span class="text-[#e03131]">L</span> means <span class="text-[#e03131]">Low</span></li><li><span class="text-[#1971c2]">M</span> means <span class="text-[#1971c2]">Medium</span></li><li><span class="text-[#2f9e44]">H</span> means <span class="text-[#2f9e44]">High</span></li></ul><p>Sounds magical?</p><p>Good, because it is pure (pun intended) magic.</p><p>We just need to point at the code with those two strangely looking antennas and we can get the measurement result back.</p><p>The result you just saw, dear Reader, was me trying to use our Func-o-meter on <a href="https://talesfrom.dev/blog/many-faces-of-ddd-aggregates-in-fsharp#solution-1-object-oriented-approach">Object-Oriented approach</a> from previous tale.</p><p>Well, it&#x27;s not that functional, isn&#x27;t it?</p><p>Let&#x27;s try to use Func-o-meter on our little snippet, presented just before.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/func-o-meter-fsm-like.png" class="max-h-[30rem]"/></div><div class="italic mx-24">Showing how much our FSM-like implementation is functional</div></div><p>And here we are - it&#x27;s pretty functional in comparison to OO one.</p><p>We are on the good path, aren&#x27;t we?</p><p>Actually, it&#x27;s really neat function (pun intended) of Func-o-meter - you are able to compare results of two consecutive measurements.</p><p>But wait, do you have any problem?</p><h3 id="problem"><a href="#problem" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Problem?</h3><p>Building something just to build something is really interesting idea, but no.</p><p>We need to have a goal.</p><p>A problem to solve.</p><p>This time our &quot;problem&quot; is pretty straightforward - we are going to try to model door mechanism.</p><p>That mechanism can be either opened, or closed or locked.</p><p>As you probably can predict, dear Reader, only some actions are able to be applied to a door mechanism in a certain state.</p><p>We could conclude the rules in the following list:</p><ul><li>door mechanism starts as <code>Closed</code></li><li>only when it&#x27;s <code>Closed</code>, when trying to <code>Open</code> it, it becomes <code>Opened</code></li><li>only when it&#x27;s <code>Opened</code>, when trying to <code>Close</code> it, it becomes <code>Closed</code></li><li>only when it&#x27;s <code>Closed</code>, when trying to <code>Lock</code> it, it becomes <code>Locked</code></li><li>only when it&#x27;s <code>Locked</code>, when trying to <code>Unlock</code> it, it becomes <code>Closed</code></li></ul><p>If one could visualize it, it might look as follows:</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/door-mechanism-to-model.png" class="max-h-[30rem]"/></div><div class="italic mx-24">A specification of how a door mechanism could work</div></div><p>Is it too naive example?</p><p>We need to have a simple problem to focus more on the modeling aspect.</p><p>Ok, fasten your seat belts, and let&#x27;s start!</p><h3 id="solution-1-mealy-state-machines"><a href="#solution-1-mealy-state-machines" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Solution #1: Mealy State Machines</h3><p>Our first attempt, for gaining more functional points, will be by using <a href="https://en.wikipedia.org/wiki/Mealy_machine">Mealy machines</a>.</p><p>As you probably know me a bit, dear Reader, I like to focus on language when modeling and solving problems.</p><p>Let&#x27;s then use mathematical language and a bit of the theory to define a Mealy machine:</p><div class="math math-display"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi><mrow><mo stretchy="false">(</mo><mi mathvariant="bold-italic">S</mi><mo separator="true">,</mo><msub><mi mathvariant="bold-italic">S</mi><mn mathvariant="bold">0</mn></msub><mo separator="true">,</mo><mi mathvariant="bold">Σ</mi><mo separator="true">,</mo><mi mathvariant="bold">Λ</mi><mo separator="true">,</mo><mi mathvariant="bold-italic">T</mi><mo separator="true">,</mo><mi mathvariant="bold-italic">G</mi><mo stretchy="false">)</mo></mrow></mi></mrow><annotation encoding="application/x-tex">\boldsymbol{(S, S_0, \Sigma, \Lambda, T, G)}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-.25em"></span><span class="mord"><span class="mord"><span class="mathbf mopen">(</span><span class="mord boldsymbol" style="margin-right:.05382em">S</span><span class="mathbf mpunct">,</span><span class="mspace" style="margin-right:.1667em"></span><span class="mord"><span class="mord boldsymbol" style="margin-right:.05382em">S</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:.3011em"><span style="top:-2.55em;margin-left:-.0538em;margin-right:.05em"><span class="pstrut" style="height:2.7em"></span><span class="mtight reset-size6 size3 sizing"><span class="mathbf mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:.15em"><span></span></span></span></span></span></span><span class="mathbf mpunct">,</span><span class="mspace" style="margin-right:.1667em"></span><span class="mathbf mord">Σ</span><span class="mathbf mpunct">,</span><span class="mspace" style="margin-right:.1667em"></span><span class="mathbf mord">Λ</span><span class="mathbf mpunct">,</span><span class="mspace" style="margin-right:.1667em"></span><span class="mord boldsymbol" style="margin-right:.15972em">T</span><span class="mathbf mpunct">,</span><span class="mspace" style="margin-right:.1667em"></span><span class="mord boldsymbol">G</span><span class="mathbf mclose">)</span></span></span></span></span></span></span></div><p>As we are diving into functional stuff, things <strong>must</strong> be mathematical in its purest form (as our functions, right?) - and also difficult.</p><p>Of course, I am joking.</p><p>We won&#x27;t go into a theory that much.</p><p>Let&#x27;s be pragmatic and focus on our goal - solving a real problem!</p><p>We could think of a Mealy finite state machine as such that its outputs are determined both by their current state and their current input.</p><p>A little computer that has some internal state and based on a given input, it change its internal state to one of finite states set.</p><p>We could represent it as follows:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">Mealy</span><span class="token operator">&lt;</span>&#x27;Input<span class="token punctuation">,</span> &#x27;Output<span class="token operator">&gt;</span> <span class="token operator">=</span> &#x27;Input <span class="token operator">-&gt;</span> &#x27;Output <span class="token operator">*</span> Mealy<span class="token operator">&lt;</span>&#x27;Input<span class="token punctuation">,</span> &#x27;Output<span class="token operator">&gt;</span>
</span></code></pre></div></div><p>So it basically gets input and does some magic to move to next state, based on some logic, and as an output it returns current state and itself.</p><p>But it&#x27;s not really the same &quot;self&quot;.</p><p>Our little machine got transformed by utilizing input and internal state - and we got &quot;new existing&quot; machine.</p><p>Immutability in its greatness.</p><p>No mutability, just transformation.</p><p>Turns out that it&#x27;s a pretty well-known &quot;problem&quot; of representing Mealy state machines.</p><p>In one of my discussions with <a href="https://twitter.com/Savlambda">borar</a>, he referred to <a href="https://github.com/purescript-contrib/purescript-machines">purescript-machines</a>.</p><p>It is a PureScript implementation of Mealy machines with halting.</p><p>Really briefly - halting means that that our machine can &quot;stop&quot; when reaching a termination state (it&#x27;s on us when we define so).</p><p>I must admit it was a great resource to understand how to implement it correctly in F#.</p><p>With <a href="https://twitter.com/Savlambda">borar</a>&#x27;s help, it was even easier.</p><p>So let&#x27;s introduce &quot;stopping a machine&quot; concept and Mealy finite state machine properly:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">Step</span><span class="token operator">&lt;</span>&#x27;Output<span class="token punctuation">,</span> &#x27;Continue<span class="token operator">&gt;</span> <span class="token operator">=</span>
</span><span class="code-line"><span class="token operator">|</span> Stop
</span><span class="code-line"><span class="token operator">|</span> ContinueWith <span class="token keyword">of</span> <span class="token punctuation">(</span>&#x27;Output <span class="token operator">*</span> &#x27;Continue<span class="token punctuation">)</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">Mealy</span><span class="token operator">&lt;</span>&#x27;Input<span class="token punctuation">,</span> &#x27;Output<span class="token operator">&gt;</span> <span class="token operator">=</span> 
</span><span class="code-line">    Mealy <span class="token keyword">of</span> <span class="token punctuation">(</span>&#x27;Input <span class="token operator">-&gt;</span> Step<span class="token operator">&lt;</span>&#x27;Output<span class="token punctuation">,</span> Mealy<span class="token operator">&lt;</span>&#x27;Input<span class="token punctuation">,</span>&#x27;Output<span class="token operator">&gt;&gt;</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token comment">//       THIS IS OUR CONTINUATION! ______/</span>
</span></code></pre></div></div><p>In order to utilize &quot;stopping a machine&quot;, we need to introduce a concept of <code>Step</code>.</p><p>It represents intention of how state machine should behave.</p><p>The most interesting part is <code>ContinueWith</code> because it yields information about the output and a continuation.</p><p>Typically a continuation is a function that contains description of what needs to be done next.</p><p>And now we have our precious machinery - <code>Mealy</code>.</p><p>It keeps a function from an input to a step.</p><p>An avid Reader might notice that <code>Step</code>, as a second type parameter, uses a continuation.</p><p>In our example its another <code>Mealy</code> type...Which holds a function.</p><p>Isn&#x27;t it weird? Shocking?</p><p>So our Mealy is keeping a function that produces a pair of output (from a state machine) and a Mealy, that keeps a function that produces a pair of...</p><p>...I hope you see where it goes.</p><p>We are going to create a recursive function there.</p><p>Isn&#x27; it too dangerous to build such recursive construct in that particular way?</p><p>Well, in case we couldn&#x27;t stop it, it might be a bit interesting to see how stack is exploding.</p><p>But thanks to <code>Stop</code> case of a <code>Step</code> type, any time our state machine yields <code>Stop</code> - no more steps are possible.</p><p>But where were we - we have the problem to solve!</p><h3 id="modeling-a-domain-door-mechanism"><a href="#modeling-a-domain-door-mechanism" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Modeling a domain: door mechanism</h3><p>Let&#x27;s move to the most intersting part - modeling.</p><p>Nothing gives so much adrenaline like modeling, isn&#x27;t it?</p><p>Let&#x27;s start with possible actions and states that are possible in our little area of activity.</p><p>Just so you know, from now on I am going to use &quot;commands&quot;, instead of actions.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">DoorMechanismState</span> <span class="token operator">=</span> Closed <span class="token operator">|</span> Opened <span class="token operator">|</span> Locked
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">DoorMechanismCommand</span> <span class="token operator">=</span> Open <span class="token operator">|</span> Close <span class="token operator">|</span> Lock <span class="token operator">|</span> Unlock
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">DoorMechanism</span> <span class="token operator">=</span> Mealy<span class="token operator">&lt;</span>DoorMechanismCommand<span class="token punctuation">,</span> DoorMechanismState<span class="token operator">&gt;</span>
</span></code></pre></div></div><p>Simple, clean, understandable - F#.</p><p>We have our basic building concepts that work inside our domain.</p><p>Here is our recursive function we talked about:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> <span class="token keyword">rec</span> <span class="token keyword">private</span> continueAs <span class="token punctuation">(</span>doorMechanism<span class="token punctuation">:</span> <span class="token class-name">DoorMechanismState</span><span class="token punctuation">)</span><span class="token punctuation">:</span> DoorMechanism <span class="token operator">=</span>
</span><span class="code-line">    <span class="token function">Mealy</span><span class="token punctuation">(</span><span class="token keyword">fun</span> doorMachineCommand <span class="token operator">-&gt;</span>
</span><span class="code-line">        <span class="token keyword">match</span> doorMechanism<span class="token punctuation">,</span> doorMachineCommand <span class="token keyword">with</span>
</span><span class="code-line">        <span class="token operator">|</span> Closed<span class="token punctuation">,</span> Open <span class="token operator">-&gt;</span> <span class="token function">ContinueWith</span><span class="token punctuation">(</span>Opened<span class="token punctuation">,</span> continueAs Opened<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token operator">|</span> Opened<span class="token punctuation">,</span> Close <span class="token operator">-&gt;</span> <span class="token function">ContinueWith</span><span class="token punctuation">(</span>Closed<span class="token punctuation">,</span> continueAs Closed<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token operator">|</span> Closed<span class="token punctuation">,</span> Lock <span class="token operator">-&gt;</span> <span class="token function">ContinueWith</span><span class="token punctuation">(</span>Locked<span class="token punctuation">,</span> continueAs Locked<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token operator">|</span> Locked<span class="token punctuation">,</span> Unlock <span class="token operator">-&gt;</span> <span class="token function">ContinueWith</span><span class="token punctuation">(</span>Closed<span class="token punctuation">,</span> continueAs Closed<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token operator">|</span> _<span class="token punctuation">,</span> _ <span class="token operator">-&gt;</span> <span class="token function">ContinueWith</span><span class="token punctuation">(</span>doorMechanism<span class="token punctuation">,</span> continueAs doorMechanism<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token comment">//  this is external &quot;output&quot; ____/              \___ here recursion happens!</span>
</span><span class="code-line">    <span class="token punctuation">)</span>
</span></code></pre></div></div><p>The most interesting part here is that this function (<code>continueAs</code>) creates a function, that accepts a <code>doorMachineCommand</code> as input (which actually is input for our state machine), and gets &quot;packaged&quot; into a <code>Mealy</code> type.</p><p>Inside, we are modeling all rules and transitions.</p><p>As you can see, dear Reader, our little door mechanism is not yielding <code>Stop</code>.</p><p>In this tiny tale, our state machine will &quot;never terminate&quot;.</p><p>Right now, we can&#x27;t yet use our state machine.</p><p>Let&#x27;s fix it by defining a <code>Send</code> function</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">Send</span><span class="token operator">&lt;</span>&#x27;Command<span class="token punctuation">,</span> &#x27;State<span class="token operator">&gt;</span> <span class="token operator">=</span>
</span><span class="code-line">    &#x27;Command <span class="token operator">-&gt;</span> Mealy<span class="token operator">&lt;</span>&#x27;Command<span class="token punctuation">,</span> &#x27;State<span class="token operator">&gt;</span> <span class="token operator">-&gt;</span> Step<span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> Mealy<span class="token operator">&lt;</span>&#x27;Command<span class="token punctuation">,</span> &#x27;State<span class="token operator">&gt;&gt;</span>
</span></code></pre></div></div><p>This function takes a command and a <code>Mealy</code> state machine and returns a <code>Step</code>.</p><p>Provided that state machine returned <code>ContinueWith</code> case, <code>Step</code> is going to keep a continuation function that will enable further state machine &quot;evolution&quot;.</p><p>Let&#x27;s implement it.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> send<span class="token punctuation">:</span> <span class="token class-name">Send</span><span class="token operator">&lt;</span>DoorMechanismCommand<span class="token punctuation">,</span> DoorMechanismState<span class="token operator">&gt;</span> <span class="token operator">=</span>
</span><span class="code-line">        <span class="token keyword">fun</span> doorMachineCommand <span class="token punctuation">(</span>Mealy runDoorMechanismWith<span class="token punctuation">)</span> <span class="token operator">-&gt;</span> 
</span><span class="code-line">            runDoorMechanismWith doorMachineCommand
</span></code></pre></div></div><p>It&#x27;s not the most advanced piece of the code.</p><p>&quot;Unwrapping&quot; a <code>Mealy</code> machine in order to &quot;run&quot; our door mechanism with a given command.</p><p>We&#x27;re almost there.</p><p>We somehow need to create a new door mechanism, right?</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> create <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span> continueAs Closed
</span></code></pre></div></div><h3 id="running-mealy-door-mechanism"><a href="#running-mealy-door-mechanism" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Running Mealy door mechanism</h3><p>Let&#x27;s create a simple mechanism:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> doorMechanism <span class="token operator">=</span> DoorMechanism<span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span></code></pre></div></div><p>FSI shows the following result (on my local):</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="code-highlight language-sh"><span class="code-line">val doorMechanism: DoorMechanism <span class="token operator">=</span> Mealy <span class="token operator">&lt;</span>fun:continueAs@2<span class="token operator"><span class="token file-descriptor important">3</span>&gt;</span>
</span></code></pre></div></div><p>Woah, perfect encapsulation!</p><p>Ok, let&#x27;s make it moving by sending <code>Open</code> to it:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line">doorMechanism
</span><span class="code-line"><span class="token operator">|&gt;</span> DoorMechanism<span class="token punctuation">.</span>send Open
</span></code></pre></div></div><p>In return, this gave:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="code-highlight language-sh"><span class="code-line">val it:
</span><span class="code-line">  StateMachines.Mealy.Step<span class="token operator">&lt;</span>DoorMechanismState,
</span><span class="code-line">                           StateMachines.Mealy.Mealy<span class="token operator">&lt;</span>DoorMechanismCommand,
</span><span class="code-line">                                                     DoorMechanismState<span class="token operator">&gt;&gt;</span> <span class="token operator">=</span>
</span><span class="code-line">  ContinueWith <span class="token punctuation">(</span>Opened, Mealy <span class="token operator">&lt;</span>fun:continueAs@2<span class="token operator"><span class="token file-descriptor important">3</span>&gt;</span><span class="token punctuation">)</span>
</span></code></pre></div></div><p>That&#x27;s interesting, isn&#x27;t it?</p><p>We got a <code>Step</code> that can be continued and it yielded <code>Opened</code> state of a state machine and...</p><p>...A continuation!</p><p>As it&#x27;s opened, let&#x27;s try to close it.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line">doorMechanism
</span><span class="code-line"><span class="token operator">|&gt;</span> DoorMechanism<span class="token punctuation">.</span>send Open
</span><span class="code-line"><span class="token operator">|&gt;</span> DoorMechanism<span class="token punctuation">.</span>send Close <span class="token comment">// ❌ bzzzzt, compile-time error!</span>
</span></code></pre></div></div><p>Oops, something isn&#x27;t working correctly.</p><p>Shouldn&#x27;t we be able to send another command?</p><p>Well, yes.</p><p>But we didn&#x27;t get a <code>Mealy</code> state machine back!</p><p>We have information that a state machine can continue processing. What&#x27;s more, we also got a pair of current state and state machine continuation.</p><p>Could we just pattern match on <code>ContinueWith</code> and continue processing?</p><p>Well, not really.</p><p>We might eventually get <code>Step</code> and then we won&#x27;t get a continuation back.</p><p>Hey, we are doing serious functional programming here!</p><p>What would you say, dear Reader, if we pass a function into <code>Step</code>, instead of &quot;getting a state machine&quot; out of the step?</p><p>One could say that we &quot;bind&quot; a function to a given <code>Step</code>, so this <code>Step</code> will have the responsibility to run this function <strong>inside</strong>.</p><p>Let&#x27;s then define <code>bind</code> function:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> bind f <span class="token punctuation">(</span>step<span class="token punctuation">:</span> <span class="token class-name">Step</span><span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> Mealy<span class="token operator">&lt;</span>&#x27;Command<span class="token punctuation">,</span>&#x27;State<span class="token operator">&gt;&gt;</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">    <span class="token keyword">match</span> step <span class="token keyword">with</span>
</span><span class="code-line">    <span class="token operator">|</span> Stop <span class="token operator">-&gt;</span> Stop
</span><span class="code-line">    <span class="token operator">|</span> ContinueWith continueWith <span class="token operator">-&gt;</span> f continueWith
</span></code></pre></div></div><p><code>bind</code> takes a function and a <code>Step</code> and provided that this <code>Step</code> can be continued, it applies a function to a continuation (yet another function).</p><p>So let&#x27;s utilize it and fix compile-time error:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line">doorMechanism
</span><span class="code-line"><span class="token operator">|&gt;</span> DoorMechanism<span class="token punctuation">.</span>send Open
</span><span class="code-line"><span class="token operator">|&gt;</span> bind <span class="token punctuation">(</span>snd <span class="token operator">&gt;&gt;</span> DoorMechanism<span class="token punctuation">.</span>send Close<span class="token punctuation">)</span> <span class="token comment">// ✅ works!</span>
</span></code></pre></div></div><p>As a result we get:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="code-highlight language-sh"><span class="code-line">val it:
</span><span class="code-line">  StateMachines.Mealy.Step<span class="token operator">&lt;</span>DoorMechanismState,
</span><span class="code-line">                           StateMachines.Mealy.Mealy<span class="token operator">&lt;</span>DoorMechanismCommand,
</span><span class="code-line">                                                     DoorMechanismState<span class="token operator">&gt;&gt;</span> <span class="token operator">=</span>
</span><span class="code-line">  ContinueWith <span class="token punctuation">(</span>Closed, Mealy <span class="token operator">&lt;</span>fun:continueAs@23-<span class="token operator"><span class="token file-descriptor important">1</span>&gt;</span><span class="token punctuation">)</span>
</span></code></pre></div></div><p>As expected, our door mechanism is closed.</p><p>As you probably noticed, dear Reader, we used <code>snd</code> function that takes the second item from a pair.</p><p>That&#x27;s because the result of <code>send</code> is a pair - current state machine state and &quot;state machine itself&quot; (in fact it&#x27;s a continuation function but let&#x27;s say it&#x27;s a state machine).</p><p>So we just &quot;discard&quot; the current state, as we are not using it anywhere.</p><p>An avid Reader might correlate &quot;bind&quot; verb with Haskell community and well-known <code>&gt;&gt;=</code> operator.</p><p>Our language, F#, is so powerful that we can define such operator that will enable smoother usage:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> <span class="token punctuation">(</span><span class="token operator">&gt;&gt;</span><span class="token operator">=</span><span class="token punctuation">)</span> step f <span class="token operator">=</span> bind f step
</span></code></pre></div></div><p>Yup, that&#x27;s it - we are reordering the arguments.</p><p>And finally, the usage:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> discardOutput <span class="token operator">=</span> snd
</span><span class="code-line">
</span><span class="code-line">doorMechanism
</span><span class="code-line"><span class="token operator">|&gt;</span> DoorMechanism<span class="token punctuation">.</span>send Open
</span><span class="code-line"><span class="token operator">&gt;&gt;</span><span class="token operator">=</span> <span class="token punctuation">(</span>discardOutput <span class="token operator">&gt;&gt;</span> DoorMechanism<span class="token punctuation">.</span>send Close<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token operator">&gt;&gt;</span><span class="token operator">=</span> <span class="token punctuation">(</span>discardOutput <span class="token operator">&gt;&gt;</span> DoorMechanism<span class="token punctuation">.</span>send Lock<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token operator">&gt;&gt;</span><span class="token operator">=</span> <span class="token punctuation">(</span>discardOutput <span class="token operator">&gt;&gt;</span> DoorMechanism<span class="token punctuation">.</span>send Open<span class="token punctuation">)</span>
</span></code></pre></div></div><p>Our final output is as follows:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="code-highlight language-sh"><span class="code-line">val it:
</span><span class="code-line">  StateMachines.Mealy.Step<span class="token operator">&lt;</span>DoorMechanismState,
</span><span class="code-line">                           StateMachines.Mealy.Mealy<span class="token operator">&lt;</span>DoorMechanismCommand,
</span><span class="code-line">                                                     DoorMechanismState<span class="token operator">&gt;&gt;</span> <span class="token operator">=</span>
</span><span class="code-line">  ContinueWith <span class="token punctuation">(</span>Locked, Mealy <span class="token operator">&lt;</span>fun:continueAs@23-<span class="token operator"><span class="token file-descriptor important">1</span>&gt;</span><span class="token punctuation">)</span>
</span></code></pre></div></div><p>I added an alias <code>discardOutput</code> for <code>snd</code> so that it communicates the intention (actually, that&#x27;s the most important principle in software design!)</p><h3 id="how-functional-are-we"><a href="#how-functional-are-we" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>How functional are we?</h3><p>Tired?</p><p>I hope not.</p><p>We have things to explore!</p><p>Let&#x27;s use our Func-o-meter and check how functional we are!</p><p>How many functional points will we get?!</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/func-o-meter-mealy.png" class="max-h-[30rem]"/></div><div class="italic mx-24">Showing how much our Mealy implementation is functional</div></div><p>That&#x27;s just fantastic!</p><p>Mealy state machine implementation beats <a href="https://talesfrom.dev/blog/many-faces-of-ddd-aggregates-in-fsharp#solution-3-functional-state-machine-like-approach">Functional, State Machine-like approach</a>!</p><p>Hurray!</p><p>Steady, gradual progress!</p><p>It&#x27;s much more functional - we utilized recursion, pattern matching, we encoded invariants what does it mean &quot;to stop a running state machine&quot;.</p><p>That&#x27;s the engineering we are looking for!</p><p>Strange, I thought it will be close to <span class="text-[#2f9e44]">High</span>.</p><p>Can we be more functional?</p><h3 id="solution-2-domain-specific-language-for-defining-state-machines"><a href="#solution-2-domain-specific-language-for-defining-state-machines" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Solution #2: Domain-specific language for defining state machines</h3><p>Previous solution for sure is functional but is it readable?</p><p>Could we do a litmus test and show it to any &quot;door mechanisms&quot; expert and ask if we modelled it correctly?</p><p>Well, recursion does not help, for sure.</p><p>Maybe we should revisit our problem that we are trying to provide a solution for.</p><p>Let&#x27;s bring the rules we started with:</p><ul><li>door mechanism starts as <code>Closed</code></li><li>only when it&#x27;s <code>Closed</code>, when trying to <code>Open</code> it, it becomes <code>Opened</code></li><li>only when it&#x27;s <code>Opened</code>, when trying to <code>Close</code> it, it becomes <code>Closed</code></li><li>only when it&#x27;s <code>Closed</code>, when trying to <code>Lock</code> it, it becomes <code>Locked</code></li><li>only when it&#x27;s <code>Locked</code>, when trying to <code>Unlock</code> it, it becomes <code>Closed</code></li></ul><p>I really believe that modelling &quot;around&quot; the language has superpowers included in it.</p><p>Ubiquitous language should live not only in spoken language, in models in our heads, but also in the code.</p><p>Ideally, we should be able to translate those rules into a specification on how the door mechanism works.</p><p>By using pseudocode, we could achieve something like this:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="code-highlight language-sh"><span class="code-line">door mechanism:
</span><span class="code-line">    starts as Closed
</span><span class="code-line">    on Closed when trying to Open <span class="token keyword">then</span> becomes Closed
</span><span class="code-line">    on Opened when trying to Close <span class="token keyword">then</span> becomes Opened
</span><span class="code-line">    on Closed when trying to Lock <span class="token keyword">then</span> becomes Locked
</span><span class="code-line">    on Locked when trying to Unlock <span class="token keyword">then</span> becomes Closed
</span></code></pre></div></div><p>It&#x27;s very readable, even non-technical experts will be able to comprehend it.</p><p>Also, it&#x27;s very declarative - we state what happens and all &quot;hows&quot; are hidden, &quot;abstracted away&quot;.</p><p>All the words we have used in our specification - they form a domain-specific language (DSL).</p><p>If we call it a ubiquitous language or domain-specific language - those are just labels for the same concept - efficient communication and smoother collaboration.</p><p>Ok, enough talking, let&#x27;s build such declarative DSL in F#!</p><p>We are going to employ very powerful feature of F# - <a href="https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/computation-expressions">Computation Expressions</a> (or CEs, shortly).</p><p>Computation Expressions empower us to create domain-specific languages, e.g.:</p><ul><li><a href="https://compositionalit.github.io/farmer/">Farmer</a> for expressing Infrastructure as Code (IaC)</li><li><a href="https://github.com/slaveOftime/Fun.Build">Fun.Build</a> for expressing CI/CD build scripts (and pipelines)</li><li><a href="https://github.com/sleepyfran/sharp-point">sharp-point</a> for building presentations</li><li>and more!</li></ul><p>It sounds like a perfect match - we want to express a specific language, coming from our tiny toy domain.</p><h3 id="expressing-state-machine"><a href="#expressing-state-machine" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Expressing state machine</h3><p>Yet again, let&#x27;s remind ourselves main words (types) used in our &quot;door mechanism area&quot;:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">DoorState</span> <span class="token operator">=</span> Closed <span class="token operator">|</span> Opened <span class="token operator">|</span> Locked
</span><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">DoorCommand</span> <span class="token operator">=</span> Open <span class="token operator">|</span> Close <span class="token operator">|</span> Lock <span class="token operator">|</span> Unlock
</span></code></pre></div></div><p>We know what are the core concepts.</p><p>Our first specification, we want to implement, is creating a state machine that starts in a certain state:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> machine <span class="token operator">=</span> stateMachine <span class="token string">&quot;doorMechanism&quot;</span> <span class="token punctuation">{</span>
</span><span class="code-line">    startsAs Closed
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>We have the following words to cover:</p><ul><li><code>stateMachine</code></li><li><code>startsAs</code></li></ul><p><code>stateMachine</code> is actual computation expression, whereas <code>startAs</code> is a custom operator within this computation expression.</p><p>Let&#x27;s define the following core building blocks for our DSL:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">HandleCommand</span><span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command<span class="token operator">&gt;</span> <span class="token operator">=</span> &#x27;Command <span class="token operator">-&gt;</span> &#x27;State
</span></code></pre></div></div><p>It simply represents a something that we&#x27;re going to call a command handler.</p><p>Let&#x27;s now add low-level contexts that will constitue our state machine:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">StateMachineContext</span><span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command <span class="token keyword">when</span> &#x27;Command <span class="token punctuation">:</span> <span class="token class-name">comparison</span> <span class="token keyword">and</span> &#x27;State <span class="token punctuation">:</span> <span class="token class-name">comparison</span><span class="token operator">&gt;</span> <span class="token operator">=</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    State<span class="token punctuation">:</span> &#x27;State
</span><span class="code-line">    Transitions<span class="token punctuation">:</span> <span class="token class-name">Map</span><span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> Map<span class="token operator">&lt;</span>&#x27;Command<span class="token punctuation">,</span> HandleCommand<span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command<span class="token operator">&gt;&gt;&gt;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>It should be self explanatory - it&#x27;s a context with current state and map of all defined transitions.</p><p>Transitions are modeled as <code>Map</code> of possible states that lead to <code>Map</code> of commands, leading to functions for handling commands.</p><p>I think being &quot;low-level&quot; here will express the details (not the intentions) might be interesting to see that &quot;there&#x27;s no magic&quot; (the only magical thing in this tale is our Func-o-meter, remember about it dear Reader).</p><p>And finally our state machine, that will be created from specification (we are wishing to build):</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">and</span> StateMachine<span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command <span class="token keyword">when</span> &#x27;Command <span class="token punctuation">:</span> <span class="token class-name">comparison</span> <span class="token keyword">and</span> &#x27;State <span class="token punctuation">:</span> <span class="token class-name">comparison</span><span class="token operator">&gt;</span> <span class="token operator">=</span> StateMachine <span class="token keyword">of</span> stateMachine<span class="token punctuation">:</span> <span class="token class-name">StateMachineContext</span><span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command<span class="token operator">&gt;</span>
</span></code></pre></div></div><p>Now we are ready to roll out the implementation for <code>stateMachine</code> computation expression:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">StateMachineAssembler</span><span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command <span class="token keyword">when</span> &#x27;Command <span class="token punctuation">:</span> <span class="token class-name">comparison</span> <span class="token keyword">and</span> &#x27;State <span class="token punctuation">:</span> <span class="token class-name">comparison</span><span class="token operator">&gt;</span><span class="token punctuation">(</span>name<span class="token punctuation">:</span> <span class="token class-name">string</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">    <span class="token keyword">member</span> this<span class="token punctuation">.</span><span class="token function">Yield</span><span class="token punctuation">(</span>_<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token keyword computation-expression">StateMachine</span> <span class="token punctuation">{</span> CurrentState <span class="token operator">=</span> Unchecked<span class="token punctuation">.</span>defaultof<span class="token operator">&lt;</span>_<span class="token operator">&gt;</span><span class="token punctuation">;</span> Transitions <span class="token operator">=</span> Map<span class="token punctuation">.</span>empty <span class="token punctuation">}</span> 
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">// 👇🏻 more members will come!</span>
</span></code></pre></div></div><p>Our state machine assembler accepts a name, but it isn&#x27;t used anywhere.</p><p>Then we have a first method, that are &quot;natively&quot; supported (and in some cases required) - <code>Yield</code>.</p><p>It helps returning a value from the computation expression.</p><p>This partical overloading of <code>Yield</code> says that given any argument, it&#x27;s going to yield a broken state machine.</p><p>Why broken?</p><p>The fact we used <code>Unchecked.defaultof&lt;_&gt;</code> which does not look functional, and safe.</p><p>&quot;Functional&quot; might mean predictive, readable, safe and explicit.</p><p>Are we really dealing with <code>StateMachine</code>? Or maybe it&#x27;s something different?</p><p>Of course, it turns out that we got a hint from our computation expression - in our lingo, the operation of building a state machine can be named as &quot;assembling a state machine&quot;.</p><p>This pesky and implicit <code>Unchecked.defaultof&lt;_&gt;</code> (which in fact will manifest as dreaded <code>null</code>) expresses a concept which is missing in our code but for sure lives in the area of our problem.</p><p>Let&#x27;s make it explicit!</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">NotAssembledStateMachineContext</span><span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command <span class="token keyword">when</span> &#x27;Command <span class="token punctuation">:</span> <span class="token class-name">comparison</span> <span class="token keyword">and</span> &#x27;State <span class="token punctuation">:</span> <span class="token class-name">comparison</span><span class="token operator">&gt;</span> <span class="token operator">=</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    CurrentState<span class="token punctuation">:</span> &#x27;State option
</span><span class="code-line">    Transitions<span class="token punctuation">:</span> <span class="token class-name">Map</span><span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> Map<span class="token operator">&lt;</span>&#x27;Command<span class="token punctuation">,</span> HandleCommand<span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command<span class="token operator">&gt;&gt;&gt;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line"><span class="token keyword">and</span> NotAssembledMachine<span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command <span class="token keyword">when</span> &#x27;Command <span class="token punctuation">:</span> <span class="token class-name">comparison</span> <span class="token keyword">and</span> &#x27;State <span class="token punctuation">:</span> <span class="token class-name">comparison</span><span class="token operator">&gt;</span> <span class="token operator">=</span> NotAssembledMachine <span class="token keyword">of</span> stateMachine<span class="token punctuation">:</span> <span class="token class-name">NotAssembledStateMachineContext</span><span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command<span class="token operator">&gt;</span>
</span></code></pre></div></div><p>Let&#x27;s introduce <code>NotAssembledMachine</code> concept as type - it will be available only when specifying and assembling a state machine.</p><p>The external world should deal with <code>StateMachine</code> - which is ready to function (pun intended) and provide value to our consumers!</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">StateMachineAssembler</span><span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command <span class="token keyword">when</span> &#x27;Command <span class="token punctuation">:</span> <span class="token class-name">comparison</span> <span class="token keyword">and</span> &#x27;State <span class="token punctuation">:</span> <span class="token class-name">comparison</span><span class="token operator">&gt;</span><span class="token punctuation">(</span>name<span class="token punctuation">:</span> <span class="token class-name">string</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">        <span class="token keyword">member</span> this<span class="token punctuation">.</span><span class="token function">Yield</span><span class="token punctuation">(</span>_<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token keyword computation-expression">NotAssembledMachine</span> <span class="token punctuation">{</span> CurrentState <span class="token operator">=</span> None<span class="token punctuation">;</span> Transitions <span class="token operator">=</span> Map<span class="token punctuation">.</span>empty <span class="token punctuation">}</span> 
</span></code></pre></div></div><p>Sounds like we are both having fun and modeling the domain of our tiny problem - neat!</p><h3 id="defining-initial-state"><a href="#defining-initial-state" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Defining initial state</h3><p>It&#x27;s time for our first custom operator: <code>startsAs</code>:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">StateMachineAssembler</span><span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command <span class="token keyword">when</span> &#x27;Command <span class="token punctuation">:</span> <span class="token class-name">comparison</span> <span class="token keyword">and</span> &#x27;State <span class="token punctuation">:</span> <span class="token class-name">comparison</span><span class="token operator">&gt;</span><span class="token punctuation">(</span>name<span class="token punctuation">:</span> <span class="token class-name">string</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">    <span class="token comment">// previous methods</span>
</span><span class="code-line">    
</span><span class="code-line">    <span class="token annotation"><span class="token punctuation">[&lt;</span><span class="token annotation-content">CustomOperation <span class="token string">&quot;startsAs&quot;</span></span><span class="token punctuation">&gt;]</span></span>
</span><span class="code-line">    <span class="token keyword">member</span>  this<span class="token punctuation">.</span>startsAs <span class="token punctuation">(</span><span class="token punctuation">(</span>NotAssembledMachine machine<span class="token punctuation">)</span><span class="token punctuation">:</span> NotAssembledMachine<span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command<span class="token operator">&gt;</span><span class="token punctuation">,</span> state<span class="token punctuation">:</span> &#x27;State<span class="token punctuation">)</span> <span class="token punctuation">:</span> NotAssembledMachine<span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command<span class="token operator">&gt;</span> <span class="token operator">=</span>
</span><span class="code-line">        <span class="token keyword computation-expression">NotAssembledMachine</span> <span class="token punctuation">{</span> machine <span class="token keyword">with</span> CurrentState <span class="token operator">=</span> Some state <span class="token punctuation">}</span>
</span></code></pre></div></div><p>Looks quite simple - it accepts &quot;previously&quot; yielded/returned not assembled machine and makes it current state defined.</p><p>In fact - that the only requirement we have for each machine - it won&#x27;t be able to do anything but at least it does no harm.</p><p>Now let&#x27;s assemble our machine!</p><h3 id="turning-not-assembled-machine-into-assembled-one"><a href="#turning-not-assembled-machine-into-assembled-one" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Turning not assembled machine into assembled one</h3><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">StateMachineAssembler</span><span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command <span class="token keyword">when</span> &#x27;Command <span class="token punctuation">:</span> <span class="token class-name">comparison</span> <span class="token keyword">and</span> &#x27;State <span class="token punctuation">:</span> <span class="token class-name">comparison</span><span class="token operator">&gt;</span><span class="token punctuation">(</span>name<span class="token punctuation">:</span> <span class="token class-name">string</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">    <span class="token comment">// previous method</span>
</span><span class="code-line">    <span class="token keyword">member</span> this<span class="token punctuation">.</span><span class="token function">Run</span><span class="token punctuation">(</span><span class="token punctuation">(</span>NotAssembledMachine machine<span class="token punctuation">)</span><span class="token punctuation">:</span> NotAssembledMachine<span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command<span class="token operator">&gt;</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">        <span class="token keyword">match</span> machine<span class="token punctuation">.</span>CurrentState <span class="token keyword">with</span>
</span><span class="code-line">        <span class="token operator">|</span> None <span class="token operator">-&gt;</span> failwith <span class="token string">&quot;You need to provide initial state for a state machine using `startsAs` operator.&quot;</span>
</span><span class="code-line">        <span class="token operator">|</span> Some state <span class="token operator">-&gt;</span> <span class="token keyword computation-expression">StateMachine</span> <span class="token punctuation">{</span> CurrentState <span class="token operator">=</span> state<span class="token punctuation">;</span> Transitions <span class="token operator">=</span> machine<span class="token punctuation">.</span>Transitions <span class="token punctuation">}</span>
</span></code></pre></div></div><p>We used another &quot;native&quot; and built-in operator - <code>Run</code> - it executes a computation expression and the type returned from this method is exactly what consumers are getting.</p><p>So we need to be careful and provide working state machine!</p><p>As you can see, dear Reader, we check if <code>CurrentState</code> is available.</p><p>Eventually, we should get correctly assembled <code>StateMachine</code> (or runtime exception, in case we didn&#x27;t cover initial state).</p><p>Let&#x27;s create &quot;an instance&quot; of state machine assembler:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> stateMachine<span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command <span class="token keyword">when</span> &#x27;Command <span class="token punctuation">:</span> <span class="token class-name">comparison</span> <span class="token keyword">and</span> &#x27;State <span class="token punctuation">:</span> <span class="token class-name">comparison</span><span class="token operator">&gt;</span> <span class="token punctuation">(</span>name<span class="token punctuation">:</span> <span class="token class-name">string</span><span class="token punctuation">)</span>  <span class="token operator">=</span>
</span><span class="code-line">    StateMachineAssembler<span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command<span class="token operator">&gt;</span>  name
</span></code></pre></div></div><p>When we use our specification:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> machine <span class="token operator">=</span> stateMachine <span class="token string">&quot;doorMechanism&quot;</span> <span class="token punctuation">{</span>
</span><span class="code-line">    startsAs Closed
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Everything compiles correctly!</p><p>Hurray!</p><p>Then, let&#x27;s see what FSI tells us, when we &quot;run&quot; our machine assembler:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="code-highlight language-sh"><span class="code-line">val machine: StateMachine<span class="token operator">&lt;</span>DoorState,DoorCommand<span class="token operator">&gt;</span> <span class="token operator">=</span>
</span><span class="code-line">    StateMachine <span class="token punctuation">{</span> CurrentState <span class="token operator">=</span> Closed
</span><span class="code-line">                   Transitions <span class="token operator">=</span> map <span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token punctuation">}</span>
</span></code></pre></div></div><h3 id="handling-state-transitions"><a href="#handling-state-transitions" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Handling state transitions</h3><p>Our machine works but not works.</p><p>We are able to assemble it, require it to start in certain state aaaand that&#x27;s it.</p><p>We need specification of state transitions!</p><p>Now, we are going to add new computation expression - <code>states</code> that will accept more computation expressions!</p><p>Our goal is to provide <code>states</code> description in the given form:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> machine <span class="token operator">=</span> stateMachine <span class="token string">&quot;doorMechanism&quot;</span> <span class="token punctuation">{</span>
</span><span class="code-line">    startsAs Closed
</span><span class="code-line">    <span class="token keyword computation-expression">states</span> <span class="token punctuation">{</span>
</span><span class="code-line">        on <span class="token keyword computation-expression">Closed</span> <span class="token punctuation">{</span>
</span><span class="code-line">            whenTryingTo Open <span class="token punctuation">(</span>thenBecomes Opened<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>As you can see, dear Reader, we introduced the following concepts: <code>states</code>, <code>on</code>, <code>whenTryingTo</code> and <code>thenBecomes</code>.</p><p>Let&#x27;s start with <code>on</code> computation expression.</p><p>Yet again, we need to have to have a &quot;context&quot; that will be evolving, as someone is going to use <code>on</code> computation expression.</p><p>Here&#x27;s its type definition:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">and</span> StateTransitions<span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command <span class="token keyword">when</span> &#x27;Command <span class="token punctuation">:</span> <span class="token class-name">comparison</span> <span class="token keyword">and</span> &#x27;State <span class="token punctuation">:</span> <span class="token class-name">comparison</span><span class="token operator">&gt;</span> <span class="token operator">=</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    OnState<span class="token punctuation">:</span> &#x27;State
</span><span class="code-line">    Transitions<span class="token punctuation">:</span> <span class="token class-name">Map</span><span class="token operator">&lt;</span>&#x27;Command<span class="token punctuation">,</span> HandleCommand<span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command<span class="token operator">&gt;&gt;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p><code>on</code> computation expression is represented by <code>StateTransitionsBuilder</code> and looks as follows:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">StateTransitionsBuilder</span><span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command <span class="token keyword">when</span> &#x27;Command <span class="token punctuation">:</span> <span class="token class-name">comparison</span> <span class="token keyword">and</span> &#x27;State <span class="token punctuation">:</span> <span class="token class-name">comparison</span><span class="token operator">&gt;</span><span class="token punctuation">(</span>fromState<span class="token punctuation">:</span> &#x27;State<span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">    <span class="token keyword">member</span> _<span class="token punctuation">.</span>Yield _ <span class="token operator">=</span> Map<span class="token punctuation">.</span>empty
</span><span class="code-line">    
</span><span class="code-line">    <span class="token annotation"><span class="token punctuation">[&lt;</span><span class="token annotation-content">CustomOperation <span class="token string">&quot;whenTryingTo&quot;</span></span><span class="token punctuation">&gt;]</span></span>
</span><span class="code-line">    <span class="token keyword">member</span> _<span class="token punctuation">.</span>whenTryingTo <span class="token punctuation">(</span>ctx<span class="token punctuation">:</span> <span class="token class-name">Map</span><span class="token operator">&lt;</span>&#x27;Command<span class="token punctuation">,</span> HandleCommand<span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command<span class="token operator">&gt;&gt;</span><span class="token punctuation">,</span> command<span class="token punctuation">:</span> &#x27;Command<span class="token punctuation">,</span> handleCommand<span class="token punctuation">:</span>  <span class="token class-name">HandleCommand</span><span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command<span class="token operator">&gt;</span><span class="token punctuation">)</span><span class="token punctuation">:</span> Map<span class="token operator">&lt;</span>&#x27;Command<span class="token punctuation">,</span> HandleCommand<span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command<span class="token operator">&gt;&gt;</span> <span class="token operator">=</span>
</span><span class="code-line">        ctx <span class="token operator">|&gt;</span> Map<span class="token punctuation">.</span>add command handleCommand
</span><span class="code-line">    
</span><span class="code-line">    <span class="token keyword">member</span> this<span class="token punctuation">.</span><span class="token function">Run</span><span class="token punctuation">(</span>ctx<span class="token punctuation">:</span> <span class="token class-name">Map</span><span class="token operator">&lt;</span>&#x27;Command<span class="token punctuation">,</span> HandleCommand<span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command<span class="token operator">&gt;&gt;</span><span class="token punctuation">)</span><span class="token punctuation">:</span> StateTransitions<span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command<span class="token operator">&gt;</span> <span class="token operator">=</span>
</span><span class="code-line">        <span class="token punctuation">{</span> OnState <span class="token operator">=</span> fromState<span class="token punctuation">;</span> Transitions <span class="token operator">=</span> ctx <span class="token punctuation">}</span>
</span></code></pre></div></div><p>It looks pretty similar to our <code>StateMachineAssembler</code>.</p><p>What&#x27;s worth noticing is that we are able to capture specific concepts through custom operators - as we saw just before.</p><p>We define <code>whenTryingTo</code> operator - it basically adds a new handle command function by a command to a map of all command handlers <code>Map</code>.</p><p>Eventually, we return <code>StateTransitions</code> for a particular state.</p><p>Now, we can define <code>on</code>:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> on<span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command <span class="token keyword">when</span> &#x27;Command <span class="token punctuation">:</span> <span class="token class-name">comparison</span> <span class="token keyword">and</span> &#x27;State <span class="token punctuation">:</span> <span class="token class-name">comparison</span><span class="token operator">&gt;</span> state <span class="token operator">=</span>
</span><span class="code-line">    StateTransitionsBuilder<span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command<span class="token operator">&gt;</span> state
</span></code></pre></div></div><p>Also, let&#x27;s define a helper function that nicely captures the language:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> thenBecomes nextState command  <span class="token operator">=</span> nextState
</span></code></pre></div></div><p>It&#x27;s dumb simple - just takes the state and returns it.</p><p>Time to check if our state transitions specification compiles!</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> onClosedTransitions <span class="token operator">=</span> on <span class="token keyword computation-expression">Closed</span> <span class="token punctuation">{</span>
</span><span class="code-line">    whenTryingTo Open <span class="token punctuation">(</span>thenBecomes Opened<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>All green, we are good!</p><p>Let&#x27;s define the last computation expression that will appear in this tiny tale - <code>states</code></p><h3 id="expressing-all-state-transitions"><a href="#expressing-all-state-transitions" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Expressing all state transitions</h3><p>Now we were dealing with transitions for a single state.</p><p>Time to handle all state transitions!</p><p>We&#x27;re going to start with a builder:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">StateMachineStateTransitionsBuilder</span><span class="token char">&#x27;&lt;&#x27;</span>State<span class="token punctuation">,</span> &#x27;Command <span class="token keyword">when</span> &#x27;Command <span class="token punctuation">:</span> <span class="token class-name">comparison</span> <span class="token keyword">and</span> &#x27;State <span class="token punctuation">:</span> <span class="token class-name">comparison</span><span class="token operator">&gt;</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">    <span class="token keyword">member</span> _<span class="token punctuation">.</span><span class="token function">Yield</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span>
</span></code></pre></div></div><p>Nothing fancy - just a &quot;default&quot; <code>Yield</code> that actually will forbid using <code>states</code> computation expression without any state transitions.</p><p>Let&#x27;s add another <code>Yield</code>, but this time for single state transitions:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">StateMachineStateTransitionsBuilder</span><span class="token char">&#x27;&lt;&#x27;</span>State<span class="token punctuation">,</span> &#x27;Command <span class="token keyword">when</span> &#x27;Command <span class="token punctuation">:</span> <span class="token class-name">comparison</span> <span class="token keyword">and</span> &#x27;State <span class="token punctuation">:</span> <span class="token class-name">comparison</span><span class="token operator">&gt;</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">    <span class="token comment">// previous methods</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">member</span> _<span class="token punctuation">.</span><span class="token function">Yield</span><span class="token punctuation">(</span>stateTransitions<span class="token punctuation">:</span> <span class="token class-name">StateTransitions</span><span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command<span class="token operator">&gt;</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">            Map<span class="token punctuation">.</span>ofArray <span class="token punctuation">[</span><span class="token operator">|</span> stateTransitions<span class="token punctuation">.</span>OnState<span class="token punctuation">,</span> stateTransitions<span class="token punctuation">.</span>Transitions <span class="token operator">|</span><span class="token punctuation">]</span>
</span></code></pre></div></div><p>Quite verbose.</p><p>Let&#x27;s move on.</p><p>We know that each our state transitions specification might have many different possible state transitions.</p><p>Then we need to handle &quot;multiple&quot; values being yielded when specying our state machine.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">StateMachineStateTransitionsBuilder</span><span class="token char">&#x27;&lt;&#x27;</span>State<span class="token punctuation">,</span> &#x27;Command <span class="token keyword">when</span> &#x27;Command <span class="token punctuation">:</span> <span class="token class-name">comparison</span> <span class="token keyword">and</span> &#x27;State <span class="token punctuation">:</span> <span class="token class-name">comparison</span><span class="token operator">&gt;</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">    <span class="token comment">// previous methods</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">member</span> _<span class="token punctuation">.</span><span class="token function">Delay</span><span class="token punctuation">(</span>f<span class="token punctuation">:</span> <span class="token class-name">unit <span class="token operator">-&gt;</span> Map</span><span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> Map<span class="token operator">&lt;</span>&#x27;Command<span class="token punctuation">,</span> HandleCommand<span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command<span class="token operator">&gt;&gt;&gt;</span><span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token keyword">member</span> _<span class="token punctuation">.</span><span class="token function">Combine</span><span class="token punctuation">(</span>newTransitions<span class="token punctuation">:</span> <span class="token class-name">Map</span><span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> Map<span class="token operator">&lt;</span>&#x27;Command<span class="token punctuation">,</span> HandleCommand<span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command<span class="token operator">&gt;&gt;&gt;</span><span class="token punctuation">,</span> previousTransitions<span class="token punctuation">:</span> <span class="token class-name">Map</span><span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> Map<span class="token operator">&lt;</span>&#x27;Command<span class="token punctuation">,</span> HandleCommand<span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command<span class="token operator">&gt;&gt;&gt;</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">            newTransitions <span class="token operator">|&gt;</span> Map<span class="token punctuation">.</span>fold <span class="token punctuation">(</span><span class="token keyword">fun</span> acc key value <span class="token operator">-&gt;</span> Map<span class="token punctuation">.</span>add key value acc<span class="token punctuation">)</span> previousTransitions
</span><span class="code-line">    <span class="token keyword">member</span> x<span class="token punctuation">.</span><span class="token function">For</span><span class="token punctuation">(</span>transitions<span class="token punctuation">:</span> <span class="token class-name">Map</span><span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> Map<span class="token operator">&lt;</span>&#x27;Command<span class="token punctuation">,</span> HandleCommand<span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command<span class="token operator">&gt;&gt;&gt;</span><span class="token punctuation">,</span> f<span class="token punctuation">:</span> <span class="token class-name">unit <span class="token operator">-&gt;</span> Map</span><span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> Map<span class="token operator">&lt;</span>&#x27;Command<span class="token punctuation">,</span> HandleCommand<span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command<span class="token operator">&gt;&gt;&gt;</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">            x<span class="token punctuation">.</span><span class="token function">Combine</span><span class="token punctuation">(</span>transitions<span class="token punctuation">,</span> <span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
</span></code></pre></div></div><p>Yet again, we need to define three &quot;native&quot; methods - <code>Delay</code>, <code>Combine</code> and <code>For</code>.</p><p>I omit describing them for brevity.</p><p>The most important part is the intention behind it - we are merging all incoming transitions for a single state into a map of such descriptions.</p><p>Eventually, we need to <code>Run</code> our builder to return a value from computation expression:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">StateMachineStateTransitionsBuilder</span><span class="token char">&#x27;&lt;&#x27;</span>State<span class="token punctuation">,</span> &#x27;Command <span class="token keyword">when</span> &#x27;Command <span class="token punctuation">:</span> <span class="token class-name">comparison</span> <span class="token keyword">and</span> &#x27;State <span class="token punctuation">:</span> <span class="token class-name">comparison</span><span class="token operator">&gt;</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">        <span class="token comment">// previous methods</span>
</span><span class="code-line">        <span class="token keyword">member</span> x<span class="token punctuation">.</span><span class="token function">Run</span><span class="token punctuation">(</span>transitions<span class="token punctuation">:</span> <span class="token class-name">Map</span><span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> Map<span class="token operator">&lt;</span>&#x27;Command<span class="token punctuation">,</span> HandleCommand<span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command<span class="token operator">&gt;&gt;&gt;</span><span class="token punctuation">)</span> <span class="token operator">=</span> transitions 
</span></code></pre></div></div><p>Time to define <code>states</code>!</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> states<span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command <span class="token keyword">when</span> &#x27;Command <span class="token punctuation">:</span> <span class="token class-name">comparison</span> <span class="token keyword">and</span> &#x27;State <span class="token punctuation">:</span> <span class="token class-name">comparison</span><span class="token operator">&gt;</span> <span class="token operator">=</span>
</span><span class="code-line">    StateMachineStateTransitionsBuilder<span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command<span class="token operator">&gt;</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span></code></pre></div></div><p>Finally!</p><p>Let&#x27;s use our newly created DSL to assemble a state machine!</p><h3 id="yet-again-assembling-a-state-machine"><a href="#yet-again-assembling-a-state-machine" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>(Yet again) Assembling a state machine</h3><p>WHAT?!</p><p>A compile-time error? How could this be?!</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> machine <span class="token operator">=</span> stateMachine <span class="token string">&quot;doorMechanism&quot;</span> <span class="token punctuation">{</span>
</span><span class="code-line">    startsAs Closed <span class="token comment">// ❌ bzzzzt, compile-time error!</span>
</span><span class="code-line">    <span class="token keyword computation-expression">states</span> <span class="token punctuation">{</span>
</span><span class="code-line">        on <span class="token keyword computation-expression">Closed</span> <span class="token punctuation">{</span>
</span><span class="code-line">            whenTryingTo Open <span class="token punctuation">(</span>thenBecomes Opened<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Inspecting the error message, one could see:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="code-highlight language-sh"><span class="code-line">This control construct may only be used <span class="token keyword">if</span> the computation expression builder defines a <span class="token string">&#x27;For&#x27;</span> method
</span></code></pre></div></div><p>Hmmm, it actually makes sense.</p><p>Our state machine assembler can handle only single value that gets yielded.</p><p>Each expression within computation expression returns something - if we put more expressions, we need to handle all the values.</p><p>Ok, let&#x27;s come back to our <code>StateMachineAssembler</code> and provide methods for handling multiple values being return from expressions, inside of a computation expression.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">StateMachineAssembler</span><span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command <span class="token keyword">when</span> &#x27;Command <span class="token punctuation">:</span> <span class="token class-name">comparison</span> <span class="token keyword">and</span> &#x27;State <span class="token punctuation">:</span> <span class="token class-name">comparison</span><span class="token operator">&gt;</span><span class="token punctuation">(</span>name<span class="token punctuation">:</span> <span class="token class-name">string</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">        <span class="token comment">// previous methods</span>
</span><span class="code-line">            
</span><span class="code-line">        <span class="token keyword">member</span> this<span class="token punctuation">.</span><span class="token function">Yield</span><span class="token punctuation">(</span><span class="token punctuation">(</span>transitions<span class="token punctuation">)</span><span class="token punctuation">:</span> Map<span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> Map<span class="token operator">&lt;</span>&#x27;Command<span class="token punctuation">,</span> HandleCommand<span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command<span class="token operator">&gt;&gt;&gt;</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">            <span class="token keyword computation-expression">NotAssembledMachine</span> <span class="token punctuation">{</span> CurrentState <span class="token operator">=</span> None<span class="token punctuation">;</span> Transitions <span class="token operator">=</span> transitions <span class="token punctuation">}</span>
</span><span class="code-line">        
</span><span class="code-line">        <span class="token keyword">member</span> this<span class="token punctuation">.</span><span class="token function">Delay</span><span class="token punctuation">(</span>f<span class="token punctuation">:</span> <span class="token class-name">unit <span class="token operator">-&gt;</span> NotAssembledMachine</span><span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command<span class="token operator">&gt;</span><span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token keyword">member</span> this<span class="token punctuation">.</span><span class="token function">For</span><span class="token punctuation">(</span><span class="token punctuation">(</span>NotAssembledMachine machine<span class="token punctuation">)</span><span class="token punctuation">:</span> NotAssembledMachine<span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command<span class="token operator">&gt;</span><span class="token punctuation">,</span> f<span class="token punctuation">:</span> <span class="token class-name">unit <span class="token operator">-&gt;</span> NotAssembledMachine</span><span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command<span class="token operator">&gt;</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">            this<span class="token punctuation">.</span><span class="token function">Combine</span><span class="token punctuation">(</span>NotAssembledMachine machine<span class="token punctuation">,</span> <span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token keyword">member</span> this<span class="token punctuation">.</span><span class="token function">Combine</span><span class="token punctuation">(</span><span class="token punctuation">(</span>NotAssembledMachine newMachine<span class="token punctuation">)</span><span class="token punctuation">:</span> NotAssembledMachine<span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command<span class="token operator">&gt;</span><span class="token punctuation">,</span> <span class="token punctuation">(</span>NotAssembledMachine existingMachine<span class="token punctuation">)</span><span class="token punctuation">:</span> NotAssembledMachine<span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command<span class="token operator">&gt;</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">            <span class="token keyword">let</span> newTransitions <span class="token operator">=</span>
</span><span class="code-line">                newMachine<span class="token punctuation">.</span>Transitions
</span><span class="code-line">                <span class="token operator">|&gt;</span> Map<span class="token punctuation">.</span>fold <span class="token punctuation">(</span><span class="token keyword">fun</span> acc key value <span class="token operator">-&gt;</span> Map<span class="token punctuation">.</span>add key value acc<span class="token punctuation">)</span> existingMachine<span class="token punctuation">.</span>Transitions
</span><span class="code-line">            
</span><span class="code-line">            <span class="token keyword computation-expression">NotAssembledMachine</span> <span class="token punctuation">{</span> CurrentState <span class="token operator">=</span>  newMachine<span class="token punctuation">.</span>CurrentState<span class="token punctuation">;</span> Transitions <span class="token operator">=</span> newTransitions  <span class="token punctuation">}</span>
</span></code></pre></div></div><p>It&#x27;s pretty similar to what we saw in <code>StateMachineStateTransitionsBuilder</code>, when creating <code>states</code> computation expression.</p><p>All those methods are required to deal with many values.</p><p>What is worth noticing is the implementation of <code>Combine</code>:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token comment">// ...rest of computation expression</span>
</span><span class="code-line"><span class="token keyword">member</span> this<span class="token punctuation">.</span><span class="token function">Combine</span><span class="token punctuation">(</span><span class="token punctuation">(</span>NotAssembledMachine newMachine<span class="token punctuation">)</span><span class="token punctuation">:</span> NotAssembledMachine<span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command<span class="token operator">&gt;</span><span class="token punctuation">,</span> <span class="token punctuation">(</span>NotAssembledMachine existingMachine<span class="token punctuation">)</span><span class="token punctuation">:</span> NotAssembledMachine<span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command<span class="token operator">&gt;</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">    <span class="token keyword">let</span> newTransitions <span class="token operator">=</span>
</span><span class="code-line">        newMachine<span class="token punctuation">.</span>Transitions
</span><span class="code-line">        <span class="token operator">|&gt;</span> Map<span class="token punctuation">.</span>fold <span class="token punctuation">(</span><span class="token keyword">fun</span> acc key value <span class="token operator">-&gt;</span> Map<span class="token punctuation">.</span>add key value acc<span class="token punctuation">)</span> existingMachine<span class="token punctuation">.</span>Transitions
</span><span class="code-line"><span class="token comment">// ...rest of computation expression</span>
</span></code></pre></div></div><p>It takes two not assembled machines and combines their state transitions - literally it merges them.</p><p>After handling all the methods, required to support multiple values returned from expressions, it&#x27;s all green!</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> machine <span class="token operator">=</span> stateMachine <span class="token string">&quot;doorMechanism&quot;</span> <span class="token punctuation">{</span>
</span><span class="code-line">    startsAs Closed <span class="token comment">// ✅ compiles!</span>
</span><span class="code-line">    <span class="token keyword computation-expression">states</span> <span class="token punctuation">{</span>
</span><span class="code-line">        on <span class="token keyword computation-expression">Closed</span> <span class="token punctuation">{</span>
</span><span class="code-line">            whenTryingTo Open <span class="token punctuation">(</span>thenBecomes Opened<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><h3 id="final-state-machine"><a href="#final-state-machine" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Final State Machine!</h3><p>We are ready to express, using our DSL, the rules of a door mechanism:</p><ul><li>door mechanism starts as <code>Closed</code></li><li>only when it&#x27;s <code>Closed</code>, when trying to <code>Open</code> it, it becomes <code>Opened</code></li><li>only when it&#x27;s <code>Opened</code>, when trying to <code>Close</code> it, it becomes <code>Closed</code></li><li>only when it&#x27;s <code>Closed</code>, when trying to <code>Lock</code> it, it becomes <code>Locked</code></li><li>only when it&#x27;s <code>Locked</code>, when trying to <code>Unlock</code> it, it becomes <code>Closed</code></li></ul><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> machine <span class="token operator">=</span> stateMachine <span class="token string">&quot;doorMechanism&quot;</span> <span class="token punctuation">{</span>
</span><span class="code-line">    startsAs Closed
</span><span class="code-line">    <span class="token keyword computation-expression">states</span> <span class="token punctuation">{</span>
</span><span class="code-line">        on <span class="token keyword computation-expression">Closed</span> <span class="token punctuation">{</span>
</span><span class="code-line">            whenTryingTo Open <span class="token punctuation">(</span>thenBecomes Opened<span class="token punctuation">)</span>
</span><span class="code-line">            whenTryingTo Lock <span class="token punctuation">(</span>thenBecomes Locked<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">}</span> 
</span><span class="code-line">        on <span class="token keyword computation-expression">Opened</span> <span class="token punctuation">{</span>
</span><span class="code-line">            whenTryingTo Close <span class="token punctuation">(</span>thenBecomes Closed<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">        on <span class="token keyword computation-expression">Locked</span> <span class="token punctuation">{</span>
</span><span class="code-line">            whenTryingTo Unlock <span class="token punctuation">(</span>thenBecomes Closed<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>And it all compiles!</p><p>It sounds very natural!</p><p>It is very explicit!</p><p>F# in its purest form ❤️</p><p>LET&#x27;S RUN OUR STATE MACHINE!</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="code-highlight language-sh"><span class="code-line">val machine: StateMachine<span class="token operator">&lt;</span>DoorState,DoorCommand<span class="token operator">&gt;</span> <span class="token operator">=</span>
</span><span class="code-line">    StateMachine
</span><span class="code-line">      <span class="token punctuation">{</span> CurrentState <span class="token operator">=</span> Closed
</span><span class="code-line">        Transitions <span class="token operator">=</span>
</span><span class="code-line">         map
</span><span class="code-line">           <span class="token punctuation">[</span><span class="token punctuation">(</span>Closed,
</span><span class="code-line">             map <span class="token punctuation">[</span><span class="token punctuation">(</span>Open, <span class="token operator">&lt;</span>fun:machine@86-3<span class="token operator"><span class="token file-descriptor important">2</span>&gt;</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">(</span>Lock, <span class="token operator">&lt;</span>fun:machine@87-3<span class="token operator"><span class="token file-descriptor important">3</span>&gt;</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token punctuation">(</span>Opened, map <span class="token punctuation">[</span><span class="token punctuation">(</span>Close, <span class="token operator">&lt;</span>fun:machine@90-3<span class="token operator"><span class="token file-descriptor important">4</span>&gt;</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token punctuation">(</span>Locked, map <span class="token punctuation">[</span><span class="token punctuation">(</span>Unlock, <span class="token operator">&lt;</span>fun:machine@93-3<span class="token operator"><span class="token file-descriptor important">5</span>&gt;</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">]</span> <span class="token punctuation">}</span>
</span></code></pre></div></div><p>Specification of how our state machine works.</p><p>Isn&#x27;t it beautiful?</p><p>But wait, we are not done yet.</p><p>We actually need to execute this specification!</p><p>As in the <a href="https://talesfrom.dev/blog/fsm-functional-state-machines#solution-1-mealy-state-machines">Solution #1: Mealy State Machines</a>, we are going to define <code>Send</code> action:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">Send</span><span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command <span class="token keyword">when</span> &#x27;State <span class="token punctuation">:</span> <span class="token class-name">comparison</span> <span class="token keyword">and</span> &#x27;Command <span class="token punctuation">:</span> <span class="token class-name">comparison</span><span class="token operator">&gt;</span> <span class="token operator">=</span>
</span><span class="code-line">    &#x27;Command <span class="token operator">-&gt;</span> StateMachine<span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command<span class="token operator">&gt;</span> <span class="token operator">-&gt;</span> StateMachine<span class="token operator">&lt;</span>&#x27;State<span class="token punctuation">,</span> &#x27;Command<span class="token operator">&gt;</span>
</span></code></pre></div></div><p>Pretty straightforward.</p><p>Now implementation of a <code>send</code> function:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> send<span class="token punctuation">:</span> <span class="token class-name">Send</span><span class="token operator">&lt;</span>DoorState<span class="token punctuation">,</span> DoorCommand<span class="token operator">&gt;</span> <span class="token operator">=</span>
</span><span class="code-line">        <span class="token keyword">fun</span> command <span class="token punctuation">(</span>StateMachine fsm<span class="token punctuation">)</span> <span class="token operator">-&gt;</span>
</span><span class="code-line">            <span class="token keyword">let</span> newState <span class="token operator">=</span>
</span><span class="code-line">                <span class="token keyword">match</span> fsm<span class="token punctuation">.</span>Transitions <span class="token operator">|&gt;</span> Map<span class="token punctuation">.</span>tryFind fsm<span class="token punctuation">.</span>CurrentState <span class="token keyword">with</span>
</span><span class="code-line">                <span class="token operator">|</span> Some transitions <span class="token operator">-&gt;</span>
</span><span class="code-line">                    <span class="token keyword">match</span> transitions <span class="token operator">|&gt;</span> Map<span class="token punctuation">.</span>tryFind command <span class="token keyword">with</span>
</span><span class="code-line">                    <span class="token operator">|</span> Some transition <span class="token operator">-&gt;</span> transition command
</span><span class="code-line">                    <span class="token operator">|</span> None <span class="token operator">-&gt;</span> fsm<span class="token punctuation">.</span>CurrentState
</span><span class="code-line">                <span class="token operator">|</span> None <span class="token operator">-&gt;</span> fsm<span class="token punctuation">.</span>CurrentState
</span><span class="code-line">            
</span><span class="code-line">            <span class="token keyword computation-expression">StateMachine</span> <span class="token punctuation">{</span> fsm <span class="token keyword">with</span> CurrentState <span class="token operator">=</span> newState <span class="token punctuation">}</span>
</span></code></pre></div></div><p>This function takes a command and finds all specified transitions for a current state, subsequently trying to find a command handler for a given command.</p><p>In case it was found - it applies a transition function to the command (in our tiny tale it&#x27;s just returning a new state), else it remains in the same state.</p><p>Are you ready?</p><p>This is the final of the all finals!</p><p>Let&#x27;s send some commands to our door mechanism state machine:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> machine&#x27; <span class="token operator">=</span>
</span><span class="code-line">    machine
</span><span class="code-line">    <span class="token operator">|&gt;</span> send Open
</span><span class="code-line">    <span class="token operator">|&gt;</span> send Close
</span><span class="code-line">    <span class="token operator">|&gt;</span> send Lock
</span><span class="code-line">    <span class="token operator">|&gt;</span> send Open
</span></code></pre></div></div><p>FSI quickly gives us feedback:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="code-highlight language-sh"><span class="code-line">  val machine&#x27;: StateMachine<span class="token operator">&lt;</span>DoorState,DoorCommand<span class="token operator">&gt;</span> <span class="token operator">=</span>
</span><span class="code-line">    StateMachine
</span><span class="code-line">      <span class="token punctuation">{</span> CurrentState <span class="token operator">=</span> Locked
</span><span class="code-line">        Transitions <span class="token operator">=</span>
</span><span class="code-line">         map
</span><span class="code-line">           <span class="token punctuation">[</span><span class="token punctuation">(</span>Closed,
</span><span class="code-line">             map <span class="token punctuation">[</span><span class="token punctuation">(</span>Open, <span class="token operator">&lt;</span>fun:machine@86-2<span class="token operator"><span class="token file-descriptor important">2</span>&gt;</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">(</span>Lock, <span class="token operator">&lt;</span>fun:machine@87-2<span class="token operator"><span class="token file-descriptor important">3</span>&gt;</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token punctuation">(</span>Opened, map <span class="token punctuation">[</span><span class="token punctuation">(</span>Close, <span class="token operator">&lt;</span>fun:machine@90-2<span class="token operator"><span class="token file-descriptor important">4</span>&gt;</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token punctuation">(</span>Locked, map <span class="token punctuation">[</span><span class="token punctuation">(</span>Unlock, <span class="token operator">&lt;</span>fun:machine@93-2<span class="token operator"><span class="token file-descriptor important">5</span>&gt;</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">]</span> <span class="token punctuation">}</span>
</span></code></pre></div></div><p>As expected, we can&#x27;t open a locked door mechanism!</p><p>Also, we clearly can see all transitions that need to be interpreted (which we already did!), but it nice to have it in a quite readable form.</p><h3 id="how-functional-are-we-1"><a href="#how-functional-are-we-1" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>How functional are we?</h3><p>Wait!</p><p>We need to measure how functional is our DSL approach to create and run state machines!</p><p>Let&#x27;s me pull Func-o-meter and check it.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/func-o-meter-dsl.png" class="max-h-[30rem]"/></div><div class="italic mx-24">Showing how much our DSL implementation is functional</div></div><p>CAN YOU BELIEVE THAT?!</p><p>We attained functional enlightment, and our work is a masterpiece.</p><p>DSL-based state machine specification beats everything in the world (in our tiny world of this tiny tale, but still).</p><p>Are you feeling boosted?</p><p>Empowered?!</p><h3 id="what-the-hell-just-happened"><a href="#what-the-hell-just-happened" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>WHAT THE HELL JUST HAPPENED?!</h3><p>Well, we experienced and encountered maaaany things, along our journey.</p><p>We defined the domain of our problem and we tried to provide as functional solutions as possible.</p><p>We used helpful device called Func-o-meter to measure how functional solutions are:</p><ul><li>Mealy State Machines</li><li>Domain-specific language for defining state machines</li></ul><p>Unfortunately, I need to disappoint you, dear and patient Reader...</p><p>...Func-o-meter does not exist.</p><p>I must appologize you - I can&#x27;t measure how functional the code is.</p><p>What does it really mean?</p><p>Recently, more and more languages are getting functional flavors (I am not calling them features, purposefully).</p><p>And that&#x27;s good - but its worth keeping that in mind they might be &quot;flavors&quot;, add-ins - not core concepts in which the language was forged.</p><p>Nothing wrong with that!</p><p>The language is a tool, and of course it shapes the way one is thinking, modeling and reasoning - still, the most important thing is delivering value to our users/customers, with software (or without it, actually).</p><p>So all the comparisons and measurements our imaginary Func-o-meter did, are farfetched.</p><p>Still we could define some tenets or attributes, that are attracted by functional-first thinking.</p><p>As I concluded in <a href="https://talesfrom.dev/blog/many-faces-of-ddd-aggregates-in-fsharp">Many faces of DDD Aggregates in F#</a></p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>FP achieves evolvability through immutability</p></div></div></div><p>And we were able to see this phenomenon, while experiencing our tiny journey.</p><p>Another one I would add to &quot;functional-first thinking&quot; basket is composition - on all levels - function composition, type composition.</p><p>Both immutability and composition, in my mind, express the most fundamental part of functional-first thinking - transformative nature.</p><p>Processes have a transformative nature too.</p><p>They make one thing become another and we literally saw that, especially in our lovely DSL.</p><p>Of course, we don&#x27;t need to model everything in such a way - there&#x27;s <a href="https://talesfrom.dev/blog/the-cost-of-modeling">The cost of modeling</a> for each model we build.</p><p>But I believe functional-first thinking helps us to perform modeling on the &quot;highest&quot; possible level - &quot;becoming&quot; level (you don&#x27;t know what I am talking about? you might be interested in <a href="https://talesfrom.dev/blog/modeling-maturity-levels">Modeling Maturity Levels</a>).</p><p>So what I would suggest is to think in the &quot;functional-first&quot; way (immutability, composition and &quot;transformatively&quot;) and not to &quot;be&quot; functional.</p><h3 id="closing"><a href="#closing" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Closing</h3><p>Thank you for your patience, dear Reader.</p><p>I hope you found it interesting to see the same problem from many different perspectives and to model the solutions on various levels.</p><p>One thing that is so important and it would be a shame for me if I didn&#x27;t mention it.</p><p>We played with the powerful, functional-first language that F# is, but still the most important aspect of our job is understanding the problem we need to solve.</p><p>This reminds me the following saying:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Well-defined problem contains half of the solution</p></div></div></div><p>As always, there&#x27;s half truth, half &quot;myth&quot;, but it gives the impression that we really need to be careful how we define our problems.</p><p>I feel it&#x27;s a nice moment to stop our little journey, dear Reader.</p><p>Thank you and see you soon!</p><p><strong>NOTE</strong>: source code will be shared soon</p>]]></content:encoded>
    <pubDate>Fri, 15 Dec 2023 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>exploration</category><category>fsharp</category><category>fsharp advent calendar</category><category>functional</category><category>paradigms</category><category>state machines</category><category>modeling</category><category>declarative programming</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/common-words-of-shared-apocalypse</guid>
    <title>Common words of the shared apocalypse</title>
    <link>https://talesfrom.dev/blog/common-words-of-shared-apocalypse</link>
    <description>Are there common words that you can share to scare your teammates?</description>
    <content:encoded><![CDATA[<h3 id="its-just-a-document"><a href="#its-just-a-document" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>It&#x27;s just a document</h3><p>Imagine that we are building a software solution for managing scientific papers.</p><p>Each of the papers gets through various processes, some of them never get published, others are successful and become a state-of-art holy grail.</p><p>Of course, building software is vastly related to understanding the underlying &quot;area of human activity&quot; so that we can build models that work as solutions for the problems within that &quot;domain&quot;.</p><p>So we went through some exploratory sessions with experts in the field - and seems like we understood the essential parts of the processes driving this business.</p><p>We have the &quot;whys&quot;, we&#x27;ve heard about the vision, we know how we make money - pretty powerful drivers, I would say.</p><p>In one of follow-ups, the modeling session, there was such a conversation:</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><span class=""><span class="italic font-bold">Engineer #1</span>: Isn&#x27;t it that all whitepapers are documents?</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold">Engineer #2</span>: Kinda. But what purpose will that change serve? Isn&#x27;t it just a wording?</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold">Engineer #1</span>: Hmm, good question. We are managing scientific papers and I was in the meeting with Joey, you know, the architect from medical documents department, they have similar review processes as we have - maybe we should look for a common ground?</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold">Engineer #2</span>: When you say so, a scientific paper is a type of document...</span></span><span class="text-white"> </span><span class="text-white"><span class=""><span class="italic font-bold">Engineer #1</span>: I told you! Document review process might be pretty generic, then we can build common workflow engine that will enable for configuring it via the shared DSL!</span></span></div><p>After such information exchange, two teams met and started figuring out the commonalities and then build services around them.</p><p>Soon, <code>Documents API</code> was created and started providing services for them all.</p><p>First release was a real blast. Developers, business people, architects - all celebrated this great success.</p><h3 id="configuration-to-the-rescue"><a href="#configuration-to-the-rescue" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Configuration to the rescue</h3><p>Things started getting a bit hairy with first few change requests.</p><p>Each of the teams pulled in its direction, trying to stretch this common service.</p><p>Coordination never ended and even small change required throwing a DACM - Document API Coordination Meeting - as it got named pretty quickly.</p><p>Massive amount of if statements, trying to cover the variabilities, followed up by the endlessly growing configuration, slowly started killing the velocity.</p><p>Soon, <code>Documents API</code> required highly skilled professionals who knew how to configure this beast.</p><h3 id="its-generic-isnt-it"><a href="#its-generic-isnt-it" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>It&#x27;s generic, isn&#x27;t it?</h3><p>One of the core princinples of the <code>Documents API</code> configuration was its generic nature.</p><p><code>Documents Configuration API</code> was created exactly for that purpose.</p><p>Whenever there was a crazy idea related to documents (it means either medical documents, financial invoices or scientific papers) - it got branded as &quot;it&#x27;s just a step in workflow and another configuration&quot;.</p><p>People started programming in a language called JSON, as it expressed Domain-Specific Languages of the <code>Documents Configuration</code>.</p><p>Soon, parsing DSON became one of the most desired skills in the company - where DSON stood for &quot;Document Script Object Notation&quot;.</p><h3 id="he-scared-all-his-friends---learn-this-weird-trick"><a href="#he-scared-all-his-friends---learn-this-weird-trick" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;He scared all his friends - learn this weird trick!&quot;</h3><p>There are certain words that bring havoc and fear to people&#x27;s ambitions, motivations, and general well-being.</p><p>They might be regarded as harbingers of future pain that brings the highest mental damage.</p><p>I suppose both yours, dear Reader, and mine, dictionary contain much of similarly described words - in this tiny tale we are going to focus on four of them.</p><p>It&#x27;s enough to destroy dreams and bury the happiness.</p><p>Let&#x27;s start with three of them, as they fall into the similar category - generalizations.</p><h3 id="shared-common-and-generic---three-horsemen-of-the-apocalypse"><a href="#shared-common-and-generic---three-horsemen-of-the-apocalypse" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Shared&quot;, &quot;common&quot; and &quot;generic&quot; - three horsemen of the apocalypse</h3><p>We all know them, we all love them - building something once and reusing everywhere - doesn&#x27;t it sound blisfully?</p><p>Common models, shared code, generic solutions - mix and match all the permutations and you get nice input for buzzword bingo.</p><p>Those ones are pretty common (pun intended) to be found in architecture diagrams programmed in PowerPoint presentations.</p><p>Put some boxes and lines - everything ready, now it&#x27;s just coding.</p><p>Donald Knuth once said:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Premature optimization is the root of all evil.</p></div></div></div><p>It&#x27;s of course tore out from its context - nevertheless we can use it for the purpose of this tale.</p><p>As you probably know dear Reader, I really like to nitpick words and play with the language - what could &quot;premature optimization&quot; mean?</p><p>What if this &quot;premature optimization&quot; points at &quot;premature optimization for generalization&quot;?</p><p>It like assuming that things can be reused because they look the same.</p><p>On diagrams and architectural sketches, everything looks marvelous.</p><p>But presentations and drawing on papers do not throw runtime errors or do not show compile time errors (can errors evolve? Check <a href="https://talesfrom.dev/blog/how-do-errors-evolve">How do errors evolve?</a>)</p><p>Typically &quot;sameness&quot; is defined on the attributes levels, structurally-wise.</p><p>If it looks like a duck, quacks like a duck, it must be a document. Oh sorry, a duck.</p><p>Also, this semantic diffusion moves meaning between the abstraction levels - how we represent certain concepts.</p><p>One of the origins of such thinking is focusing on data, not on entities, or not even on concepts (what&#x27;s the difference? Please check <a href="https://talesfrom.dev/blog/concepts-entities-data">Concepts, Entities, Data</a>)</p><p>We tend to look for structure commonalities but we should move into thinking and observing <strong>communication structure commonalities</strong>.</p><p>This leads us into process thinking, looking at interactions and how certain concepts work together - not how they are related, hierarchy wise.</p><p>Still, this category of dreaded words is dangerous as we can pretty early start generalizing the common, generic solutions to distinct problems.</p><p>I like to say that each solution needs to prove its usefulness - eventually we might spot some commonalities and find out how we can generalize our solution to support more generic use cases.</p><p>Such support for other use cases might require us to generalize and/or abstract away the details - but yet again, <strong>abstracting does not mean generalizing</strong> (what do I mean by that? Please check <a href="https://talesfrom.dev/blog/the-ambiguity-of-abstraction">The ambiguity of abstraction</a>)</p><p>By prematurely generalizing we might start building enormous solutions for small problems we want to solve in the first place.</p><p>We will trap ourselves in big-bang planning, which always results in one thing: big-bang.</p><p>This involves complexity from every hole in our reasoning - as we plan to make common things, that will serve generic purposes which eventually become shared across many teams.</p><p>But now let&#x27;s move the deadliest villain in the whole crew - in fact, everything starts from it and with it.</p><h3 id="its-just-x---ruthless-and-scariest-horseman-of-the-apocalypse"><a href="#its-just-x---ruthless-and-scariest-horseman-of-the-apocalypse" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;It&#x27;s just X&quot; - ruthless and scariest horseman of the apocalypse</h3><p>Imagine that you are brainstorming on a particular problem and someone throws the following statement:</p><ul><li>&quot;it&#x27;s just an if in the class Fluggaenkoecchicebolsen&quot;</li><li>&quot;it&#x27;s just another parameter in the constructor of Fluggaenkoecchicebolsen&quot;</li><li>&quot;it&#x27;s just a new bool property in Fluggaenkoecchicebolsen class&quot;</li><li>&quot;it&#x27;s just a new column in Fluggaenkoecchicebolsen table&quot;</li><li>&quot;it&#x27;s just about adding new attribute with the name Fluggaenkoecchicebolsen and it will work&quot;</li><li>etc.</li></ul><p>All these have the same root - &quot;it&#x27;s just a&quot;.</p><p>It looks like I am really nitpicking on the language, but this little guy typically expresses carelessness in understanding the underlying problem we want to solve and immediately transitions us into thinking about the easy solution(s).</p><p>As we discussed that previously - <a href="https://talesfrom.dev/blog/simple-isnt-easy">Simple isn&#x27;t easy</a>.</p><p>&quot;It&#x27;s just a&quot; dulls our vigilance.</p><p>It makes us vulnerable and susceptible to so many biases, mental shortcuts, and mistakes in thinking.</p><p>If things sound &quot;just easy&quot;, fasten your seatbelts, turn on sixth-sense and observe the surroundings - possible proofless assumptions are being made!</p><p>Of course, one might say: &quot;hey Damian, we don&#x27;t have time to explore everything to start working&quot;.</p><p>Yup, that&#x27;s true, but beware, because we always can rapidly build the wrong thing.</p><p>But no one said &quot;everything&quot; - there are certain concepts that drive the given area of human activity.</p><p>Those fundamental concepts are there, waiting to bloom and show their beauty.</p><p>&quot;It&#x27;s just a&quot; don&#x27;t let them grow, evolve and appear.</p><p>Everything stems from &quot;it&#x27;s just a&quot; - including &quot;shared&quot;, &quot;common&quot; and &quot;generic&quot; horsemen of the apocalypse.</p><p>This works almost like a dark magic spell, summoning The Horde of Deceiveful Assumptions.</p><p>Don&#x27;t let the dark magic deceive you, dear Reader.</p><h3 id="the-cure-for-the-poisonous-thinking"><a href="#the-cure-for-the-poisonous-thinking" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The cure for the poisonous thinking?</h3><p>Ok, we revealed the despicable four words, and I hope you are not frightened, dear Reader.</p><p>Now we need to find something to counteract the consequences of those words.</p><p>Let&#x27;s start with really obvious one - don&#x27;t be afraid of playing with ideas - be brave and have a heart full of courage.</p><p>Not every idea needs to be implemented - by playing with ideas, brainstorming the possible options, we might eventually understand the problem more deeply and/or broadly.</p><p>Be open and put all the words - concepts - in the board (you can try to find out if they form <a href="https://talesfrom.dev/blog/concept-maps">Concept Maps</a>).</p><p>There is no wrong answer, eventually you might end up with really elegant and simple solution.</p><p>And this requires iterations.</p><p>Growing.</p><p>Evolution.</p><p>Experiments.</p><p>Not every experiment needs to be implemented - it&#x27;s all about breaking from &quot;building the big castle&quot; thinking.</p><p>Most of the experiments might bring discoveries - and it might lead to interesting observations and insights on what we are actually doing.</p><p>Of course, &quot;concepts do not delivery value&quot; - one might say.</p><p>In my mind, everything starts from the concepts and ends with the concepts - as we, human beings, operate in a world full of symbols we continuously create.</p><p>The winner is the one who has concepts that model a given area of human activity more efficiently, usefully, and evolvably.</p><p>And this model does not mean database model or data model.</p><p>It&#x27;s above and beyond them.</p><p>So play with ideas. Iterate with understanding. Express it clearly and carefully.</p><p>Language is everything.</p>]]></content:encoded>
    <pubDate>Wed, 06 Dec 2023 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>fundamentals</category><category>domain-driven design</category><category>software design</category><category>simplicity</category><category>software architecture</category><category>software</category><category>modeling</category><category>models</category><category>principles</category><category>patterns</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/easy-becomes-complex</guid>
    <title>Easy becomes complex</title>
    <link>https://talesfrom.dev/blog/easy-becomes-complex</link>
    <description>When easy eventually becomes complex?</description>
    <content:encoded><![CDATA[<h3 id="problems-strike-back"><a href="#problems-strike-back" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Problems strike back!</h3><p>Yet again, the echo of the past got me.</p><p>Another bug, this time introduced in codebase written in my beloved F#.</p><p>You might think, dear Reader, how bad programmer I am as I am producing so many bugs.</p><p>This might be true, not denying that.</p><p>Let&#x27;s see what can we learn this time.</p><h3 id="we-need-more-options"><a href="#we-need-more-options" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>We need more options!</h3><p>This &quot;subtle&quot; thing slipped through three, maybe four years ago.</p><p>It might not have been that hard to fix, but truly it was difficult to find.</p><p>Imagine that we are integrate with an API (we don&#x27;t own it) that is responsible for managing tasks that human beings can pick and work on them.</p><p>There&#x27;s a concept of a &quot;reason&quot; - why this task was created.</p><p>Someone decided to model those two concepts in a way that a task might have multiple reasons (why not?).</p><p>We could manifest this little problem area as follows:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">Task</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
</span><span class="code-line">    Reason<span class="token punctuation">:</span> <span class="token class-name">string</span> seq
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>So far so good. We are clearly doing DDD right, aren&#x27;t we?</p><p>Turns out that even though there&#x27;s a collection of reasons, we were told that in 99.999999% there&#x27;s only one reason that is attached to a task.</p><p>Within our system&#x27;s boundary, when we consume this information, we must use this reason for presentation purposes so that people can take some actions/decisions based on it.</p><p>Ok, so let&#x27;s play a roulette and try getting the first <code>Reason</code>:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> reason<span class="token punctuation">:</span> <span class="token class-name">string</span> option <span class="token operator">=</span> receivedTasks <span class="token operator">|&gt;</span> Seq<span class="token punctuation">.</span>tryHead 
</span></code></pre></div></div><p>Boom, that was easy.</p><p>Yeah, let&#x27;s put even more DDD into it!</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">Reason</span> <span class="token operator">=</span> Reason <span class="token keyword">of</span> taskReason<span class="token punctuation">:</span> <span class="token class-name">string</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">Task</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
</span><span class="code-line">    Reason<span class="token punctuation">:</span> <span class="token class-name">Reason</span> seq
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Then our parsing logic becomes:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> reason<span class="token punctuation">:</span> <span class="token class-name">Reason</span> option <span class="token operator">=</span>
</span><span class="code-line">    receivedTasks
</span><span class="code-line">    <span class="token operator">|&gt;</span> Seq<span class="token punctuation">.</span>tryHead
</span><span class="code-line">    <span class="token operator">|&gt;</span> Option<span class="token punctuation">.</span>map Reason
</span></code></pre></div></div><p>No primitive obsession, right? We are expressing <a href="https://talesfrom.dev/blog/language-of-the-problem">Language of the problem</a>.</p><h3 id="no-options"><a href="#no-options" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>No options?</h3><p>As we got our lovely task with the reason, somewhere down the processing pipeline (in another file), an assumption has been encoded.</p><p>The assumption that each task almost always has a reason.</p><p>So there was a usage of task&#x27;s <code>Reason</code>:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> consume <span class="token punctuation">(</span>reason<span class="token punctuation">:</span> <span class="token class-name">Reason</span> option<span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">    <span class="token comment">//...</span>
</span><span class="code-line">    <span class="token keyword">let</span> <span class="token punctuation">(</span>Reason reason&#x27;<span class="token punctuation">)</span> <span class="token operator">=</span> reason<span class="token punctuation">.</span>Value
</span><span class="code-line">    consumeReasonAsText reason&#x27;
</span><span class="code-line">    <span class="token comment">//...</span>
</span></code></pre></div></div><p>I hope you see the potential issue there.</p><p>Never trust the incoming data.</p><p>After 3-4 years in production, a task came in without any reason (pun intended).</p><p>It turned out that there was a data consistency problem, outside of the our system&#x27;s boundary.</p><p>The bug got fixed, as always fixing it is easier when you know what the problem is.</p><p>Can we do a little thought experiment and check what we could do?</p><h3 id="option-i-see-a-result"><a href="#option-i-see-a-result" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Option? I see a result</h3><p>Yeah, <code>Option</code> might not be the perfect choice there.</p><p>No information gets carried, regarding the reason of failure (pun intended).</p><p>So maybe then we should use <code>Result</code> type and put meaningful information in the error path?</p><p>We would get the following:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> reason<span class="token punctuation">:</span> <span class="token class-name">Result</span><span class="token operator">&lt;</span>Reason<span class="token punctuation">,</span> string<span class="token operator">&gt;</span> <span class="token operator">=</span>
</span><span class="code-line">    <span class="token keyword">match</span> receivedTasks <span class="token operator">|&gt;</span> Seq<span class="token punctuation">.</span>tryHead <span class="token keyword">with</span>
</span><span class="code-line">    <span class="token operator">|</span> Some reason <span class="token operator">-&gt;</span> Ok reason
</span><span class="code-line">    <span class="token operator">|</span> None <span class="token operator">-&gt;</span> Error <span class="token string">&quot;missing reason for a task&quot;</span>
</span></code></pre></div></div><p>Better, at least we see the possible intention.</p><p>Still, I am not convinced with this result (pun intened). We expressed the knowledge about the problem as a <code>string</code>.</p><p>So even though we are in F#, we did stringly-typed programming.</p><p>Shame on me, shame on me.</p><p>We know that there is a single scenario that might be considered as almost impossible to be reached - missing reason.</p><p>Why not modelling it explicitly?</p><p>Then our code becomes:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">GettingReasonError</span> <span class="token operator">=</span> MissingReason <span class="token comment">// when more problems are found, add more cases</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">let</span> reason<span class="token punctuation">:</span> <span class="token class-name">Result</span><span class="token operator">&lt;</span>Reason<span class="token punctuation">,</span> GettingReasonError<span class="token operator">&gt;</span> <span class="token operator">=</span>
</span><span class="code-line">    <span class="token keyword">match</span> receivedTasks <span class="token operator">|&gt;</span> Seq<span class="token punctuation">.</span>tryHead <span class="token keyword">with</span>
</span><span class="code-line">    <span class="token operator">|</span> Some reason <span class="token operator">-&gt;</span> Ok reason
</span><span class="code-line">    <span class="token operator">|</span> None <span class="token operator">-&gt;</span> Error MissingReason
</span></code></pre></div></div><p>What a blast.</p><p>Domain modeling made truly functional.</p><h3 id="its-all-about-the-language"><a href="#its-all-about-the-language" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>It&#x27;s all about the language</h3><p>As I like using <code>Result</code> type for capturing the intent and modeling failure effects, it does not read well.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> reason<span class="token punctuation">:</span> <span class="token class-name">Result</span><span class="token operator">&lt;</span>Reason<span class="token punctuation">,</span> GettingReasonError<span class="token operator">&gt;</span> <span class="token operator">=</span> <span class="token comment">//...</span>
</span></code></pre></div></div><p>How would you read it aloud, dear Reader?</p><p>Something like: &quot;a reason is either ok of Reason or error of GettingReasonError&quot;?</p><p>I assume not.</p><p>I might be hugely biased but I feel that language, how do we communicate, is enormously important.</p><p>Code is also communicating with us, so it needs to be very clear with its intentions. (you might be interested in <a href="https://talesfrom.dev/blog/conversation-driven-design">Conversation-Driven Design</a>)</p><p>That&#x27;s why I believe <code>Either</code> would be a better choice (it is not available by default in F#):</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> reason<span class="token punctuation">:</span> <span class="token class-name">Either</span><span class="token operator">&lt;</span>Reason<span class="token punctuation">,</span> GettingReasonError<span class="token operator">&gt;</span> <span class="token operator">=</span> <span class="token comment">//...</span>
</span></code></pre></div></div><p>It somehow feels much natural when saying it aloud: &quot;a reason is either a Reason or a GettingReasonError&quot;.</p><p>Of course, one would say I am cheating because in the previous example I explicitly wrote &quot;ok of Reason&quot; and now I didn&#x27;t write &quot;left of Reason or right of GettingReasonError&quot;.</p><p>Well, maybe.</p><p>But let&#x27;s get back to our lovely tale!</p><h3 id="what-is-the-case"><a href="#what-is-the-case" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What is the case?</h3><p>We have used built-in type to express the intention of missingness.</p><p>Built-in types are great because they are easy to use.</p><p>You can just let those types flow through your fingers and boom - it&#x27;s all there.</p><p>Almost effortless work, especially in such a language like F#.</p><p>It looks easy, but <a href="https://talesfrom.dev/blog/simple-isnt-easy">Simple isn&#x27;t easy</a>.</p><p>One of the conclusions, coming from <a href="https://www.youtube.com/watch?v=SxdOUGdseq4&amp;ab_channel=StrangeLoopConference">&quot;Simple made easy&quot;</a> presentation I mentioned in <a href="https://talesfrom.dev/blog/simple-isnt-easy">previous</a> blog post was:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Simplicity often mean making more things, not fewer</p></div></div></div><p>Even though it is really easy to utilize built-in types, it might not be simple.</p><p>And there are two assumptions, invisible for ourselves when we have such way of thinking: it is easy <strong>now</strong>, <strong>for me</strong>.</p><p>If we <a href="https://talesfrom.dev/blog/slow-down">Slow down</a> a bit and re-consider our model, eventually <a href="https://talesfrom.dev/blog/rethinking-missingness">Rethinking &quot;missingness&quot;</a>.</p><p>In F# we are blessed with discriminated unions and our domain model could be free from any effects (like <code>Option</code>, <code>Result</code> or <code>Async</code>).</p><p>One could say: &quot;Damian, but <code>option</code> serves exactly that purpose - it models missingness&quot;.</p><p>While this might be true, it does not tell us why things are not there.</p><p>And <code>Result</code> type is typically associated with &quot;failures&quot;.</p><p>I would like my model to tell this story (or tale).</p><p>What would you say about such model, dear Reader?</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">SingleReason</span> <span class="token operator">=</span> SingleReason <span class="token keyword">of</span> reason<span class="token punctuation">:</span> <span class="token class-name">string</span>
</span><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">Reason</span> <span class="token operator">=</span> Expected <span class="token keyword">of</span> <span class="token class-name">SingleReason</span> <span class="token operator">|</span> MissingReason
</span></code></pre></div></div><p>When more cases will appear, we would be able to work with this model and let it express the language we would typically use.</p><p>Of course, it&#x27;s just a toy problem and we could argue between using <code>Result</code> and this custom type.</p><p>Nevertheless, there&#x27;s a point to be made.</p><h3 id="dont-fool-others---including-future-yourself"><a href="#dont-fool-others---including-future-yourself" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Don&#x27;t fool others - including future yourself</h3><p>Even though we worked with awesome language that F# is - it&#x27;s still our responsibility to provide a solution to the given problem.</p><p>Couple of years back, I did something that was easy.</p><p>I don&#x27;t recall the context - maybe I was rushing as it was super critical to be solved in a limited amount of time.</p><p>Maybe my son came to this beautiful world and I was sleeping -2 hours during the night.</p><p>Can&#x27;t really say.</p><p>What comes to my mind right now is that quality needs time.</p><p>Time for thinking, capturing the right concepts and terms, eventually manifesting them and embedding into the code as our model.</p><p>And this is actually one of the biggest impacts of DDD-like thinking - each time we solve a problem, we build a model.</p><p>A model of our understanding.</p><p>Understanding of the problem - all the concepts, rules between them, their interactions and eventually - relationships.</p><p>Our understanding might change, so the model should too.</p><p>In F#, expressing your intentions is really, really easy - sometimes it&#x27;s not simple, as we need to build up the understanding, but the language is so powerful and enabling.</p><p>Such exercise that we had throughout this little tale, dear Reader, would not have been that easy in, e.g. C#</p><p>Not because C# does not provide means and ways of achieving similar level of expressivity, but because fellow team members might not be used to such a way of thinking.</p><p>One might call it &quot;proper modelling&quot;, whereas another person might label it as &quot;overengineering&quot;.</p><p>Everything boils down to &quot;it depends&quot;.</p><p><strong>Now, for me</strong>, an author of this code, it might be easy to use primitive types and not focus on capturing the right language, expressing the concepts living in the domain, via types.</p><p><strong>In the future, for future myself or you</strong>, it might be crucial to comprehend the code in the effortless way.</p><h3 id="easy-becomes-complex"><a href="#easy-becomes-complex" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Easy becomes complex</h3><p>Readability is one of the highest qualities of what we are doing.</p><p>When I read the code I wrote one week ago, I might consider that <a href="https://talesfrom.dev/blog/i-dont-know">I don&#x27;t know</a> what&#x27;s there - how quickly can I catch up?</p><p>Many times, many people, in many places, stated that programmers more often read code rather than write it.</p><p>Easy will become complex, eventually, but <strong>now</strong>, <strong>for me</strong>, it might look as the best way of solving this problem.</p><p>Don&#x27;t get me wrong, I am not agitating and advocating building a huge hierarchy of classes or trying to predict the future and adding functionality &quot;just in case&quot;.</p><p>Reveal your intentions through the code - be expressive, play with your model.</p><p>Don&#x27;t be afraid of using such tools like <a href="https://github.com/mcintyre321/OneOf">OneOf</a>, <a href="https://github.com/gvergnaud/ts-pattern">ts-pattern</a>, <a href="https://github.com/vkhorikov/CSharpFunctionalExtensions">CSharpFunctionalExtensions</a> or similar (based on your programming language), in order to express your intentions.</p><p>Even if they might increase <a href="https://talesfrom.dev/blog/the-cost-of-modeling">The cost of modeling</a>, it might be just an assumption.</p><p>We should ask ourselves - what will I get when I organize the model/the code in such a way? (what do I mean by &quot;organize&quot;? You might be interested in <a href="https://talesfrom.dev/blog/the-ambiguity-of-software-architecture">The ambiguity of software architecture</a>).</p><p>Next time, dear Reader, <a href="https://talesfrom.dev/blog/slow-down">Slow down</a>, think about the problem you are trying to solve, and model things accordingly - remember about <a href="https://talesfrom.dev/blog/the-value-of-value-objects">The value of Value Objects</a>!</p><p>Future yourself will thank you (and maybe me?).</p>]]></content:encoded>
    <pubDate>Fri, 17 Nov 2023 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>fundamentals</category><category>domain-driven design</category><category>software design</category><category>simplicity</category><category>software architecture</category><category>software</category><category>modeling</category><category>models</category><category>contexts</category><category>principles</category><category>patterns</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/simple-isnt-easy</guid>
    <title>Simple isn&#39;t easy</title>
    <link>https://talesfrom.dev/blog/simple-isnt-easy</link>
    <description>Why simplicity does not require less but more?</description>
    <content:encoded><![CDATA[<h3 id="you-can-run-but-you-cant-hide"><a href="#you-can-run-but-you-cant-hide" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>You can run but you can&#x27;t hide</h3><p>The destiny is merciless.</p><p>The time has come and I made the full circle - I had exposition to code written, probably by me, 8 years ago.</p><p>Angular.js 1.x, pure JavaScript, no tests (who writes tests...Don&#x27;t I trust myself?!).</p><p>Turns out that there was a bug.</p><p>Was it truly a bug?</p><p>Or maybe it was rather a behavior of &quot;the system&quot;, unintentionally designed?</p><p>Built-in without proper usage considerations?</p><p>Still, something I needed to help taking care of!</p><h3 id="what-is-the-duration-of-code"><a href="#what-is-the-duration-of-code" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What is the duration of code?</h3><p>Except the issue itself was pretty easy to be tracked down, I found this piece of behavior:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-js code-highlight"><span class="code-line"><span class="token keyword">var</span> duration <span class="token operator">=</span> token<span class="token punctuation">.</span><span class="token property-access">duration</span>
</span><span class="code-line"><span class="token keyword control-flow">if</span><span class="token punctuation">(</span>duration <span class="token operator">&gt;</span> <span class="token number">60</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// react to duraction is less than 60 </span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>With high chances, I wrote this code.</p><p>What was I thinking back then?</p><p>What does &quot;60&quot; mean? There&#x27;s &quot;duration&quot; which points at time domain.</p><p>Everything was placed in the access token and authentication surroundings - possibly it said something about for how long this token is going to be valid?</p><p>So this magic &quot;60&quot; might mean minutes, maybe seconds; for sure not tons, meters or pieces.</p><h3 id="time-passed"><a href="#time-passed" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Time passed</h3><p>Of course, it&#x27;s not that easy to show you, dear Reader, all the code around, but bear with me.</p><p>I spend a little more time to figure out what&#x27;s happening there, as I couldn&#x27;t let go this feeling of not understanding it.</p><p>A personal flaw of mine.</p><p>Turned out that it was checking how much time was left before token will eventually expire.</p><p>Easy.</p><p>We could just leave it as it is because it wasn&#x27;t the point of my journey in this past, this historical piece of code.</p><p>The &quot;original&quot; bug was already fixed, or rather the new extension of behavior was provided.</p><p>But hey, let&#x27;s do the experiment - what could we do there to improve the readability of the code?</p><h3 id="no-magic"><a href="#no-magic" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>No magic</h3><p>This magical &quot;60&quot; turned out to be the time left before token expiration - 60 seconds.</p><p>So in other words, if one minute was left before expiration, we need to do some action.</p><p>How this could be then improved?</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-js code-highlight"><span class="code-line"><span class="token keyword module">import</span> <span class="token punctuation">{</span> <span class="token constant">ONE_MINUTE</span> <span class="token punctuation">}</span> <span class="token keyword module">from</span> <span class="token string">&quot;@/common/time&quot;</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">var</span> duration <span class="token operator">=</span> token<span class="token punctuation">.</span><span class="token property-access">duration</span>
</span><span class="code-line"><span class="token keyword control-flow">if</span><span class="token punctuation">(</span>duration <span class="token operator">&gt;</span> <span class="token constant">ONE_MINUTE</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// ...</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Not bad, now at least we put the bare, naked number in a specific context - time domain.</p><p>If someone peeks <code>ONE_MINUTE</code>, he or she will see &quot;60&quot; - so there might be a little glitch when reading.</p><p>&quot;ONE&quot; vs &quot;60&quot; might be not challenging at all, but jumping between levels might take some mana points.</p><p>An alternative?</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-js code-highlight"><span class="code-line"><span class="token keyword">var</span> duration <span class="token operator">=</span> token<span class="token punctuation">.</span><span class="token property-access">duration</span>
</span><span class="code-line"><span class="token keyword control-flow">if</span><span class="token punctuation">(</span>duration <span class="token operator">&gt;</span> <span class="token number">60</span> <span class="token comment">/*seconds*/</span><span class="token punctuation">)</span>
</span></code></pre></div></div><p>Well, it communicates the time-intention there, so no naked number. Also, this communication goes on the same &quot;cognition level&quot; so there will be no &quot;one to sixty&quot; glitch-like surprise.</p><p>Could we do better?</p><h3 id="stop-primitive-thinking"><a href="#stop-primitive-thinking" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Stop primitive thinking</h3><p>Remember this is pure JS, so no types at all.</p><p>What if we take this time domain more seriously.</p><p>So seriously that we will capture this language in a programming constructs.</p><p>Let&#x27;s see how it could look like.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-js code-highlight"><span class="code-line"><span class="token keyword">var</span> duration <span class="token operator">=</span> token<span class="token punctuation">.</span><span class="token property-access">duration</span>
</span><span class="code-line"><span class="token keyword control-flow">if</span> <span class="token punctuation">(</span>duration<span class="token punctuation">.</span><span class="token property-access function method">isGreaterThan</span><span class="token punctuation">(</span><span class="token maybe-class-name">Time</span><span class="token punctuation">.</span><span class="token property-access"><span class="token maybe-class-name">OneMinute</span></span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// ...</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>To achieve so, we would need to introduce a new class:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-js code-highlight"><span class="code-line"><span class="token keyword module">export</span> <span class="token keyword">class</span> <span class="token class-name">Duration</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token function">isGreaterThan</span><span class="token punctuation">(</span><span class="token parameter">threashold</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">// ...</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token comment">// and</span>
</span><span class="code-line"><span class="token keyword module">export</span> <span class="token keyword">class</span> <span class="token class-name">Time</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">static</span> <span class="token maybe-class-name">OneMinute</span> <span class="token operator">=</span> <span class="token maybe-class-name">Time</span><span class="token punctuation">.</span><span class="token property-access function method">of</span><span class="token punctuation">(</span><span class="token number">60</span> <span class="token comment">/*seconds*/</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>I predict we would need to add something around 60-100 lines more to achieve that expresiveness.</p><p>If I came to this place next time, I would need less time to orient myself.</p><p>Someone could say: &quot;how often you visit this code? Probably not that often. Leave it, cost-to-benefit ratio doesn&#x27;t look good&quot;.</p><p>Well, that might be true. With high chances, I might not need to see this code in next 8 years.</p><p>This might be regarded as complete waste of time and resources to &quot;overengineer&quot; this code in that way.</p><p>On the other hand, how might one know how often such place in the code is going to be visited?</p><p>Magical orb, black cat and oracle-like foresight?</p><h3 id="could-an-understanding-ever-expire"><a href="#could-an-understanding-ever-expire" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Could an understanding ever expire?</h3><p>Let&#x27;s give us one more chance to grow this piece of code.</p><p>We know that we operate in the time domain AND it is about the token expiration.</p><p>What if we do something like this:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-js code-highlight"><span class="code-line"><span class="token keyword control-flow">if</span><span class="token punctuation">(</span>token<span class="token punctuation">.</span><span class="token property-access function method">willExpire</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">// ...</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>So instead of treating &quot;token&quot; as a bag of data, we treat it as &quot;a thing&quot;, that can manage on its own, within the boundaries of the language.</p><p>Then, a definition of the <code>token</code> might look like:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-js code-highlight"><span class="code-line"><span class="token keyword module">export</span> <span class="token keyword">class</span> <span class="token class-name">AccessToken</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">accessToken<span class="token punctuation">,</span> timeBeforeExpiration</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> 
</span><span class="code-line">        <span class="token comment">// ...</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token function">willExpire</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword control-flow">if</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span><span class="token property-access">_duration</span><span class="token punctuation">.</span><span class="token property-access function method">isGreaterThan</span><span class="token punctuation">(</span>timeBeforeExpiration<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token comment">// ...</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>In this case, we might increase number of lines to maintain by 100-200 lines.</p><p>So overengineering.</p><p>Who does write code in that way?!</p><h3 id="you-never-know"><a href="#you-never-know" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>You never know</h3><p>8 years ago I didn&#x27;t consider I was writing this code for future myself to see.</p><p>I just wrote the code.</p><p>Just placed those characters, those ifs, those numbers to finish a task.</p><p>Complete a feature.</p><p>One might say that this part of code might not be critical so there&#x27;s no need to put the highest quality in it.</p><p>What&#x27;s more, we work with highly intelligent people, full of insightful practices and skills, so decoding this code will be easy for them.</p><p>It all might be true.</p><p>But when you take the perspective of next 2 months, next 2 years, next 2 decades - someone might eventually look at the code you wrote - including yourself.</p><p>Don&#x27;t make them thinking too much.</p><p>All those transformations we made along this tale produced much more code.</p><p>There was much more code, not less.</p><p>But this served the specific purpose - readability, understability and contextual thinking.</p><p>Bare strings, naked numbers, raw bools do not carry the context with itself.</p><h3 id="the-value-of-value-objects"><a href="#the-value-of-value-objects" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The value of Value Objects</h3><p>Many people do not see <a href="https://talesfrom.dev/blog/the-value-of-value-objects">The value of Value Objects</a>.</p><p>Such constructs might easily be called &quot;primivite values&#x27; wrappers&quot;, because they don&#x27;t have any behavior.</p><p>And in such model of thinking, this leads to &quot;overengineering&quot; - &quot;YAGNI&quot; they say.</p><p>To me, there&#x27;s a &quot;behavior&quot; that is not visible in the code.</p><p>I mean, you can&#x27;t &quot;dot&quot; it and get some meaningful, domain-oriented operations (other than <code>toString</code> and similar).</p><p>This behavior is <strong>communication of the intent</strong>.</p><p>It is very subtle, implicit. It helps one to <a href="https://talesfrom.dev/blog/slow-down">Slow down</a>, absorb the context and build up the understanding.</p><p>Types capture the context, and it gets carried everywhere this thing appears.</p><p>And regarding &quot;the value of wrappers&quot; - it might not be directly visible because it manifests itself later, in the future, <strong>not now</strong>.</p><p>I haven&#x27;t expected to browse the code I wrote 8 years ago - I would rather have said this code would extinct in next 2 years from writing, back then.</p><p>I really like how Steve Freeman and Nat Pryce described it in <a href="https://www.amazon.com/Growing-Object-Oriented-Software-Guided-Tests/dp/0321503627">&quot;GOOS&quot;</a>:</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">Growing Object-Oriented Software: Budding off</div><div class="pb-2 px-3"><div class="break-words"><p>When we want to mark a new domain concept in the code, we often introduce a placeholder type that wraps a single field, or maybe has no fields at all. As the code grows, we fill in more detail in the new type by adding fields and methods. With each type that we add, we&#x27;re raising the level of abstraction of the code.</p></div></div></div><p>Each concept becomes manifested as &quot;a placeholder&quot; to grow.</p><p>It all raises the level of abstraction we operate with - and yet again we might misunderstand the intention of abstraction (you might be interested in <a href="https://talesfrom.dev/blog/the-ambiguity-of-abstraction">The ambiguity of abstraction</a>).</p><p>It serves the purpose of embedding the right language in the right place, expressing <a href="https://talesfrom.dev/blog/language-of-the-problem">Language of the problem</a> so that we can reason about the &quot;code&quot; in higher-order way.</p><p>For me, similar heuristics apply to so-called &quot;strongly-typed identifiers&quot; - creating a specific boundary for expressing meaning around <code>Guid</code>, e.g. <code>TenantId</code> or <code>ProcessingId</code>, leaves some space to be filled when there&#x27;s a need.</p><p>If we treat each concept&#x27;s manifestation in a &quot;mechnical way&quot; - and call working with them as &quot;wrapping and unwrapping&quot; - well, no doubt that we might find it as unnecessary overhead.</p><p>Yet again, there&#x27;s some subtle, hidden behavior - <strong>communication of the intent</strong> - even if it looks and sounds obvious, it is <strong>obvious</strong> for <strong>us</strong>, <strong>now</strong>.</p><p>Even if I need to write some more characters, add some more lines - I take this downside of more &quot;code&quot; to maintain, at the same time adopting the benefit of higher-order reasoning.</p><p>This reminds me Mark Seeman&#x27;s observation that <a href="https://blog.ploeh.dk/2018/09/17/typing-is-not-a-programming-bottleneck/">&quot;Typing is not a programming bottleneck&quot;</a>.</p><p>I am not afraid to type more, provided that I might get benefit of better understability and better readability.</p><p>What&#x27;s more, some languages require more typing (also regarded) than others which might eventually lead to the topic of <a href="https://talesfrom.dev/blog/the-cost-of-modeling">The cost of modeling</a>. I see that&#x27;s why people might get discouraged to model domain concepts accordingly.</p><p>You might hear that such code is &quot;overengineering&quot;, &quot;non-idiomatic&quot; and even get more similar labels - the best would be to ask this guy in next 5 years who might touch this part of code and look at bare strings, naked numbers and primitive booleans, without encapsulation and with no composition.</p><p>For sure, such code is easy to write.</p><h3 id="simple-isnt-easy"><a href="#simple-isnt-easy" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Simple isn&#x27;t easy</h3><p>In his great and insightful presentation, <a href="https://www.youtube.com/watch?v=SxdOUGdseq4&amp;ab_channel=StrangeLoopConference">&quot;Simple made easy&quot;</a>, Rich Hickey showed us how we can understand something that is &quot;simple&quot;, &quot;complex&quot; or &quot;easy&quot;.</p><p>&quot;Easy&quot; might not be &quot;simple&quot;, and &quot;simple&quot; migh not be &quot;easy&quot;.</p><p>They express two different perspectives on doing things.</p><p>If you haven&#x27;t seen this presentation, dear Reader, stop right now and watch it - you won&#x27;t regret it.</p><p>In one of his slides, one can see the following:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Simplicity often mean making more things, not fewer</p></div></div></div><p>That&#x27;s why I consider simplicity as not easy state to reach.</p><p>It requires one to dive into complexity, decompose problem into manageable parts, yield understanding and meaning, and eventually come back and compose everything with simplicity in mind.</p><p>Similar conclusion also appears in Rich&#x27;s slide:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Create abstractions with simplicity as basis</p></div></div></div><p>In our tiny tale we saw that we could grow our software - and it required more parts, not less.</p><p>This mantra of conflating &quot;less things&quot; with simplicity - might eventually be very harmful.</p><p>Simple isn&#x27;t easy, it requires effort to explore the problem area, learn language and find out concepts that are relevant to the context, eventually picking what is worth modeling.</p><p>And it all takes time.</p><p>Don&#x27;t afraid to say <a href="https://talesfrom.dev/blog/i-dont-know">&quot;I don&#x27;t know&quot;</a>, <a href="https://talesfrom.dev/blog/slow-down">Slow down</a> and face complexity, eventually finding simplicity.</p><p>You never know if code you just wrote survives next 10 years and you will get back to it.</p>]]></content:encoded>
    <pubDate>Sat, 11 Nov 2023 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>fundamentals</category><category>domain-driven design</category><category>software design</category><category>simplicity</category><category>software architecture</category><category>software</category><category>modeling</category><category>models</category><category>contexts</category><category>principles</category><category>patterns</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/the-ambiguity-of-composition</guid>
    <title>The ambiguity of composition</title>
    <link>https://talesfrom.dev/blog/the-ambiguity-of-composition</link>
    <description>How can we represent composition?</description>
    <content:encoded><![CDATA[<h3 id="any-experts-here"><a href="#any-experts-here" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Any experts here?</h3><p>Imagine that we were challenged to organize a process (what do I mean by &quot;organize&quot;? you might be interested in <a href="https://talesfrom.dev/blog/the-ambiguity-of-software-architecture">The ambiguity of software architecture</a>) in which we need to work on some documents, on behalf of our customers.</p><p>We have plenty of resources at our disposal but one of the main factors is a workspace in which the experts will do their best to deliver value.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/experts-room-empty.png" class="max-h-[30rem]"/></div><div class="italic mx-24">An empty room waiting to be used by experts</div></div><p>They (experts) enter the room through &quot;for staff only&quot; door and get the document that is delivered through &quot;main entrance&quot;.</p><p>Typically they have all the knowledge to finish their task - most of the results are delivered outside of the room by some experts, through &quot;main exit&quot;.</p><h3 id="handle-that-document-please"><a href="#handle-that-document-please" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Handle that document, please!&quot;&quot;</h3><p>Imagine we&#x27;ve invited bunch of experts to deal with coming documents.</p><p>There&#x27;s one coordinator, or &quot;process expert&quot;, that knows what are the &quot;coarse-grain&quot; steps to be followed.</p><p>The rest of the crew are experts on providing some kind of services.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/experts-room-processing-1.png" class="max-h-[30rem]"/></div><div class="italic mx-24">Experts waiting to get things done</div></div><p>Through the main entrance a document is going to be delivered and process expert will be responsible for guiding what to do.</p><p>Others, by their expertise, will know how to deal with a particular stage.</p><p>As outcomes of such collaborative work, multiple facts will happen.</p><p>For the purpose of this tiny tale, here are the steps that the coordinator need to ensure to happen:</p><ol><li>Syntactic details verification</li><li><span class="text-[#2d823d]">Formal tone verification</span></li><li><span class="text-[#d783eb]">Customer importance evaluation</span></li><li><span class="text-[#965200]">Content&#x27;s legal aspects verification</span></li><li>Actual document processing (signing, etc.)</li><li><span class="text-[#478cca]">Customer notification or customer notification with a delay and processed document archiving</span></li></ol><p>As you can notice, dear Reader, some of the responsibilities might be in hands of the coordinator too (check the colors).</p><p>Of course, we are not naive - no one is omnipotent and knows everything - sometimes experts on providing a particular service need to get some help from their colleagues.</p><p>They need to refer to them and call them for help.</p><p>The important part here is that their mates might be located in different room, different floor or even different building! (if you are more interested in this kind of metaphor, please check <a href="https://talesfrom.dev/blog/organization-driven-design">&quot;Organization-Driven Design&quot;</a> and <a href="https://talesfrom.dev/blog/modularity-uncertainty-heuristic">Modularity Uncertainty Heuristic</a>)</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/experts-room-processing-mates.png" class="max-h-[30rem]"/></div><div class="italic mx-24">Service provider getting help from his collaborators</div></div><p>For the coordinator, it doesn&#x27;t really matter (or it does?) how a given expert delivers a service - job needs to be done.</p><p>One could imagine that even a simple task might involve various people, from various places.</p><h3 id="why-the-hell-did-you-call-me"><a href="#why-the-hell-did-you-call-me" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Why the hell did you call me?!&quot;</h3><p>Imagine a scenario when a document is delivered and the process expert takes (1) step - he verifies syntactic details of the document.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/experts-room-processing-syntactic-mistake.png" class="max-h-[30rem]"/></div><div class="italic mx-24">The process coordinator takes the lead and works on the first stage</div></div><p>It turns out that there are some mistakes - a document issuer filled some of the fields incorrectly.</p><p>Other experts were invited to the room already but their skills were not able to be used.</p><p>The coordinator yelled &quot;we have an exception - syntactic verification failed!&quot;.</p><p>The rest of the crew just looked at each other - no expected outcome was delivered out through the main exit.</p><p>Further processing was rejected.</p><p>Initially, everyone felt busy - you know, getting invitation to the &quot;war room&quot; and this kind of things.</p><p>The more silly mistakes were present in the document and the more &quot;syntactic verification failures&quot; were communicated by the process expert, the more other experts got angry.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><span class="italic"><span class="text-[#965200]">Expert on legal matters</span>: Why the hell did you call me? I am waiting to get my turn but for most of the time you&#x27;re just yelling something about exceptional cases - what&#x27;s wrong with you?</span></span><span class="text-white"> </span><span class="text-white"><span class="italic"><span class="font-bold">Process expert</span>: We are team, aren&#x27;t we? I thought you might be needed to help me but you see what&#x27;s the case - most of the work is useless until we have this silly mistakes fixed.</span></span><span class="text-white"> </span><span class="text-white"><span class="italic"><span class="text-[#d783eb]">Expert on customer importance</span>: Do you want to see the pile of importance elevation requests on my desk? I have stuff to do!</span></span></div><p>Even if exceptional &quot;syntactic mistakes&quot; were not present anymore, other kinds of scenarios happened - formal tone wasn&#x27;t meeting the corporate requirements and so on.</p><p>Some of the experts were just sitting there and waiting until they&#x27;re getting something to work on.</p><p>Eventually, the outcomes were delivered through the main exit by <span class="text-[#478cca]">Delivery expert</span>.</p><p>However, most of the times something wasn&#x27;t right and only yelling could be heared from outside of the experts&#x27; room.</p><h3 id="i-depend-on-you-guys"><a href="#i-depend-on-you-guys" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;I depend on you, guys!&quot;</h3><p>The coordinator needed to beg other experts to come to the room to get things done - he promised that their time will be respected.</p><p>Fortunately and unfortunately, changes never change - they happen and occur, even if we think everything is and will be stable.</p><p>Same happened to our process expert - turned out that he needed to get help from more &quot;dependencies&quot; - as corporate called this kind of relationship.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/experts-room-processing-more-dependencies.png" class="max-h-[30rem]"/></div><div class="italic mx-24">More experts need more space to collaborate</div></div><p>Process also get a &quot;little&quot; more complex - there were more expected outcomes, each expert was able to break the entire workflow just by shouting &quot;I have an exception X, we need to stop here&quot;.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/experts-room-processing-more-frustration.png" class="max-h-[30rem]"/></div><div class="italic mx-24">Experts yelling at each other, the room is full of anger and frustration</div></div><p>&quot;I depend on you, guys!&quot; said the coordinator with huge sadness.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><span class="italic"><span class="text-[#d783eb]">Expert on customer importance</span>: Come on, call me into the meeting only when you are sure that you have syntactically correct document, with correct formal tone.</span></span><span class="text-white"> </span><span class="text-white"><span class="italic"><span class="font-bold">Process expert</span>: I understand your point but according to the corporate policies, I need to organize the work in the way that we...</span></span><span class="text-white"> </span><span class="text-white"><span class="italic"><span class="text-[#d783eb]">Expert on customer importance</span>: Just call me when you have verified that sytntactically and formally everything is fine, I&#x27;m leaving.</span></span></div><h3 id="another-way-of-organizing-the-work"><a href="#another-way-of-organizing-the-work" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Another way of organizing the work?</h3><p>Imagine that our process expert decided to organize the collaboration in a slightly different manner.</p><p>Instead of finding one, big workspace, he thought of many, smaller rooms where each expert might get focused work, when everything is ready for his or her stage.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/experts-tiny-room.png" class="max-h-[30rem]"/></div><div class="italic mx-24">Smaller room for focused work, by coincidence it is rotated vertically</div></div><p>Another interesting policy that we introduced was that when a document will be pushed through the main exit to another room&#x27;s main entrance, it needs to be &quot;labeled&quot; in a specific way.</p><p>Based on this labeling, him, the coordinator, will be able to decide if further processing is required or not.</p><p>Experts&#x27; time is worth much of gold and he didn&#x27;t want to get anyone angry anymore.</p><p>After organizing the collaboration in this way, experts still were able to invite some other people to get help but at least they were pretty confident that it&#x27;s right moment to do so.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/experts-sequential-work.png" class="max-h-[40rem]"/></div><div class="italic mx-24">Experts waiting to get their turn only when everything is checked</div></div><p>From now, yelling isn&#x27;t that effective as each expert might be located in a different room.</p><p>They started communicating through well-defined contracts - it became very explicit and visual when things got incorrect - the result was immediately discarded by the process expert and others were not even bothered.</p><p>Was it easy? Oh no, believe me - they needed to change their habits and learn that instead of yelling they can return results in a slightly different form.</p><p>Those results stated if there&#x27;s an error or if everything is ok.</p><p>And for others - when they did some evaluation or scored something, like <span class="text-[#d783eb]">Expert on customer importance</span>, they were able to state a certain fact. Then, this fact was propagated further and someone was able to interpret it in his or her way.</p><p>Eventually, <span class="text-[#478cca]">Delivery expert</span> was able to decide what to do, based on the facts that happened throught the process.</p><p>What is also important, all the results pushed through the main exit, there were just for reading - no one was able to change them when they received their &quot;copy&quot; through main entrances.</p><p>When someone required getting help from his or her mates, the room got slightly larger - but only the experts required at that stage were invited.</p><h3 id="composition"><a href="#composition" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Composition?</h3><p>Some ages ago, I <a href="https://twitter.com/raimeyuu/status/1632109684202110977">posted</a> a little visualization that emerged in my head. Along with confusion and questions, it got plenty (in the scale of mine) attention within the community.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/fp-and-oop.jpeg" class="max-h-[40rem]"/></div><div class="italic mx-24">Visualizing various paradigms</div></div><p>I didn&#x27;t purposefully write any legend or description, as I was very curious how others could project their mental representations, in a kind of <a href="https://en.wikipedia.org/wiki/Rorschach_test">Rorschach test</a>.</p><p>Some months passed, I observed more code and codebases, I participated in various interesting discussions.</p><p>Somehow it become obvious that the well-known, fundamental attribute of our designs - composition - exists in many forms, even though we refer to it as just &quot;composition&quot;.</p><p>What is even more interesting - different languages and paradigms encourage or discourage some of its forms.</p><h3 id="horizontal-composition"><a href="#horizontal-composition" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Horizontal composition</h3><p>One of the typical way of referring to &quot;external service providers&quot; is calling them <strong>dependencies</strong>.</p><p>It expresses the necessity of having them when the task is on the table (or in the room).</p><p>In our little tale, the process expert <a href="https://talesfrom.dev/blog/the-ambiguity-of-composition#i-depend-on-you-guys">&quot;I depend on you, guys!&quot;</a> was very explicit that they need to collaborate together.</p><p>I believe that there&#x27;s another name for &quot;people&quot; participating in the joint effort on solving a particular problem - <strong>collaborators</strong> (I think it was established by invention of the <a href="https://en.wikipedia.org/wiki/Class-responsibility-collaboration_card">CRC</a> cards?)</p><p>Nevertheless, in my world, it totally changes the meaning, the semantics of treating those &quot;experts&quot;.</p><p>Suddently, we might use different language - we might &quot;invite&quot;, &quot;ask for participation&quot; or postpone their appearance.</p><p>Still, how does our little metaphor relate to the code?</p><p>I believe we all have seen such a scenarios:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">TheCoordinator</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token function">TheCoordinator</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token class-name">IFormalToneVerificationService</span> formalToneVerificationService<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">ICustomerImportanceEvaluationService</span> customerImportanceEvaluationService<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">IContentLegalAspectsVerificationService</span> contentLegalAspectsVerificationService<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">ICustomerNotificationService</span> customerNotificationService<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">IDocumentArchivingService</span> documentArchivingService
</span><span class="code-line">    <span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">//...details omitted for brevity</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">Process</span><span class="token punctuation">(</span><span class="token class-name">Document</span> document<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">//...details omitted for brevity</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>(an avid Reader might notice that I included vital and helpful <code>*Service</code> suffix, to make the code looking more familiar)</p><p>A class &quot;orchestrating&quot; a given process &quot;invites&quot; many participants to get help in solving the task.</p><p>We could think of <code>TheCoordinator</code>&#x27;s constructor as &quot;for staff only&quot; door.</p><p>Then:</p><ul><li>the &quot;main entrance&quot; gets mapped into all that gets into the method</li><li>expected input is all the arguments</li><li>the &quot;main exit&quot; gets mapped into all that gets out from the method</li><li>expected outcome is all the visible &quot;return types&quot;</li></ul><p>That&#x27;s probably pretty obvious.</p><p>For now, the most important question is: how many &quot;people&quot; have been invited through the &quot;for staff only&quot; door?</p><p>Here we have only 5 experts but I do believe that both me and you, dear Reader, we saw much more &quot;people&quot; invited for collaboration.</p><p>As the number grows, &quot;the room&quot; needs to get wider too.</p><p>One might say: &quot;yeah but that&#x27;s the reason why you are hiding some of the dependencies under the abstraction!&quot;.</p><p>I am all for it. This becomes pretty visible and transparent when working with Outside-In TDD, in my humble opinion.</p><p>Especially, when one writes all stubs, fakes and mocks by hand - the pain guides to reduce the number of collaborators, or &quot;dependencies&quot;, if you will, dear Reader.</p><p>Let&#x27;s be a little honest - in most scenarios &quot;the room gets horizontally wider&quot;, instead of reducing number of &quot;invited&quot; collaborators.</p><p>In my observations, this form of composition appears mostly in OO languages.</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>How many &quot;people&quot; do you want to invite through the &quot;for staff only&quot; door?</p></div></div></div><p>&quot;Just injecting dependencies&quot; - one might say.</p><p>If one is skilled and disciplined enough, only specific roles (roles? you might be interested in <a href="https://talesfrom.dev/blog/i-interface">I, interface</a>) are getting invited and then, if they need, they refer to their collaborators to get help. (via calling them directly, or through sending them a message - you decide)</p><p>And of course, there&#x27;s another way of composing the efforts.</p><h3 id="vertical-composition"><a href="#vertical-composition" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Vertical composition</h3><p>What if, just as a pure thought experiment, we would orgnize our code similarly to what the process expert did in <a href="https://talesfrom.dev/blog/the-ambiguity-of-composition#another-way-of-organizing-the-work">Another way of organizing the work?</a>?</p><p>Then, by focusing on the responsibilities:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">IVerifySyntacticCorrectness</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">Result<span class="token punctuation">&lt;</span>SyntacticallyCorrectDocument<span class="token punctuation">,</span> SyntacticMistake<span class="token punctuation">&gt;</span></span> <span class="token function">Verify</span><span class="token punctuation">(</span><span class="token class-name">Document</span> document<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">IVerifyFormalTone</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">Result<span class="token punctuation">&lt;</span>DocumentWithFormalTone<span class="token punctuation">,</span> FormalToneProblem<span class="token punctuation">&gt;</span></span> <span class="token function">Verify</span><span class="token punctuation">(</span><span class="token class-name">SyntacticallyCorrectDocument</span> document<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">IEvaluateCustomerImportance</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>OneOf<span class="token punctuation">&lt;</span>CustomerImportance_1<span class="token punctuation">,</span> CustomerImportance_2<span class="token punctuation">,</span> CustomerImportance_3<span class="token punctuation">&gt;</span><span class="token punctuation">&gt;</span></span> <span class="token function">Verify</span><span class="token punctuation">(</span><span class="token class-name">DocumentWithFormalTone</span> document<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token comment">// ...and so on...</span>
</span></code></pre></div></div><p>(you might wonder why the hell I&#x27;m using &quot;interfaces&quot; in such a strange way - stop and read <a href="https://talesfrom.dev/blog/i-interface">I, interface</a>, then come back)</p><p>As it&#x27;s a thought experiment, we don&#x27;t want to &quot;invite&quot; all the collaborators to a single, large room - instead we should use try to organize their work in &quot;tiny rooms&quot;, distributed sequentially, in a &quot;vertical manner&quot;.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token class-name"><span class="token keyword">var</span></span> process <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">Process</span><span class="token punctuation">(</span>
</span><span class="code-line">    <span class="token keyword">new</span> <span class="token class-name constructor-invocation">SyntacticCorrectnessVerificationStep</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token keyword">new</span> <span class="token class-name constructor-invocation">FormalToneVerificationStep</span><span class="token punctuation">(</span>
</span><span class="code-line">            <span class="token keyword">new</span> <span class="token class-name constructor-invocation">CustomerImportanceEvaluationStep</span><span class="token punctuation">(</span>
</span><span class="code-line">                <span class="token keyword">new</span> <span class="token class-name constructor-invocation">ContentLegalAspectsVerificationStep</span><span class="token punctuation">(</span>
</span><span class="code-line">                    <span class="token keyword">new</span> <span class="token class-name constructor-invocation">DocumentProcessingStep</span><span class="token punctuation">(</span>
</span><span class="code-line">                        <span class="token keyword">new</span> <span class="token class-name constructor-invocation">CustomerNotificationStep</span><span class="token punctuation">(</span><span class="token comment">/* other collaborators */</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
</span><span class="code-line">                        <span class="token keyword">new</span> <span class="token class-name constructor-invocation">DocumentArchivizationStep</span><span class="token punctuation">(</span><span class="token comment">/* other collaborators */</span><span class="token punctuation">)</span>
</span><span class="code-line">                    <span class="token punctuation">)</span>
</span><span class="code-line">                <span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token comment">// imagine that `document` is of a type `Document`</span>
</span><span class="code-line"><span class="token class-name"><span class="token keyword">var</span></span> finalResult <span class="token operator">=</span> process<span class="token punctuation">.</span><span class="token function">Process</span><span class="token punctuation">(</span>document<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// it is of a type `Result&lt;DocumentProcessingResult, DocumentProcessingError&gt;</span>
</span></code></pre></div></div><p>Of course, one might say: &quot;hey, no one writes the code like that!&quot;.</p><p>We could use well-known &quot;polymorphism&quot;, abstract class with template methods to ensure sequential nature and correct order, probably we would reach the level where we would need to get &quot;chain of command&quot; design pattern.</p><p>Nevertheless, a question we&#x27;re trying to get answer to might be: how we can chain operations to get the desired result?</p><p>If we follow this reasoning, turns out all the &quot;steps&quot; form a &quot;pipeline&quot;. In an imaginary language it could look as follows:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line">document
</span><span class="code-line">processWith SyntacticCorrectnessVerificationStep
</span><span class="code-line">thenProcessWith FormalToneVerificationStep
</span><span class="code-line">thenProcessWith CustomerImportanceEvaluationStep
</span><span class="code-line">thenProcessWith ContentLegalAspectsVerificationStep
</span><span class="code-line">thenProcessWith DocumentProcessingStep
</span><span class="code-line">thenProcessInParallel <span class="token punctuation">[</span>
</span><span class="code-line">    CustomerNotificationStep<span class="token punctuation">,</span>
</span><span class="code-line">    DocumentArchivizationStep
</span><span class="code-line"><span class="token punctuation">]</span>
</span></code></pre></div></div><p>Yes, with high probability you already got me - the sequential nature of document processing didn&#x27;t disappear and we exchange one syntax to another.</p><p>An important aspect to the above, imaginary &quot;pipeline&quot;, that I found interesting to observe it&#x27;s how it affects thinking - writing small, focused and oriented &quot;steps&quot; becomes quite natural.</p><p>One focuses on behaviors instead of all the <code>-ers</code> and <code>-Service</code>s.</p><p>Suddenly, what gets through the &quot;pipeline&quot; isn&#x27;t just &quot;data&quot; - we might enclose very important facts about the process by focusing on the correct concepts.</p><p>In our little tale, we found out that there&#x27;s a slight difference between <code>SyntacticallyCorrectDocument</code> and <code>Document</code>. Not just in their structure but how they can be used.</p><p>Eventually, a <code>Document</code> might become either a <code>SyntacticallyCorrectDocument</code> or a <code>SyntacticMistake</code> (you might be interested in <a href="https://talesfrom.dev/blog/modeling-maturity-levels">Modeling Maturity Levels</a>).</p><h3 id="horizontal-and-vertical-composition"><a href="#horizontal-and-vertical-composition" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Horizontal and vertical composition</h3><p>The sequential character of processing does not disappear, it manifests itself either we use one language or another.</p><p>When it comes to collaborators, or &quot;dependencies&quot;, some languages encourage inviting them through &quot;for staff only&quot; doors, whereas discouraging other means of working with them.</p><p>In .NET space, this &quot;imaginary language&quot; from <a href="https://talesfrom.dev/blog/the-ambiguity-of-composition#vertical-composition">Vertical composition</a> already exists - it&#x27;s F# (I hope you know I am biased towards this language, sorry).</p><p>So our &quot;vertical composition&quot;, when expressed in F#, becomes:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="code-highlight language-fsharp"><span class="code-line">document
</span><span class="code-line"><span class="token operator">|&gt;</span> verifySyntacticCorrectness
</span><span class="code-line"><span class="token operator">|&gt;</span> verifyFormalTone
</span><span class="code-line"><span class="token operator">|&gt;</span> evaluateCustomerImportance
</span><span class="code-line"><span class="token operator">|&gt;</span> verifyContentLegalAspects
</span><span class="code-line"><span class="token operator">|&gt;</span> processDocument
</span><span class="code-line"><span class="token operator">|&gt;</span> <span class="token function">finalizeWith</span><span class="token punctuation">(</span>notifyingCustomer<span class="token punctuation">,</span> documentArchiving<span class="token punctuation">)</span>
</span></code></pre></div></div><p>(note that this example comes from imaginary land I can do what I want to shape it)</p><p>And yes, even if I could be accused of comparing &quot;orange to apple&quot; - I still found it useful to think of the composition in those two forms.</p><p>In my humble experience, people, using &quot;OO paradigm&quot; (or at least using languages with <code>class</code> keyword), tend to evaluate &quot;vertical composition&quot; and writing small, well-focused classes as &quot;overengineering&quot;.</p><p>Hence &quot;horizontal composition&quot; becomes bottleneck as there are so many &quot;collaborators&quot; that eventually things get &quot;underengineered&quot;.</p><p>(of course, one possible origin might be lack of behavior specification through tests - you might be interested in <a href="https://talesfrom.dev/blog/the-ambiguity-of-tdd">&quot;The ambiguity&quot; of TDD</a>)</p><p>Note I am not saying that OO paradigm is wrong, broken and no one should use it - I am just trying to show various &quot;forms&quot; of composition.</p><p>Yet again, the sequential nature of processing won&#x27;t cease to exist - it&#x27;s about the way we are organizing it to manage the complexity and &quot;focus on one thing at the single time&quot;.</p><h3 id="composition---what-are-next-steps"><a href="#composition---what-are-next-steps" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Composition - what are next steps?</h3><p>As with other aspects of human activities, the ambiguity creeps in when no one is looking.</p><p>The King of Kings is always ruling - The Context doesn&#x27;t leave his throne.</p><p>Try to think about &quot;collaborators&quot; and not &quot;dependencies&quot;.</p><p>It will change your life, believe me.</p><p>What&#x27;s more, all those collaborators play various roles so that the overall goal might get solved.</p><p>There&#x27;s short path from roles, to responsibilities, to functions - when it comes to functions, soon we&#x27;re reaching the vertical composition.</p><p>Next time, dear Reader, ask yourself a question:</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>How many collaborators need to be invited and what roles they need to play to solve the problem?</p></div></div></div>]]></content:encoded>
    <pubDate>Tue, 24 Oct 2023 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>principles</category><category>fundamentals</category><category>guidelines</category><category>programming</category><category>modeling</category><category>model</category><category>contexts</category><category>representations</category><category>mental models</category><category>heuristics</category><category>principles</category><category>patterns</category><category>design-thinking</category><category>concepts</category><category>software architecture</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/the-ambiguity-of-software-architecture</guid>
    <title>The ambiguity of software architecture</title>
    <link>https://talesfrom.dev/blog/the-ambiguity-of-software-architecture</link>
    <description>What do we mean by &quot;software architecture&quot;?</description>
    <content:encoded><![CDATA[<h3 id="party-people"><a href="#party-people" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Party people</h3><p>Imagine that we were asked by our friends, a couple, to help them organizing their the wedding.</p><p>It&#x27;s a big deal, as there are so many moving parts!</p><p>What about the food?</p><p>What should be the ratio of traditional meals, in comparison to &quot;modern&quot; ones?</p><p>Don&#x27;t forget about vegeterians!</p><p>Yeah, food is one thing, but what about the seats?</p><p>Should we group young people together and leave older people sitting next to each other?</p><p>Don&#x27;t forget that auntie Dorothy doesn&#x27;t like talking with auntie Marie!</p><p>Music - what&#x27;s should be the ratio between good&#x27;n&#x27;old songs and the latest pop hits?</p><p>There&#x27;s no good or bad decision, we just need to understand the conditions we have.</p><p>Let&#x27;s focus on the way we organize seats.</p><h3 id="far-from-the-dj-yes-please"><a href="#far-from-the-dj-yes-please" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Far from the DJ? Yes, please!</h3><p>Turns our there are much more constraints we need to take into account when we are organizing the seats.</p><p>People have their local preferences that sometimes are pretty darn impossible to satisfy!</p><p>Eventually, everything becomes clear when we went into the place where entire celebration will take place.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-architecture-wedding-seats.png" class="max-h-[30rem]"/></div><div class="italic mx-24">A pattern of tables and seats available at the wedding premise</div></div><p>Well, this situation constrains as a bit.</p><p>We won&#x27;t be able to distribute people as we would wish for.</p><p>We decide to go with friends and younger parts of the family to sit together, and let older parts of the family be with each other.</p><p>Additionally, older parts of family will sit far from the DJ, as grandma Susanne complained about &quot;her ears dying from the modern beats&quot;.</p><p>Our friends, that we&#x27;re hepling them, were amazed by the skills we have!</p><p>Now, everything looks so crystal clear.</p><p>We&#x27;ve made a really good job!</p><h3 id="workshop-yes-please"><a href="#workshop-yes-please" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Workshop? Yes, please!</h3><p>Turns out that the rumours about our outstanding performance, regarding organizing seats for the wedding, were spreading so rapidly that we got another request.</p><p>This time, another friend of ours, who&#x27;s organizing a workshop for elder people on how to use computer, asked as if we could do him a favor.</p><p>Sounds easy, isn&#x27;t it?</p><p>We&#x27;ve already tried out one pattern and it make total sense...</p><p>...In the wedding context, at least.</p><p>As it&#x27;s easy to start with, we have asked our friend if the same pattern of tables and seats, that we used for wedding, wouldn&#x27;t make a decent job.</p><p>The principle of the least effort doesn&#x27;t work this time.</p><p>Our friend gives us some additional piece of information, when it comes to this workshop.</p><h3 id="three-really-mobile-mentors"><a href="#three-really-mobile-mentors" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Three, really mobile mentors</h3><p>The staff, doing the workshop, will consist of three young and bright mentors.</p><p>They will try to do their best to faciliate and help elder people.</p><p>In general, twelve seniors are going to come.</p><p>What&#x27;s more, our friend wants to keep attendees close to each other so they can feel support while facing some struggles.</p><p>Turns out that our mentors would need to be pretty mobile so that everyone feels the presence of a knowledgeable staff member.</p><p>Eventually, when we went into the premise, where the workshop will take place, everything became clear.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/the-ambiguity-of-architecture-workshop-seats.png" class="max-h-[30rem]"/></div><div class="italic mx-24">A pattern of tables and seats suggested for the workshop</div></div><p>Decision was made.</p><p>After couple of weeks, we got a feedback from the friend that &quot;all attendees felt that no one was &#x27;alone&#x27;, and everyone could support others in all the efforts!&quot;</p><h3 id="software-architecture"><a href="#software-architecture" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Software architecture?</h3><p>I hope, my dear Reader, you&#x27;re now wondering &quot;how the hell seats has something to do with software architecture?!&quot;.</p><p>So actually, what is a <em>software architecture</em>?</p><p>One of the images, that is drawn is that there&#x27;s a wizard, sitting on the magical orb and grasping an ivory tower in his hand, creating big plans and making important decisions.</p><p>Maybe he has a black cat, too.</p><p>Then, builders, doers or peons are just executing the masterplan.</p><p>Another answer that is typically summoned is &quot;the decisions that are hard to change later&quot;.</p><p>Yet another one could be;</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">Ralph E Johnson on Software Architecture</div><div class="pb-2 px-3"><div class="break-words"><p>Architecture is about the important stuff. Whatever that is.</p></div></div></div><p>Let&#x27;s use <a href="https://en.wikiquote.org/wiki/Software_architecture">Wiki definition</a>:</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">Software architecture</div><div class="pb-2 px-3"><div class="break-words"><p>Software architecture is a term for the high level structures of a software system. It can be defined as the set of structures needed to reason about the software system, which comprise the software elements, the relations between them, and the properties of both elements and relations. (...)</p></div></div></div><p>It&#x27;s all makes sense, isn&#x27;t it?</p><p>Also, it&#x27;s about decisions.</p><p>Those ones that are hard to change later. So the software architect, creator and big planner, needs to make it all before everything starts.</p><p>But really, why are we naming <em>it</em> as &quot;software architecture&quot;?</p><h3 id="a-denture"><a href="#a-denture" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>A denture</h3><p>Somehow I have a feeling that back then we didn&#x27;t have a good metaphor for those things we consider as &quot;important&quot;.</p><p>Our industry was crawling, craftsmanship wasn&#x27;t yet there and you must explain to someone non-techy that this single decision might give problems in the future.</p><p>Typically, we would use something common, so that both sides would understand.</p><p>Software is being build, we plug or glue things together and so on.</p><p>You&#x27;re getting the point, right?</p><p>Software is not like building houses. It might be one of possible metaphors, helpful in conversation, but is it really hepling when doing it?</p><p>Hence I am not satisfied with existing definitions, or attempts to cover this highly important, and sometimes mythical concept (Concept? You might be interested in <a href="https://talesfrom.dev/blog/concepts-entities-data">Concepts, Entities, Data</a>).</p><p>As you might know me (hopefully, dear Reader!), I like playing with the language because it might actually open a new ways of thinking (models?).</p><h3 id="how-to-name-it"><a href="#how-to-name-it" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>How to name <em>it</em>?</h3><p>At the beginning of this little tale, we were involved in organizing seats in two differents events.</p><p>The way we organized where people will sit, what would be the table arrangement, was the key aspect of achieving the goal.</p><p>Our decisions and ideas were depending on what we wanted to achieve or what to support.</p><p>Could you imagine another scenario when we would need to organize tables and chairs for a lecture?</p><p>Would tables be even needed?</p><p>One of the best definitions I&#x27;ve heard comes from Udi Dahan&#x27;s <a href="https://www.youtube.com/watch?v=Lw04HRF8ies&amp;t=220s&amp;ab_channel=NDCConferences">talk</a> (it points to exact moment of time when it appears).</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">Udi Dahan on Software Architecture:</div><div class="pb-2 px-3"><div class="break-words"><p>Quite simply, a way of organizing things</p></div></div></div><p>It&#x27;s so concise, so terse! And also it captures the essence, as it&#x27;s focused on the process, on the act of doing it.</p><p>To make it a little more complete, I extend it a bit in the following form:</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">Software architecture</div><div class="pb-2 px-3"><div class="break-words"><p>A way of how we are organizing things to achieve or support X</p></div></div></div><p>Powerful, isn&#x27;t it?</p><p>As in our two examples from the beginning of the tale, we organized the seats and tables in certain ways to achieve or support some qualities.</p><p>An avid Reader might say - &quot;architecture is more than a structure!&quot; - and that&#x27;s true.</p><h3 id="organizing-things"><a href="#organizing-things" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Organizing things</h3><p>It&#x27;s true because this thing we call (by mistake?) <em>architecture</em>, it&#x27;s much more than just a structure.</p><p>But this way on how we organize our thinking about <em>architecture</em> also supports other aspects of it.</p><p>In case of the wedding, we focused on organizing the communication so that two aunties won&#x27;t start a bar fight in the middle of the celebration.</p><p>When we worked on the workshop scenario, we put our attention into attendees feeling taken care of and supported.</p><p>It was much more than just a structure.</p><p>Hey, what about &quot;architecture as (hard) decisions&quot;?</p><p>&quot;Decisions about the way of organizing things&quot; and &quot;a way of organizing things&quot; are two different beasts.</p><p>In my mind, architecture shouldn&#x27;t be conflated with &quot;decisions&quot;, as we have another process for that (I am thinking of &quot;designing&quot;, an activity - more about it in the next blog post!).</p><h3 id="isnt-that-too-broad"><a href="#isnt-that-too-broad" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Isn&#x27;t that too broad?</h3><p>You might wonder, dear Reader, that &quot;a way of we organize things to support or achieve X&quot;, might be too broad.</p><p>Software architecture touches various aspects of our industry, but typically it boils down to technical things.</p><p>Data models, sequence diagrams, technical tools, frameworks, scalability, loose coupling, and so on.</p><p>What makes me happy is the fact that we&#x27;re maturing our approaches in perceiving things we build, create and operate as sociotechnical systems.</p><p>Take famous Conway&#x27;s Law as an example.</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">Conway&#x27;s Law</div><div class="pb-2 px-3"><div class="break-words"><p>Organizations, who design systems, are constrained to produce designs which are copies of the communication structures of these organizations.</p></div></div></div><p>A way of organizations organize a communication structures supports limiting a way these organizations design so that the structures of designs are the copy of the organization communication structure.</p><p>We could simplify it as: the way we organize teams will impact designs that those teams will produce.</p><p>Again, it&#x27;s about the act of organizing, the process of arrangement.</p><p>This process touches every aspect of human activity. Hence, it&#x27;s widely applicable!</p><h3 id="should-we-drop-the-name-software-architecture"><a href="#should-we-drop-the-name-software-architecture" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Should we drop the name &quot;software architecture&quot;?</h3><p>Of course, that&#x27;s the right moment to do so. This blogpost will rule the world and turn the entire industry around.</p><p>Jokes aside, &quot;software architecture&quot; is an abstraction for &quot;a way of how we organize things to support or archive something&quot;.</p><p>Could you imagine your boss asking you each and every time: &quot;hey, did you finish working on a way we organize communication between the services to achieve desired qualities?&quot;.</p><p>Looks silly and not funny, isn&#x27;t it?</p><p>We need to abstract the details away. And reusability is not a desired goal here (what I am talking about? Check <a href="https://talesfrom.dev/blog/the-ambiguity-of-abstraction">The ambiguity of abstraction</a>).</p><p>This word, &quot;architecture&quot;, is a nice replacement for those kind of activities we typically do to organize things so that they support or achieve desired qualities.</p><p>As mentioned, it&#x27;s a nice abstraction.</p><p>But leaky one.</p><p>Next time, when you will be working on, *<em>cough cough</em>*, architecture in any aspect of your daily work, ask yourself:</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>How should I organize it to achieve/support/limit/constrain X?</p></div></div></div>]]></content:encoded>
    <pubDate>Sun, 17 Sep 2023 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>systems thinking</category><category>programming</category><category>modeling</category><category>model</category><category>contexts</category><category>representations</category><category>mental models</category><category>heuristics</category><category>principles</category><category>patterns</category><category>design-thinking</category><category>concepts</category><category>decisions</category><category>software architecture</category><category>architecture</category><category>collaboration</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/the-ambiguity-of-documentation</guid>
    <title>The ambiguity of documentation</title>
    <link>https://talesfrom.dev/blog/the-ambiguity-of-documentation</link>
    <description>Is a documentation only a manual?</description>
    <content:encoded><![CDATA[<h3 id="new-day-new-task"><a href="#new-day-new-task" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>New day, new task</h3><p>Imagine that we were assigned a task to add something to our existing application.</p><p>Let&#x27;s say this &quot;something&quot; is actually very serious piece of UI or maybe a visualization of huge amount of data that we received from IoT devices.</p><p>We start thinking, asking Chat-GPT and other useful tools, we try to wrap our heads around the problem we are faced with.</p><p>Well, I don&#x27;t know how would you do next steps but I would probably check if this is a problem from a category &quot;a set of already solved problems&quot;.</p><p>It might be that we just avoided reinventing the wheel as someone already hit similar issue long time ago and we might benefit from his or her learnings.</p><p>Few clicks, minutes of googling, quick evaluation and there it is - a library or a package, name it however you want.</p><h3 id="how-the-hell-can-i-use-it"><a href="#how-the-hell-can-i-use-it" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>How the hell can I use it?</h3><p>Let&#x27;s assume the tool has some docs written. There&#x27;s a section about examples, how to install and what are the potential pitfalls.</p><p>Easy.</p><p><code>npm i</code> / <code>yarn add</code> / <code>dotnet add package</code> / <code>pip install</code> - boom, we&#x27;ve got the tool!</p><p>We try to take a simple example, brief walkthrough of each lines. Looks fairly easy.</p><p>Ok, now our case!</p><p>Change here, change there. As predicted, should work.</p><p>And this magic moment happens when we actually might have missed the point of this tool.</p><p>Bad docs, bad docs. Didn&#x27;t guide us decently enough!</p><p>Click click, few keystrokes and here we are - everything wired up, now it&#x27;s the time for success.</p><p>Nah, not yet. We forgot importing one last thing and adding it to the configuration.</p><p>Maybe this time...</p><h3 id="a-manual"><a href="#a-manual" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>A manual?</h3><p>Does it sound familiar?</p><p>Have you experienced such &quot;quick &amp; mindless&quot; stitching just to make things work?</p><p>Don&#x27;t get me wrong, not saying it&#x27;s a miserable thing to do.</p><p>I am still falling in this &quot;trap&quot;, especially when I really want to do a proof of concept work just to yield some understanding or to verify if my one million-dollar idea makes sense.</p><p>While being in the process of exploration, when I have &quot;skin in the game&quot; experience, I am magically treating documentation as a manual.</p><p>Do this, do that and here&#x27;s the effect you want to get.</p><p>Quite imperative, isn&#x27;t it?</p><p>What if there&#x27;s another level of the documentation, that is typically hidden?</p><h3 id="a-philosophy"><a href="#a-philosophy" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>A philosophy?</h3><p>Let&#x27;s start from the beginning (in the ideal world).</p><p>A humble creator, a mere doer, faced a problem.</p><p>No one had similar issue before or the suggested solution didn&#x27;t fit the mental representation of the mentioned builder.</p><p>As there is a problem to solve, we might be exposed to <a href="https://talesfrom.dev/blog/language-of-the-problem">Language of the problem</a>.</p><p>The same was with our library author - in the &quot;problem area&quot; some concepts existed that were or were not captured by him, while designing the solution.</p><p>What if &quot;design&quot; was accidental and &quot;just happened&quot;?</p><p>Or maybe there was a huge effort put into understanding &quot;what do we mean by that?&quot;, which yielded precise words, artistically distilled into abstractions.</p><h3 id="words-concepts-abstractions-building-blocks"><a href="#words-concepts-abstractions-building-blocks" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Words, concepts, abstractions, building blocks</h3><p>Have you ever started your evaluation of a tool/a library/a framework based on the concepts it comes with?</p><p>How natural did they seem to you?</p><p>Of course, sometimes there&#x27;s &quot;no time&quot; (really?).</p><p>Then we see all the memes &quot;try to fight with the tool for 4 hours vs read the docs for 5 min&quot;.</p><p>But going back to the point, the documentation not only informs us about the usage but also embodies the concepts, the philosophy, the motivation behind it.</p><p>Sometimes they are not mentioned explicitly, though.</p><p>Those levels, or perspectives, (what is the difference? you might be interested in <a href="https://talesfrom.dev/blog/modeling-maturity-levels">Modeling Maturity Levels</a>) might manifest themselves directly in the API of the tool or through so-called &quot;building blocks&quot;.</p><h3 id="language-designers"><a href="#language-designers" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Language designers?</h3><p>As we are at the &quot;building blocks&quot; station, is it yet another name for abstraction?</p><p>You know, abstracting away what is irrelevant in order to amplify what is essential.</p><p>Hence, are the fellow library authors, consciously or not, designing/capturing the language around the problem they try to solve?</p><p>We are slowly reaching the main point of this little tale - are the concepts properly described in the documentation?</p><p>I believe this might transform the documentation from being &quot;just a manual&quot; into a profound library (pun intended), full of intentional words and ideas expressed that constitute the knowledge base.</p><p>The knowledge base that when &quot;loaded&quot; into our minds becomes the way we &quot;live by&quot; while using the tool.</p><h3 id="modeling-around-the-language"><a href="#modeling-around-the-language" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Modeling around the language</h3><p>Isn&#x27;t that the point of the process of modeling?</p><p>The tool&#x27;s author has some ideas in his or her mind.</p><p>They are getting expressed in the code via some abstractions (enhanted concepts?).</p><p>The language, that binds those abstractions, appears in the docs, too. (sounds similar to the bounded context from DDD, isn&#x27;t it?)</p><p>Let&#x27;s take one of my favorite state management libraries - <a href="https://overmindjs.org/introduction">Overmind</a>, masterfully crafted by <a href="https://github.com/christianalfoni">Christian Alfoni</a>.</p><p>When one goes through the docs, he or she can quickly get into &quot;code examples&quot;.</p><p>But those &quot;code snippets&quot;, as we saw at the beginning of this little tale, use concepts that were created by the author and are expressed in the code.</p><p>When such a library gets adopted in the team, all the team members using the tool might eventually speak the language that it brought.</p><p>It might sound obvious to you, but isn&#x27;t that the point - if the author created a well-suited model, solving the problem(s), it&#x27;s so easy to use it within its context?</p><p>And when those abstractions and concepts don&#x27;t capture the essential aspects of the problem - wouldn&#x27;t this tool be a nightmare to use, e.g. its API is too low-level or requires unnecessary boilerplate? (when discussing the essential and the accidental perspectives, you might be interested in <a href="https://talesfrom.dev/blog/essentially-bounded-accidentally-unlimited">Essentially bounded, Accidentally unlimited</a>)</p><p>We could take other examples of &quot;tools&quot;, like Kubernetes or Docker.</p><p>They came with their concepts - pods, containers, images, services, etc.</p><p>Those names stuck with us got adopted and became a de facto communication standard, language patterns used in day-to-day life (don&#x27;t you talk with your relatives about images and replica sets?).</p><p>We might eventually conclude that exploring, distilling, and naming concepts living in the problem&#x27;s world, is enormously impactful on the efficiency of the tool.</p><h3 id="more-accurate-models-win-blunt-models-lose"><a href="#more-accurate-models-win-blunt-models-lose" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>More accurate models win, blunt models lose?</h3><p>Can we evaluate the success of solving the problem by the set of models that are provided by a tool of choice? (when I say &quot;models&quot; I have in my mind concepts captured, e.g. in the code by types)</p><p>Going back to <a href="https://overmindjs.org/introduction">Overmind</a>, it comes with set of core concepts: actions, operators, effects.</p><p>Each of them represent some sub-problems of a bigger problem that we might encounter while building the rich UI application.</p><p>And what&#x27;s more intersting, there are some &quot;functions&quot; or roles that those abstractions provide or play.</p><p>A set of capabilities that must be there to efficiently solve the problem that one is facing.</p><p>What if some of those capabilities are not explicitly expressed?</p><h3 id="capabilities-concepts-abstractions"><a href="#capabilities-concepts-abstractions" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Capabilities, concepts, abstractions</h3><p>As Mathias and Rebecca showed in their <a href="https://youtu.be/ecW1jMhIt2k?si=kq4tkVzO0coSsFRu">talk</a>, if you care about something, make sure you have it properly represented.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>If you care about something, have a building block for it.</p></div></div></div><p>Those building blocks, &quot;concepts&quot; or abstractions (name them as you wish, dear Reader), will eventually come from the effortful time consisting of hard thinking and &quot;what does it mean?&quot; questions posed multiple times.</p><p>All of this is a yielded knowledge.</p><p>Understanding.</p><p>The essence that should have its place in the code, in the speech and in the documentation.</p><p>It might be that the tool is flashy and shiny but don&#x27;t be fooled by it - there probably are some core and foundational concepts behind it. (you might be interested in <a href="https://talesfrom.dev/blog/new-tools-old-rules">New tools, old rules</a>)</p><p>Next time, when you will be learning a new tool/library, a new language or even a new pattern, try to ask yourself:</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>What are the core concepts, motivation and philosophy behind it?</p></div></div></div>]]></content:encoded>
    <pubDate>Thu, 24 Aug 2023 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>object-oriented</category><category>functional</category><category>programming</category><category>modeling</category><category>model</category><category>contexts</category><category>representations</category><category>mental models</category><category>heuristics</category><category>principles</category><category>patterns</category><category>design-thinking</category><category>concepts</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/new-tools-old-rules</guid>
    <title>New tools, old rules</title>
    <link>https://talesfrom.dev/blog/new-tools-old-rules</link>
    <description>Does &quot;old&quot; always remain unattractive?</description>
    <content:encoded><![CDATA[<div class="bg-slate-600 rounded-xl "><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Attention!</span></div><div class="pb-2 px-3"><div class="break-words"><p>In this article, by rules I mean patterns/guides/observations/heuristics/principles/laws in general.</p></div></div></div><h3 id="a-day-of-typical-software-engineer"><a href="#a-day-of-typical-software-engineer" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>A day of typical software engineer</h3><p><code>npm install X</code> to get the package we want (and maybe need).</p><p>Deploy to cloud because it&#x27;s easy, sometimes cheap and makes us prepared for massive scale.</p><p>Leverage React, or other view library, to craft beautiful user interfaces.</p><p>Use a SaaS app for sketching and collaborating in real time, generate markdown file and send it to team members.</p><p>Add logging and monitoring with a single step and entire product gets observability with the highest possible grade.</p><p>Levarage CQRS to have narrow, vertically sliced behaviors of the system.</p><p>Prompt GPT and have a chat regarding implementing a feature with highly encapsulated and flexible OO code.</p><p>Easy.</p><p>Does it sound familiar to you, dear Reader?</p><h3 id="a-typical-horror-of-a-software-engineer"><a href="#a-typical-horror-of-a-software-engineer" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>A typical horror of a software engineer</h3><p>Installed 3rd party packages, wrapped with our leaky abstractions made their usage appear everywhere.</p><p>Applications are fast to deploy, but slow to be developed - everything is connected with everything.</p><p>User interfaces have strange glitches as numerous booleans are spread across components for controlling app state. (see related: <a href="https://talesfrom.dev/blog/bool-considered-harmful">Bool considered harmful?</a>)</p><p>Generated markdown file contains persistence models (aka data models), as it was created with &quot;noun-oriented&quot; thinking - and totally discards behaviors and transformations. (see related: <a href="https://talesfrom.dev/blog/concepts-entities-data">Concepts, Entities, Data</a>)</p><p>Logged information comes in massive amounts and soon we need to parse plain text to capture crucial business facts.</p><p>Implemented Commands and Queries are full of collaborators which makes them bloated and makes related tests full of fixtures. (see related: <a href="https://talesfrom.dev/blog/i-interface">I, interface</a>)</p><p>Suggested code is full of inheritance, indirection, layers and the only notion of modularization is in names of the classes: &quot;*Module&quot;.</p><h3 id="too-fast-too-dubious"><a href="#too-fast-too-dubious" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Too fast, too dubious</h3><p>We could enumerate through the tools more and more, for instance, mention k8s and other modern &quot;equipment&quot;, but that&#x27;s not the point.</p><p>Nowadays, we need to move fast (I wonder if 20 years ago people weren&#x27;t saying wanting the same?) and deliver quickly.</p><p>We need resilience and reliability.</p><p>Apps must be snappy, modern looking and highly interactive.</p><p>To achieve so, we are grabbing the latest advancements from IT industry.</p><p>Nothing wrong with that - it will be weird (and unprofessional) to argue to use punch cards or to build web applications with Assembler.</p><p>Tools and their functions, the roles they play, shouldn&#x27;t be neglected whatsoever.</p><p>But such behavior might root us in &quot;new good, old bad&quot; way of reasoning.</p><h3 id="there-will-always-be-new-shiny-tools"><a href="#there-will-always-be-new-shiny-tools" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>There will always be new, shiny tools</h3><p>Year by year, human creativity is able to be manifested, materialized, and expressed through technical evolution.</p><p>It&#x27;s really amazing that one person is able to build SaaS product alone, run in the cloud and utilize serverless - marvelous experience.</p><p>Amazing times to live in.</p><p>As an industry, we don&#x27;t have very long tradition. New tools are (re)invented periodically, sometimes they are getting new names, maybe they are faster.</p><p>It&#x27;s a matter of evolution, one might say.</p><p>The new glittery tool presented a month ago shows how better it is than its competitor released half a year ago.</p><p>There will always be new, shiny tools.</p><p>Trying to advertise strengths, power-ups, and so on.</p><h3 id="what-about-the-almanacs"><a href="#what-about-the-almanacs" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What about the almanacs?</h3><p>Books that were published 10 years ago, 20 years ago, 30 years ago.</p><p>Articles published 10 years ago. Probably using old-fashioned, not-so-cool version of your favorite language.</p><p>What&#x27;s with them?</p><p>Turns out that there&#x27;s knowledge that is hidden from the regular sight.</p><p>Of course, not every book or article carries &quot;the value&quot;, the essential teaching one would wish for.</p><p>Among all of there, one could find eternal practices about modularization, encapsulation, decomposition, composition, cohesion, coupling, revealing intentions through abstractions, modeling and more.</p><p>Unfortunately, it seems they got burried under the dust of time.</p><p>Comparing to tooling, it doesn&#x27;t seem so &quot;sexy&quot; enough to read about modeling, &quot;patterns&quot; for achieving modularization, heuristics for decomposition. (btw. I wrote a bit about similar topic in <a href="https://talesfrom.dev/blog/software-engineering-for-busy-parents">Software Engineering for busy parents</a>)</p><p>This might be considered as the &quot;art&quot;-like part of software engineering - it might be even considered as not so deterministic, way far from real engineering.</p><p>Contradictory, tools are here - they are quite tangible, visible, &quot;touchable&quot;.</p><p>You can read the docs and you &quot;know it all&quot; - of course, I am not saying there are no nitty gritty things and fishy solutions.</p><h3 id="old-rules-never-get-old-huh"><a href="#old-rules-never-get-old-huh" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Old rules never get old, huh?</h3><p>Somehow &quot;old&quot; guides, observations, insights, remain evergreen.</p><p>Why?</p><p>&quot;Problems&quot; of decomposition, composition, responsibilities assignment, roles/interface discovery, capabilities mapping, domain modeling, encapsulation, cohesion, coupling will always be there.</p><p>Why?</p><p>Because they are essential.</p><p>They are inherent.</p><p>They are built in the problem we are trying to solve. (you might be interested in <a href="https://talesfrom.dev/blog/essentially-bounded-accidentally-unlimited">Essentially bounded, Accidentally unlimited</a>)</p><p>There are beautiful and mind-changing books, for example:</p><ul><li><a href="https://www.amazon.com/Emergent-Design-Evolutionary-Professional-Development/dp/0321509366">Emergent Design: The Evolutionary Nature of Professional Software Development</a></li><li><a href="https://www.amazon.com/Secrets-Consulting-Giving-Getting-Successfully/dp/0932633013">The Secrets of Consulting: A Guide to Giving and Getting Advice Successfully</a></li><li><a href="http://www.growing-object-oriented-software.com/">Growing Object-Oriented Software Guided by Tests</a></li><li><a href="https://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215">Domain-Driven Design: Tackling Complexity in the Heart of Software</a></li></ul><p>that might be considered as &quot;old&quot;.</p><p>And the fact is - they are old. But the hidden gems of knowledge, subtle sapphires of mental models, created through experience and reflection - it&#x27;s all there.</p><h3 id="the-problem-of-rewrite"><a href="#the-problem-of-rewrite" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The problem of rewrite</h3><p>I don&#x27;t want to claim I have a magical orb that enables me seeing the future.</p><p>But all this focus on the tools, on their glitter, might actually make new people coming into the field a bit distracted from what is also important (note I didn&#x27;t say tools are not important 😉).</p><p>In the times, where microservices grow up like mushrooms in the forest after heavy rain, it shouldn&#x27;t be hard to rewrite a piece of capability delivered by a microservice.</p><p>Just stop developing crappy and poorly written code in C# or Java - set up new service, use strangler pattern and write in Rust (btw. I really like Rust!).</p><p>What are the chances of having next rewrite in some months? Of course, it&#x27;s not that easy and straightforward to predict (even with my imaginary magical orb!).</p><p>But I believe you get the point.</p><p>Being able to quickly tear down a module/microservice/service/command handler/function/put-the-name-for-the-thing-you-want-to-rewrite and build a new one doesn&#x27;t solve the problem of failing with modularization and other tenets of high-quality software.</p><p>I feel that GPT and other prompting thingies are beautifully showing it - they work like a signal amplifiers.</p><p>Give them the correct input signal, you will get what you wanted in return.</p><p>Given them the lack of knowledge signal, you will get amplified lack of knowledge.</p><h3 id="learn-tools-study-rules"><a href="#learn-tools-study-rules" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Learn tools, study rules</h3><p>At the moment of writing, I think there&#x27;s a subtle difference between learning tools and studying rules.</p><p>We learn tools like Azure Functions to be able to levarage serverless computing to solve our business problems, without being concerned about infrastructure too much.</p><p>Of course, we can learn about various triggers, and so on - still, it&#x27;s quite finite job.</p><p>What&#x27;s more, we can even discover new ways of using it!</p><p>Contrary to that, studying rules requires time.</p><p>A lot of time.</p><p>It&#x27;s something like going back and forth from saying &quot;OO design patterns are utter BS&quot; to &quot;I will decorate this handler with validation behavior&quot;.</p><p>Applying patterns in the wrong contexts make them anti-patterns.</p><p>Noticing so requires reflection, self-awareness and time.</p><p>I think that&#x27;s why it is so important to go back to the &quot;roots&quot; and study fundamentals (from time to time).</p><p>To reflect on them.</p><p>To rewire our brains.</p><p>To change the understanding of the concepts we grasped such a long time ago.</p><p>What&#x27;s worth noting is that &quot;the essential&quot; parts give good ground for applying tools.</p><p>Learn tools, study rules.</p>]]></content:encoded>
    <pubDate>Wed, 02 Aug 2023 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>architecture</category><category>object-oriented</category><category>functional</category><category>programming</category><category>modeling</category><category>model</category><category>contexts</category><category>representations</category><category>mental models</category><category>heuristics</category><category>principles</category><category>patterns</category><category>design-thinking</category><category>contracts</category><category>service-oriented</category><category>microservices</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/concepts-entities-data</guid>
    <title>Concepts, Entities, Data</title>
    <link>https://talesfrom.dev/blog/concepts-entities-data</link>
    <description>What is the relationship between all three of them?</description>
    <content:encoded><![CDATA[<h3 id="domain"><a href="#domain" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Domain?</h3><p>Imagine we are starting our new gig and he are in the middle of the discussion with the customer.</p><p>(you can interact with the &quot;tabs&quot; below)</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Talk</div><div class="cursor-pointer border-2 border-l-0 border-b-0 border-gray-50 w-48 text-center text-gray-700">Pay attention</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><p>Customer: Our users work with three different <span class="pr-2">types</span>of <span class="">tasks</span>: quick <span class="">task</span>, complex <span class="">task</span>and supervised <span class="">task</span>.</p></span><span class="text-white"><p>Us: What is the difference between them?</p></span><span class="text-white"><p>Customer: Quick <span class="pr-2">tasks</span>are just to register that someone did something. Really simple.</p></span><span class="text-white"><p>Us: Mhm.</p></span><span class="text-white"><p>Customer: Complex <span class="pr-2">tasks</span>are a bit more tricky as they require <span class="">special equipment</span>and <span class="">qualification card</span>.</p></span><span class="text-white"><p>Us: And supervised <span class="">tasks</span>?</p></span><span class="text-white"><p>Customer: Supervised <span class="pr-2">tasks</span>require attention from <span class="pr-2">a supervisor</span>that gives <span class="pr-2">evaluation</span>back. What&#x27;s more, they might have multiple people involved.</p></span><span class="text-white"><p>Us: It is very important to remember that both complex and supervised <span class="pr-2">tasks</span>might take some <span class="pr-2">tasks</span>might take some time and we need to know what is their <span class="pr-2">time</span>and we need to know what is their <span class="">status</span>.</p></span></div><p>What is your gut feeling, dear Reader?</p><p>Should we have one single table <code>Task</code> or one table for each: <code>SupervisedTask</code>, <code>ComplexTask</code> and <code>QuickTask</code>?</p><p>Then probably we would need to represent <code>QualificationCard</code>, <code>Supervisor</code> and <code>Evaluation</code> as separate tables too.</p><p>Ah, we almost forgot about multiple people contributing for <code>ComplexTask</code> - our customer didn&#x27;t say a word about proper name of underlying profession, let&#x27;s call them <code>Worker</code>.</p><p>Also, behind the scenes we got some more details that all types of tasks are related to common set of data, e.g. <code>Worker</code>.</p><p>Language is something that flows and goes, it isn&#x27;t tangible, and might be volatile.</p><p>Let&#x27;s sketch something.</p><div class="flex justify-center items-center flex-col"><div><img class="max-h-[25rem]" src="https://talesfrom.dev/static/images/erd.png"/></div><div>Entity Relationship Diagram</div></div><p>As you can see, we are open for extension because we have tables for <code>TaskType</code> and <code>TaskStatus</code>, in case of changing mind by our customer. Smart, ain&#x27;t it?</p><h3 id="whats-the-problem"><a href="#whats-the-problem" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What&#x27;s the problem?</h3><p>You probably already know me a bit (I hope so, dear Reader!) - I like to exaggerate a bit.</p><p>I intentionally focused on nouns and completely forgot about asking hugely important questions:</p><ul><li>who are our users?</li><li>how they are going to use our system?</li><li>what is the current way of satisfying their needs?</li><li>how this system should help them achieving their goals?</li><li>etc.</li></ul><p>Of course, I trivialized the example - guilty and charged.</p><p>But how often do we hear in our day to day conversations about statuses, status flags, entities, data models?</p><p>How frequently do we take the following premise: &quot;two entities share similar set of data&quot; and build an assumption that they might be represented by the same entity?</p><p>In our toy case, <code>Task</code> might be represented as a base class so that we are avoiding data duplication.</p><p>No one would disagree that <code>QuickTask</code> is a <code>Task</code>, right?</p><h3 id="in-the-search-for-relationships"><a href="#in-the-search-for-relationships" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>In the search for relationships</h3><p>We looked for hierarchies, how things related to each other.</p><p>If we <a href="https://talesfrom.dev/blog/slow-down">Slow down</a> and ask ourselves - what did our imaginary customer describe?</p><p>Out of the unstructured, analog, audio signal that we call sound, we interpreted the words and made them a little bit more structured.</p><p>Immediately focusing for nouns, relationships between them, and possibly paying attention to attributes (also called data).</p><p>In fact, seeking all of them is facilitated by thinking in terms of Entity Relationship Diagram (ERD), which might be connected to efficiently representing entities and data in the persistence tools like SQL databases.</p><p>This might be considered as a quite low level, when it comes to modeling.</p><p>It&#x27;s just one level (Being) - and there are more. (why am I calling it a level? Check <a href="https://talesfrom.dev/blog/modeling-maturity-levels">Modeling Maturity Levels</a>)</p><h3 id="what-was-first-entity-or-entity"><a href="#what-was-first-entity-or-entity" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What was first: Entity or Entity?</h3><p>Before diving into sketching of the ERD, let&#x27;s think about what we have heard in the discussion from the beginning of the tale.</p><p>How would we call all of the highlighted &quot;things&quot;?</p><p>The first and foremost label that people use to call those &quot;things&quot; is <code>Entity</code>.</p><p>Each <code>Entity</code> has <code>Data</code> related to it.</p><p>This word is biased and easily might anchore us in very specific, narrowed thinking.</p><p>To avoid entangling our minds with TDD and DDD (Table-Driven Development and Database-Driven Design), I like to use another word.</p><p>I like to use <code>Concept</code> label for those &quot;things&quot;.</p><p>&quot;It&#x27;s just a <code>Concept</code>&quot; - <a href="https://talesfrom.dev/blog/i-dont-know">I don&#x27;t know</a> what will be the technical realization of it.</p><p>I expect nothing, so I am prepared for everything.</p><p>Not being bound, by anchors coming from the persistence realms, liberates.</p><p>We can now break the rules.</p><h3 id="what-is-the-nature-of-a-concept"><a href="#what-is-the-nature-of-a-concept" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What is the nature of a <code>Concept</code>?</h3><p>We don&#x27;t need to ask ourselves &quot;how many <code>Equipment</code>s can a <code>Task</code> have?&quot; - it&#x27;s secondary.</p><p>We don&#x27;t need to think whether a <code>QualificationCard</code> has name and what is the max lenght of it - this won&#x27;t cause problems.</p><p>Concepts don&#x27;t have statuses, Entities do.</p><p>Taking that into account, we might play with the names of the concepts - is there a place for <code>Completed Quick Task</code>? Would it differ from <code>Completed Complex Task</code>?</p><p>Remember, we are not talking about technical implementation yet!</p><p>In my head, concepts can naturally emerge and die - not literally, of course.</p><p>They can come and go by being transformed from one to another.</p><p>They are processed, they evolve into other ones.</p><h3 id="can-a-quick-task-become-a-complex-one"><a href="#can-a-quick-task-become-a-complex-one" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Can a quick task become a complex one?</h3><p>Let&#x27;s imagine that our customer, being asked - &quot;is it possible that a quick task won&#x27;t be able to be finished because it has some unexpected complications?&quot;.</p><p>Assume, the customer replied: &quot;Yup, then task type is changed from &#x27;Quick&#x27; to &#x27;Complex&#x27;.&quot;</p><p>(although there are business people that were harmed with Database-Driven Design - we need to help them)</p><p>Sorry to say, but this doesn&#x27;t sound like a <a href="https://talesfrom.dev/blog/language-of-the-problem">Language of the problem</a>, at all.</p><p>With high probability, the answer would be a bit different: &quot;Yes, the quick task might eventually become a complex one&quot;.</p><p>&quot;<strong>Become a</strong>&quot; - very important expression - the highest possible level from <a href="https://talesfrom.dev/blog/modeling-maturity-levels">Modeling Maturity Levels</a>.</p><p>If we carefully listen to ourselves, we express various concepts from our day to day life exactly in the form of transformations.</p><p>Neverending arising and ceasing.</p><p>Sooner or later we might realize that it&#x27;s very natural for us to think of, e.g. an important document to become &quot;signed&quot; or an old sandwich in the backpack to become &quot;rotten&quot;.</p><p>Thinking with concepts gives this possibility, at least in my opinion.</p><h3 id="concepts-do-not-compile"><a href="#concepts-do-not-compile" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Concepts do not compile</h3><p>Yup, concepts are the first step - they don&#x27;t throw any errors or cause the servers to go down (or do they?).</p><p>Of course, we might be judged that we are creating unnecessary complexity.</p><p>Someone might say - &quot;you are complicating things that were simpler before!&quot;.</p><p><a href="https://talesfrom.dev/blog/the-cost-of-modeling">The cost of modeling</a> increases!</p><p>Concepts allow to model &quot;things&quot; around the <a href="https://talesfrom.dev/blog/language-of-the-problem">Language of the problem</a> - no one says we must manifest everything in the code.</p><p>Considering that <a href="https://talesfrom.dev/blog/i-dont-know">I don&#x27;t know</a> - what if our concepts do not have relational nature, but graph one?</p><p>Maybe there are no relationships as we know them from SQL databases.</p><p>How do we persist our concepts and how do we represent them in the application - those are totally different questions that we will need to ask ourselves at some point.</p><p>They will come, no worries.</p><h3 id="from-lines-to-arrows"><a href="#from-lines-to-arrows" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>From lines to arrows</h3><p>Let us come back to our little case with quick task becoming complex one.</p><p>We know that complex task has some status related to it - right?</p><p>Knowing that, let&#x27;s imagine our customer told us that they simply consider the following statuses as valid:</p><ul><li><code>ongoing</code></li><li><code>assigned</code></li><li><code>rejected</code></li><li><code>blocked</code></li><li><code>failed</code></li></ul><p>Our Entity Relationship Diagram captured the static side of our &quot;domain&quot;.</p><p>It has its own place - but not when &quot;modeling the domain&quot;.</p><p>It might be massively helpful when we are working with relational databases, for example.</p><p>So let&#x27;s now try to think of a combination of each &quot;status&quot; and complex task as a separate...Concepts.</p><div class="flex justify-center items-center flex-col"><div><img class="max-h-[25rem]" src="https://talesfrom.dev/static/images/concept-map.png"/></div><div>Concept Map</div></div><p>Such web of concepts, in which there are no lines, but arrows, can be called a <a href="https://talesfrom.dev/blog/concept-maps">Concept Map</a>.</p><p>It helps me with capturing the transformational nature of concepts, and model from the highest possible level - &quot;Becoming&quot; (you don&#x27;t know what am I talking about? Check <a href="https://talesfrom.dev/blog/modeling-maturity-levels">Modeling Maturity Levels</a>).</p><p>What&#x27;s more, there are high chances that there is an action that a user can do on <code>Blocked Complex Task</code>, but it cannot be applied to <code>Assigned Complex Task</code>.</p><p>Those are additional set of questions that we would need to ask for each of the concepts - and thankfully they are located in the &quot;middle&quot; level of <a href="https://talesfrom.dev/blog/modeling-maturity-levels">Modeling Maturity Levels</a>.</p><p>As you probably noticed, dear Reader, it highly resembles a finite state machine.</p><p>Try to tell your business people about finite state machine, I wonder what would be the reaction.</p><h3 id="data---what-about-it"><a href="#data---what-about-it" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Data - what about it?</h3><p>We shouldn&#x27;t forget about very important aspects of each enterprise and human endeavour - data.</p><p>We could also call it information - just to break the anchors from persistence realms.</p><p>It is hugely relevant, and has it place - maybe not directly from day 0.</p><p>Each of the transitions, in our concept map, might require very precise set of details.</p><p>How we are going to store this information isn&#x27;t the primary concern - or at least it shouldn&#x27;t be.</p><h3 id="entity-hater"><a href="#entity-hater" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Entity hater?</h3><p>Am I <code>Entity</code> hater, moaning about the irrelevance of <code>Data</code>?</p><p>Well, kind of.</p><p>&quot;Everything has its place, and there&#x27;s the place for everything&quot;.</p><p>I think they might be irrelevant at the given stage, whereas during another one they play the most important role - and if we don&#x27;t use our technical excellence, our users might not get the value from our system.</p><p>We shouldn&#x27;t limit ourselves from exploring the concepts that manifest in the language, used by other human beings.</p><p>Our concepts do not have a boolean flag <code>IsValid</code> or <code>IsActive</code> attached, even though they might be technically implemented like that. (when talking about bools you might be interested in <a href="https://talesfrom.dev/blog/bool-considered-harmful">Bool considered harmful?</a>)</p><p>When we move from concepts to entities, we might eventually talk about behavior, responsibilities.</p><p>Then we will probably transition from entities to data, because we need to have information to use.</p><p>Such process won&#x27;t be discrete - it will, for sure, be turbulent, chaotic, fluid and full of emergence - the same as life is.</p><p>Next time, dear Reader, when you start you work, ask yourself a question:</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>What is the level I am reasoning on right now?</p></div></div></div>]]></content:encoded>
    <pubDate>Thu, 20 Jul 2023 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>architecture</category><category>object-oriented</category><category>functional</category><category>programming</category><category>modeling</category><category>model</category><category>contexts</category><category>representations</category><category>mental models</category><category>heuristics</category><category>principles</category><category>patterns</category><category>design-thinking</category><category>contracts</category><category>service-oriented</category><category>microservices</category><category>blasphemy</category><category>database-driven design</category><category>table-driven development</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/how-do-errors-evolve</guid>
    <title>How do errors evolve?</title>
    <link>https://talesfrom.dev/blog/how-do-errors-evolve</link>
    <description>Compile-time, run-time - what is next in the evolution?</description>
    <content:encoded><![CDATA[<h3 id="the-last-copy"><a href="#the-last-copy" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The last copy</h3><p>Imagine that an unexpected event happened - the two evil villains, DDD (Database-Driven Design) and TDD (Table-Driven Development) did a vile act.</p><p>The world is in despair because of that.</p><p>Those two vicious anti-heroes wished for all of the people to forget how to properly model the domain, think about boundaries, assign responsibilities and use the language as a guideline.</p><p>All the copies of <a href="https://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215">Blue Book</a> are gone.</p><p>They destroyed both physical and digital ones.</p><p>Except one.</p><p>Seems like we need to protect this book from evil twins, DDD and TDD.</p><h3 id="the-order-of-hidden-sapphire"><a href="#the-order-of-hidden-sapphire" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The Order of Hidden Sapphire</h3><p>People want the knowledge, they seek the understanding.</p><p>Imagine that they around the world come to us to get a quote from the book.</p><p>This last copy is so valuable that we decided to keep it in a <code>SecureSafe</code>.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">sealed</span> <span class="token keyword">class</span> <span class="token class-name">SecureSafe</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><div class="flex justify-center items-center flex-col"><div><img class="max-h-[15rem]" src="https://talesfrom.dev/static/images/safe.png"/></div><div>A secure safe</div></div><p>Its main responsibilities would be to <code>ProtectTheBlueBook</code> and to <code>AllowAcessingTheBlueBook</code>.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">IProtectTheBlueBook</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name return-type"><span class="token keyword">void</span></span> <span class="token function">Protect</span><span class="token punctuation">(</span><span class="token class-name">BlueBook</span> blueBook<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">IAllowAccessingTheBlueBook</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name return-type">BlueBook</span> <span class="token function">AccessWith</span><span class="token punctuation">(</span><span class="token class-name">PinCode</span> pinCode<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Then we know how we can use <code>SecureSafe</code>:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">sealed</span> <span class="token keyword">class</span> <span class="token class-name">SecureSafe</span> <span class="token punctuation">:</span> 
</span><span class="code-line">                    <span class="token type-list"><span class="token class-name">IProtectTheBlueBook</span><span class="token punctuation">,</span>
</span></span><span class="code-line"><span class="token type-list">                    <span class="token class-name">IAllowAccessingTheBlueBook</span></span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">BlueBook</span> <span class="token function">AccessWith</span><span class="token punctuation">(</span><span class="token class-name">PinCode</span> pinCode<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">//...</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">void</span></span> <span class="token function">Protect</span><span class="token punctuation">(</span><span class="token class-name">BlueBook</span> blueBook<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token comment">//...</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>(you might wonder why <code>IUseInterfaces</code> in a &quot;strange&quot; way - please look on <a href="https://talesfrom.dev/blog/i-interface">I, interface</a>)</p><p>To access the protected book, we need to type a <code>PinCode</code>.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">enum</span> <span class="token class-name">PinNumber</span> <span class="token punctuation">{</span>
</span><span class="code-line">    One <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">,</span>
</span><span class="code-line">    Two <span class="token operator">=</span> <span class="token number">2</span><span class="token punctuation">,</span>
</span><span class="code-line">    Three <span class="token operator">=</span> <span class="token number">3</span><span class="token punctuation">,</span>
</span><span class="code-line">    Four <span class="token operator">=</span> <span class="token number">4</span><span class="token punctuation">,</span>
</span><span class="code-line">    Five <span class="token operator">=</span> <span class="token number">5</span><span class="token punctuation">,</span>
</span><span class="code-line">    Six <span class="token operator">=</span> <span class="token number">6</span><span class="token punctuation">,</span>
</span><span class="code-line">    Seven <span class="token operator">=</span> <span class="token number">7</span><span class="token punctuation">,</span>
</span><span class="code-line">    Eight <span class="token operator">=</span> <span class="token number">8</span><span class="token punctuation">,</span>
</span><span class="code-line">    Nine <span class="token operator">=</span> <span class="token number">9</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">sealed</span> <span class="token keyword">record</span> <span class="token class-name">PinCode</span><span class="token punctuation">(</span><span class="token class-name">IEnumerable<span class="token punctuation">&lt;</span>PinNumber<span class="token punctuation">&gt;</span></span> PinNumbers<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre></div></div><p>Then we can use <code>BlueBook</code> and fetch a quote from it.</p><h3 id="numbers-not-letters"><a href="#numbers-not-letters" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Numbers, not letters</h3><p>As our interface informs us, the expected input is a sequence of <code>PinNumber</code>s.</p><p>Only specified <code>PinNumber</code>s are allowed to be used.</p><p>When someone would even think about giving a bunch of letters, e.g. &quot;admin123&quot;, it wouldn&#x27;t make any sense.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token comment">// somewhere in a method...</span>
</span><span class="code-line">
</span><span class="code-line">safe<span class="token punctuation">.</span><span class="token function">AccessWith</span><span class="token punctuation">(</span><span class="token string">&quot;admin123&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre></div></div><p>In the code, our dear friend, the compilerm would give the feedback: <span class="text-red-600">cannot convert from &#x27;string&#x27; to &#x27;PinCode&#x27;</span>.</p><p>And it makes sense - that&#x27;s the designed interface.</p><p>This error (in thinking?) would be quickly revealed in the <strong>compile-time</strong>.</p><p>It is really precious gift to be able to check that things are correct in the compile-time. Instant feedback.</p><p>Of course, nothing stops a pesky and smart hacker to try to connect a device that allows typing sequences of both letters and numbers. It would be somehow translated to electrical signals that would try to break the <code>PinCode</code>.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token comment">// somewhere in a method...</span>
</span><span class="code-line">
</span><span class="code-line">SmartHackDevice
</span><span class="code-line">    <span class="token punctuation">.</span><span class="token function">ConnectTo</span><span class="token punctuation">(</span>safe<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">.</span><span class="token function">AccessWith</span><span class="token punctuation">(</span><span class="token string">&quot;hacking time!11!!&quot;</span> <span class="token keyword">as</span> <span class="token class-name"><span class="token keyword">object</span></span> <span class="token keyword">as</span> <span class="token class-name">PinCode</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre></div></div><p>The evil hacker might try as much as he can and nothing would stop him from giving input that no one designing the interface expected to get.</p><p>Still, all those trials are futile.</p><h3 id="valid-numbers-not-any-numbers"><a href="#valid-numbers-not-any-numbers" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Valid numbers, not any numbers</h3><p>It is really simple - someone designed the interface in the way that only numbers are allowed.</p><p>Things are different when it comes to validity of given <code>PinCode</code>.</p><p>One could stare at the pin pad and he or she wouldn&#x27;t know what is the valid <code>PinCode</code>.</p><p>Someone needs to act, to run an experiment in order to verify or falsify the assumption.</p><p>Either the evil hacker gives the invalid input or we mistyped the valid <code>PinCode</code>, the feedback happens during the interaction with the pin pad.</p><p>Not before, while interacting with it.</p><p>We could name it as the &quot;acting-time&quot; feedback, but in fact we already have a name for it - <strong>run-time</strong>.</p><p>Imagine that given the wrong <code>PinCode</code> (doesn&#x27;t matter how it got there), the <code>SecureSafe</code> would inform us about incorrect passpin (it&#x27;s a not pass<strong>word</strong> as there are no letters 😉) by throwing an exception <code>InvalidPasspinException</code>.</p><h3 id="offtopic-making-an-implicit-explicit"><a href="#offtopic-making-an-implicit-explicit" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Offtopic: making an implicit explicit</h3><p>How would we know about <code>InvalidPasspinException</code>?</p><p>Where is it mentioned?</p><p>Documentation?</p><p>Should the moment of getting the feedback about this exception, obtained from docs reading, be named as <strong>reading-documentation-time</strong>?</p><p>Let&#x27;s recall the interface:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">IAllowAccessingTheBlueBook</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name return-type">BlueBook</span> <span class="token function">AccessWith</span><span class="token punctuation">(</span><span class="token class-name">PinCode</span> pinCode<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Hm, nothing is mentioned here about any possible issue with using it.</p><p>Is it only the run-time in which we can get this feedback?</p><p>In <a href="https://talesfrom.dev/blog/essentially-bounded-accidentally-unlimited">Essentially bounded, Accidentally unlimited</a>, I concluded that:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>There is no single solution, but there is a single problem.</p></div></div></div><p>Getting the feedback as soon as possible is the &quot;problem&quot; here.</p><p>Typically in C#, exceptions are used to inform about reaching failure-ish states.</p><p>Functional languages come with a beautiful &quot;building block&quot; named <code>Result</code>/<code>Either</code> (in F# we use the first one).</p><p>It has various interesting properties but one of its responsibilities might be to document various states in which the given collaborator might end up in. (you can read more <a href="https://fsharpforfunandprofit.com/rop/">here</a>)</p><p>Some might say it&#x27;s not idiomatic in languages like C# - are they afraid of <a href="https://talesfrom.dev/blog/the-cost-of-modeling">The cost of modeling</a>?</p><h3 id="its-time-to-distribute-the-knowledge"><a href="#its-time-to-distribute-the-knowledge" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>It&#x27;s time to distribute the knowledge</h3><p>Seems like our efforts paid off - many of the people got their quotes and domain modeling is preserved.</p><p>Imagine all of those interactions with people, chats, discussions, and so on.</p><p>Everyone would feel a bit tired. Overjoyed, but tired.</p><p>Other folks decided to evangelize domain-driven thinking but they needed quotes from the book too.</p><p>There&#x27;s only one <code>SecureSafe</code> - what can we do?</p><p>It&#x27;s very simple - we need to place the <code>SecureSafe</code> in one spot, and make sure that one knight of The Order Of Hidden Sapphire is available for a call so that he can serve a person doing the phone call with an answer.</p><p>Of course, it&#x27;s questionable if we really need the <code>SecureSafe</code> right now. Someone protecting the resource would need to check the identity and permissions of the caller.</p><p>Nevermind, let&#x27;s assume we made agreed with each other that we will use Verbal Phone Token (VPT), it&#x27;s still based on <code>PinCode</code>.</p><p>Only the chosen, trustworthy ones know it.</p><h3 id="book-but-deferred"><a href="#book-but-deferred" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Book, but deferred</h3><p>Are we actually working with the <code>SecureSafe</code> right now?</p><p>Hard to say, as we don&#x27;t see any physical object.</p><p>What about the interfaces we used to interact with the <code>SecureSafe</code>?</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">IAllowAccessingTheBlueBook</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name return-type">BlueBook</span> <span class="token function">AccessWith</span><span class="token punctuation">(</span><span class="token class-name">PinCode</span> pinCode<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>The responsibility is exactly the same - but it&#x27;s postponed in time, as need to call our friend.</p><p>Let&#x27;s make the interface a little bit more closer to the truth - we want to document our intentions, right?</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">IAllowAccessingTheBlueBook</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>BlueBook<span class="token punctuation">&gt;</span></span> <span class="token function">AccessWith</span><span class="token punctuation">(</span><span class="token class-name">PinCode</span> pinCode<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Not a big change for us, though. Of course, we are not getting exact book, but it&#x27;s software right?</p><p>Everything is possible in the software world.</p><p>We will make <code>BlueBookQuote</code> inheriting from <code>BlueBook</code> and override <code>ToString</code> method so that we can use existing model and not pay <a href="https://talesfrom.dev/blog/the-cost/of-modeling">The cost of modeling</a>.</p><p>Easy.</p><p>We could say that our phone would adhere to the interface <code>IAllowAccessingTheBlueBook</code> - but under the hood it will dial the right number so that we will get the quote.</p><h3 id="can-you-hear-me"><a href="#can-you-hear-me" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Can you hear me?</h3><p>Imagine that we are during a session in which spread the knowledge from the <code>BlueBook</code>.</p><p>We got a request to get a quote - we just need to call our friend.</p><p>Dialing...</p><p>Waiting...</p><p>&quot;The person you are trying to reach is currently not available&quot;, the voice says.</p><p>Mother of God, not now.</p><p>We call him seven times in a row.</p><p>We send him a SMS. A voice message. An e-mail.</p><p>&quot;I NEED A BOOK&quot;, one of them stated.</p><p>Nothing.</p><p>No response.</p><h3 id="available-for-a-call-not-a-deferred-book"><a href="#available-for-a-call-not-a-deferred-book" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Available for a call, not a deferred book</h3><p>We went further with our agenda and suddenly we got interrupted by excessive call-backs from our friend.</p><p>Ten text messages, seventeen e-mails, pictures.</p><p>What the hell is happening?</p><p>Turns out that our friend, having a guard in the remote, secure place, was having a trouble with serving all the requests he was getting.</p><p>All called him, sent messages and he was not able to handle all the load.</p><p>He decided to take a break from this stressful time.</p><p>When he got back, he started handling it again but unfortunately he was not able to do it right.</p><h3 id="not-a-compile-time-not-a-run-time"><a href="#not-a-compile-time-not-a-run-time" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Not a compile-time, not a run-time?</h3><p>When did we encounter the problems with reaching our friend?</p><p>We could say - in the run-time. As we would discover them while having an interaction.</p><p>We would experience it in that moment, yes, does it make any difference if our friend was located in the same building, but in the next room?</p><p>When we distributed the ability to get the knowledge from the <code>BlueBook</code>, suddenly we got new set of problems. (you might be interested in another aspect of distributing the responsibilities - <a href="https://talesfrom.dev/blog/modularity-uncertainty-heuristic">Modularity Uncertainty Heuristic</a>)</p><p>As we used phone call, sending SMS, and sending e-mails - we stepped into another dimension, where network is involved.</p><p>One then could say that the problems were revealed at <strong>network-time</strong>.</p><p>Distributing the knowledge in space (remote location) and time (network communication) isn&#x27;t a matter of &quot;fixing interfaces&quot;.</p><p>As moving between <strong>compile-time</strong> and <strong>run-time</strong> seems easy, moving between both of them to <strong>network-time</strong>, is a big leap.</p><p>Network-time errors involve another dimension that might materialize in the runtime, but it doesn&#x27;t have to.</p><h3 id="network-time---what-are-other-dimensions"><a href="#network-time---what-are-other-dimensions" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Network-time - what are other dimensions?</h3><p>When hearing &quot;The person you are trying to reach is currently not available&quot; - the feedback is quite immediate - we need to try next time.</p><p>What would happen if we send an SMS - and there&#x27;s no answer - did the recipient see it?</p><p>Should we send another one?</p><p>Distributing the caller and the callee, changing the way of their communicating, from direct call to message sending, might not materialize the issue in &quot;run-time&quot;.</p><p>Of course, there are tools, methods, practices, patterns and principles (like <a href="https://en.wikipedia.org/wiki/Fallacies_of_distributed_computing">Fallacies of distributed computing</a>).</p><p>No doubt on that.</p><p>As compile-time errors and interprocess run-time errors are relatively easy to be encountered (and forced to occur), network-time ones require different mindset and perspective.</p><p>We spend some time on discussing the designed interfaces - how will it work when it comes to network-time errors?</p><p>Each of them involves a unique dimension, that requires analysis on its own.</p><p>Next time, dear Reader, when you would consider distributing any responsibility, ask yourself:</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>What network-time errors am I introducing by doing so?</p></div></div></div>]]></content:encoded>
    <pubDate>Mon, 17 Jul 2023 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>architecture</category><category>object-oriented</category><category>functional</category><category>programming</category><category>modeling</category><category>model</category><category>contexts</category><category>representations</category><category>mental models</category><category>heuristics</category><category>principles</category><category>patterns</category><category>design-thinking</category><category>contracts</category><category>service-oriented</category><category>microservices</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/i-interface</guid>
    <title>I, interface</title>
    <link>https://talesfrom.dev/blog/i-interface</link>
    <description>Have we misunderstood interfaces?</description>
    <content:encoded><![CDATA[<div class="bg-slate-600 rounded-xl mt-10"><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Kudos! 🙏🏻</span></div><div class="pb-2 px-3"><div class="break-words"><p>This tale wouldn&#x27;t be here if I didn&#x27;t have conversations with <a href="https://twitter.com/GGalezowski">Grzegorz Galezowski</a>.</p>
<p>We have tons of discussions (or rather me asking a plethora of questions and learning from  <a href="https://twitter.com/GGalezowski">Grzegorz Galezowski</a>), especially on Object-Oriented Analysis &amp; Design</p>
<p>Thanks <a href="https://twitter.com/GGalezowski">Grzegorz Galezowski</a> for your patience, your knowledge and sharing your experience with me!</p></div></div></div><h3 id="a-great-mystery"><a href="#a-great-mystery" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>A great mystery</h3><p>How many times have you seen an interface with the pattern: <code>I&lt;&lt;Your-Random-Name&gt;&gt;Service</code>, followed by a single implementation: <code>&lt;&lt;Your-Random-Name&gt;&gt;Service</code>?</p><p>Of course <code>I</code> prefix might sound odd to you, if you don&#x27;t come from .NET world, but we will get back to that.</p><p>It&#x27;s not that rare to encounter such an interesting phenomena.</p><p>There might be various incetives and reasons to pursue such pattern.</p><p>Typically, such specimen attracts many methods (not conflating it with behaviors yet!), most of them fulfilling query and command functions.</p><p>Of course, one might say that &quot;writing&quot; <code>&lt;&lt;Your-Random-Name&gt;&gt;Service</code>s is old-fashioned and now cool kids use CQRS, in the form of <code>IQueryHandler</code> and <code>ICommandHandler</code> family.</p><p>I don&#x27;t attack this approach (can a human attact an approach?), what&#x27;s more - I personally like the separation of concerns it potentially brings.</p><p>I am just worried we misunderstood interfaces.</p><h3 id="interface---public-api"><a href="#interface---public-api" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Interface - public API</h3><p>Are interfaces just a communication tool for letting consumers know on how to use them?</p><p>Or maybe they are required to enable loose coupling, open-closed principle and dependency injection through Inversion of Control (IoC) container?</p><p>Should they be used purely for &quot;polymorphism&quot; quality? (it&#x27;s possibly the only &quot;morphism&quot; that doesn&#x27;t make OO programmers scared)</p><p>Imagine that in a certain software product we need to work with a <code>Feedback</code> concept.</p><p>Some capabilities, related to it, are fulfilled by a <code>FeedbackService</code>, that implements, you won&#x27;t guess, <code>IFeedbackService</code> interface.</p><p>If we go to its public API, we might see:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">IFeedbackService</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name return-type">Task</span> <span class="token function">Give</span><span class="token punctuation">(</span><span class="token class-name">Feedback</span> feedback<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span><span class="token keyword">bool</span><span class="token punctuation">&gt;</span></span> <span class="token function">Approve</span><span class="token punctuation">(</span><span class="token class-name">Feedback</span> feedback<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span><span class="token keyword">bool</span><span class="token punctuation">&gt;</span></span> <span class="token function">Disapprove</span><span class="token punctuation">(</span><span class="token class-name">Feedback</span> feedback<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>IEnumerable<span class="token punctuation">&lt;</span>Feedback<span class="token punctuation">&gt;</span><span class="token punctuation">&gt;</span></span> <span class="token function">Get</span><span class="token punctuation">(</span><span class="token class-name">FeedbackSubject</span> feedbackSubject<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>It doesn&#x27;t look incorrect. It even tries to capture the language of the given domain.</p><p>Of course, as it works with <code>Feedback</code>, some other parties are interested in getting help from it, when working with various processes.</p><p>Imagine that one process, based on some conditions, wants to <code>Disapprove</code> a <code>Feedback</code>.</p><p>We would like to specify such behavior (provided that we have tests) so we can mock it and teach the test double how it should behave, e.g. when someone calls <code>Disapprove</code> method.</p><p>What about other methods?</p><p>We probably would just leave them as they aren&#x27;t used.</p><p>No harm, we could say.</p><h3 id="a-recipe"><a href="#a-recipe" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>A recipe</h3><p>As we are concerned with other methods, we could introduce CQRS and then have three commands and one query.</p><p>One could say original code is missing segregation of interfaces, one of the princinples of SOLID.</p><p>Our little interface looks as if it got segregated in a pretty good way - it aggregates methods on <code>Feedback</code>, isn&#x27;t it?</p><p>Such pairs, an interface, followed by the class named astonishingly similarly, are so common.</p><p>To create such structure, the recipe is simple:</p><ol><li>Create a class, name it accordingly (preferably focusing on the noun).</li><li>Add public methods and immediately add the code inside each of them.</li><li>Create an interface with the same name as the class, then add <code>I</code> as a prefix (only for .NET pros).</li><li>Make sure you covered all public methods.</li><li>Work with tests you wanted to touch and mock this new class with providing a mock for the interface.</li></ol><p>Voila!</p><p>What&#x27;s missing?</p><p>This recipe creates something in isolation. Without any feedback (pun intended) from its consumers.</p><p>Now when we work with our tests, we need to make a decision (consciously or subconsciously) what to do with the remaining methods we are not mocking.</p><p>Actually, this kind of interface (having multiple methods) is typically created <strong>AFTER</strong> writing any specification for its behavior.</p><p>And this leads to mocking an object, not a responsibilty, we might need from it.</p><h3 id="roles-responsibilities"><a href="#roles-responsibilities" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Roles, responsibilities</h3><p>Mocking object, not responsibility?</p><p>Fortunately for us, in their seminal work - <a href="http://jmock.org/oopsla2004.pdf">&quot;Mock Roles, Not Objects&quot;</a> - Steve Freeman, Nat Pryce, Tim Mackinnon, Joe Walnes - warn us from exactly what we described above.</p><p>If you haven&#x27;t read this paper (yes, a whitepaper!), stop reading this tiny tale and rush for reading this paper.</p><p>Really. I am not joking.</p><p>I assume you did so and we can go further, my dear Reader.</p><p>As they write:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>It is really a technique for identifying types in a system based on the <strong>roles</strong> that <strong>objects</strong> <strong>play</strong>.</p></div></div></div><p>So instead of focusing on what we did - meaning, focusing on objects - we should think of the roles that those objects are playing.</p><p>Of course this rises another question - what do we mean by &quot;a role&quot;, in the context of playing it?</p><p>We could bring Sandi Metz&#x27;s words from <a href="https://www.youtube.com/watch?v=XXi_FBrZQiU&amp;ab_channel=SandiMetz">&quot;Polly want a message&quot;</a>:</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">Role-playing</div><div class="pb-2 px-3"><div class="break-words"><p>Objects are more players of their roles than instances of their types.</p></div></div></div><p>Taking into account Sandi&#x27;s great explanatory skills, it&#x27;s really interesting perspective.</p><p>If we involve our fellow <code>FeedbackService</code> class and try to talk to it (yes, talk to it - if you&#x27;re curious of what am I talking about, please check <a href="https://talesfrom.dev/blog/conversation-driven-design">Conversation-Driven Design</a>).</p><p>What its answers would be when asked about its role?</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Talk</div><div class="cursor-pointer border-2 border-l-0 border-b-0 border-gray-50 w-48 text-center text-gray-700">Listen carefully</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><p>Us: Hi FeedbackService!</p></span><span class="text-white"><p>FeedbackService: Yo! What&#x27;s up?</p></span><span class="text-white"><p>Us: We are wondering, what is your role?</p></span><span class="text-white"><p>FeedbackService: Role? What do you mean by &quot;a role&quot;?</p></span><span class="text-white"><p>Us: You know, what is expected from you - what you need to know to be productive and useful.</p></span><span class="text-white"><p>FeedbackService: Ah. Typically in my role, <span class="">I get all feedback </span>, <span class="">I give feedback </span>, <span class="">I approve feedback</span>. Almost forgot, <span class="">I disapprove feedback </span>too.</p></span></div><p>Interesting. Maybe we can&#x27;t really say what is <code>FeedbackService</code>&#x27;s role just by looking at it when it&#x27;s not &quot;moving&quot;, or rather not doing anything.</p><p>It might be easier to get the notion of the role it plays when we think of what it is responsible for!</p><h3 id="dreaded-i-prefix"><a href="#dreaded-i-prefix" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Dreaded <code>I</code> prefix</h3><p>There are many jokes, confusions and interesting (but not productive?) discussions about .NET and <code>I</code> suffix.</p><p>But I believe we might use it for changing the way we think of interfaces.</p><p>Let&#x27;s recap what <code>FeedbackService</code> mentioned that it is doing when it plays its role:</p><ul><li>&quot;I get all feedback&quot;</li><li>&quot;I give feedback&quot;</li><li>&quot;I approve feedback&quot;</li><li>&quot;I disapprove feedback&quot;</li></ul><p>Read it aloud, please.</p><p>Have you captured it?</p><p>In many lanuages, the most basic statement structure follows &quot;SVO&quot; pattern: <code>&lt;&lt;Subject&gt;&gt; &lt;&lt;Verb&gt;&gt; &lt;&lt;Object&gt;&gt;</code>.</p><p>With this amazing knowledge, <code>FeedbackService</code> words (actually those were mine but let&#x27;s pretend, ok?), we can combine them into interfaces:</p><ul><li><code>IGetAllFeedback</code></li><li><code>IGiveFeedback</code></li><li><code>IApproveFeedback</code></li><li><code>IDisapproveFeedback</code></li></ul><p>When you read it aloud, it even sound as if a real person said so.</p><p>Just for our little tale, we could change <code>FeedbackService</code> from this:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">FeedbackService</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">IFeedbackService</span></span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">//...details here</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>into this:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">FeedbackService</span> <span class="token punctuation">:</span> 
</span><span class="code-line">                <span class="token type-list"><span class="token class-name">IGetAllFeedback</span><span class="token punctuation">,</span>
</span></span><span class="code-line"><span class="token type-list">                <span class="token class-name">IGiveFeedback</span><span class="token punctuation">,</span>
</span></span><span class="code-line"><span class="token type-list">                <span class="token class-name">IApproveFeedback</span><span class="token punctuation">,</span>
</span></span><span class="code-line"><span class="token type-list">                <span class="token class-name">IDisapproveFeedback</span></span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">//...details here</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>One could go even further and try to &quot;humanize&quot; it a bit and say:</p><p>&quot;as a <code>FeedbackService</code>, I get all feedback, I give feedback, I approve feedback, I disapprove feedback&quot;.</p><p>Exactly the same as <code>FeedbackService</code> replied when we had a short conversation with it!</p><p>Those interfaces, or those responsibilities, are highly fine-grained.</p><h3 id="its-not-a-real-life-example"><a href="#its-not-a-real-life-example" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;It&#x27;s not a real life example&quot;</h3><p>Maybe too fine-grained?</p><p>Yes, it might be.</p><p>One could argue it&#x27;s very artificial, theoretical scenario.</p><p>Segregating them in that way might sound dogmatic too.</p><p>Eventually, it&#x27;s all about the <code>Feedback</code>, so why bothering to cut a single interface into pieces?</p><p>Let&#x27;s pay attention to the words, again. How probable it is that the same person would both approve/disapprove feedback and give it?</p><p>Not so much, I would say.</p><p>And what about getting all feedback and giving it? Might be similar to the first answer - not so much.</p><p>If we &quot;translate&quot; our example into the real world scenario - will it be a single person or two people?</p><p>Could it be that there are actually two people, playing two different roles?</p><p>The first role might be concerned about evaluating something, and the second might be interested in evaluating evaluation, aren&#x27;t they?</p><p>Imagine there&#x27;s a customer that bought a product and is asked to give feedback. When this feedback is gathered, someone needs to assess how trustworthy this feedback actually is.</p><p>Our <code>FeedbackService</code> might cease to exist. It will turn into two roles instead:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">IFeedbackGiver</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">IGiveFeedback</span></span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">//...</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">IFeedbackAuditor</span> <span class="token punctuation">:</span> 
</span><span class="code-line">                    <span class="token type-list"><span class="token class-name">IGetAllFeedback</span><span class="token punctuation">,</span>
</span></span><span class="code-line"><span class="token type-list">                    <span class="token class-name">IApproveFeedback</span><span class="token punctuation">,</span>
</span></span><span class="code-line"><span class="token type-list">                    <span class="token class-name">IDisapproveFeedback</span></span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">//...</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>They have exemplary names, of course - role such as &quot;feedback auditor&quot; might not exist in the real life.</p><h3 id="domain-exploration---the-side-effect"><a href="#domain-exploration---the-side-effect" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Domain exploration - the side-effect</h3><p>But what if it does? Is it something we could verify with our domain experts?</p><p>Such segregation makes roles, bounded by responsibilities, oriented toward behaviors - meaning verbs.</p><p>And verbs summon the context.</p><p>All this makes fat &quot;interfaces&quot; (which turn out not to be real roles) get exercised through domain lenses and become fitting into a particular role.</p><p>When we challenge ourselves by resisting to name everything as a <code>&lt;&lt;Your-Random-Name&gt;&gt;Service</code>, we might discover missing concepts too. Concepts that exist in the lanugage but they are not materialized in the code.</p><p>&quot;What I cannot see, it doesn&#x27;t exist&quot;, as the saying goes.</p><p>Let&#x27;s then revisit role that approves feedback:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">IApproveFeedback</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span><span class="token keyword">bool</span><span class="token punctuation">&gt;</span></span> <span class="token function">Approve</span><span class="token punctuation">(</span><span class="token class-name">Feedback</span> feedback<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>We could ask: &quot;is it any feedback I approve?&quot;</p><p>Now, it might become straightforward that it&#x27;s not every feedback - but the one that was given.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">IApproveFeedback</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span><span class="token keyword">bool</span><span class="token punctuation">&gt;</span></span> <span class="token function">Approve</span><span class="token punctuation">(</span><span class="token class-name">GivenFeedback</span> feedback<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Then, both <code>Approve</code>/<code>Disapprove</code> actions might create <code>EvaluatedFeedback</code> that has totally different rules associated with it.</p><p>Soon, we might become aware that we are using <a href="https://talesfrom.dev/blog/language-of-the-problem">Language of the problem</a>.</p><p>And as we broaden our language, <code>Feedback</code> gradually stops looking like &quot;an entity&quot; (what am I talking about? If you&#x27;re intersted, please check <a href="https://talesfrom.dev/blog/concept-maps">Concept maps</a>).</p><h3 id="responsibilitity-means-function"><a href="#responsibilitity-means-function" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Responsibilitity means &quot;function&quot;?</h3><p>If we stop being .NET pros, just for a while, and drop <code>I</code> prefix from our newly discovered responsibilities?</p><p>What would they become?</p><p>Each of those narrow interfaces require only one method, from an object, to implement.</p><p>Let&#x27;s take <code>IApproveFeedback</code> and try this process on it.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">IApproveFeedback</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span><span class="token keyword">bool</span><span class="token punctuation">&gt;</span></span> <span class="token function">Approve</span><span class="token punctuation">(</span><span class="token class-name">Feedback</span> feedback<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>It becomes just <code>ApproveFeedback</code> and as it has single method - can we try to approximate it with a <a href="https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/delegates/">.NET delegate</a>?</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">delegate</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span><span class="token keyword">bool</span><span class="token punctuation">&gt;</span></span> <span class="token function">ApproveFeedback</span><span class="token punctuation">(</span><span class="token class-name">Feedback</span> feedback<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre></div></div><p>So our responsibility became a delegate. As a delegate represents a function, responsibilities can be thought of as functions too.</p><p>We could say that a role is shaped by the functions it provides.</p><p>When we apply <a href="https://talesfrom.dev/blog/i-interface#domain-exploration---the-side-effect">recently explored domain knowledge</a>, we could say <code>ApproveFeedback</code> is a function (a delegate) that turns a <code>GivenFeedback</code> into an <code>EvaluatedFeedback</code>. So it becomes:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">delegate</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>EvaluatedFeedback<span class="token punctuation">&gt;</span></span> <span class="token function">ApproveFeedback</span><span class="token punctuation">(</span><span class="token class-name">GivenFeedback</span> feedback<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre></div></div><p>Signature expresses the contract between two sides, and instead of using technical terms, let&#x27;s read it aloud in a human-oriented way:</p><p>&quot;<code>EvaluatedFeedback</code> will be provided back (in the future), when <code>ApproveFeedback</code> is provided with <code>GivenFeedback</code>&quot;.</p><p>It might sound a bit odd - the reason might lay in providing the expected results firstly and then required input.</p><p>Could we reverse it?</p><p>C# language has its syntax and we need to adhear to it. The best would be to express it as the following:</p><p>&quot;<code>ApproveFeedback</code> promises to turn <code>GivenFeedback</code> into <code>EvaluatedFeedback</code>, at some point in the future.&quot;</p><p>Let&#x27;s do small changes and translate:</p><ul><li><code>promises to</code> into <code>=</code></li><li><code>turn X into Y</code> into <code>X -&gt; Y</code></li><li>and <code>at some point in the future</code> into <code>Future&lt;Y&gt;</code>.</li></ul><p>Then it all becomes:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="code-highlight language-fsharp"><span class="code-line">ApproveFeedback <span class="token operator">=</span> GivenFeedback <span class="token operator">-&gt;</span> Future<span class="token operator">&lt;</span>EvaluatedFeedback<span class="token operator">&gt;</span>
</span></code></pre></div></div><p>Interestingly, it looks astonishingly similar to a function type syntax in F#. The only thing to make it compile correctly is adding a <code>type</code> keyword before everything:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="code-highlight language-fsharp"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">ApproveFeedback</span> <span class="token operator">=</span> GivenFeedback <span class="token operator">-&gt;</span> Future<span class="token operator">&lt;</span>EvaluatedFeedback<span class="token operator">&gt;</span>
</span></code></pre></div></div><p>Also, there is no <code>Future</code> type in F# so we would need to &quot;make&quot; one:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="code-highlight language-fsharp"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">Future</span><span class="token operator">&lt;</span>&#x27;PromisedValue<span class="token operator">&gt;</span> <span class="token operator">=</span> Async<span class="token operator">&lt;</span>&#x27;PromisedValue<span class="token operator">&gt;</span>
</span></code></pre></div></div><p>So I lied to you - those were two things that were missing, eventually.</p><p>With this little example, one might observe that &quot;one-method&quot;, narrow, interfaces realize the same function as functions (pun intended) in functional(-first) languages. What&#x27;s more, we can think in responsibility-terms in functional languages too!</p><p>What we actually gain through this segregation is that we might be very precise in selecting objects to play a very specific role - or fulfill a very specific function.</p><p>Similarly to function composition, such atomic &quot;isolation&quot; enables responsibilities compositionality into something bigger - a role. (yes - <em>composition</em> and <em>compositionality</em> are different terms!)</p><h3 id="a-responsibilitity-is-not-a-method-a-role-is-not-an-interface"><a href="#a-responsibilitity-is-not-a-method-a-role-is-not-an-interface" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>A responsibilitity is not a method, a role is not an interface</h3><p>Both roles and responsibilities are something more than interfaces with bunch of methods glued together.</p><p>They express higher-level concepts by capturing the language that lives in the problem area.</p><p>Unfortunately, we often mix everything together, without paying much attention to underlying concepts, rules and contextual details.</p><p><a href="http://jmock.org/oopsla2004.pdf">&quot;Mock Roles, Not Objects&quot;</a> enlightens the path by recommending to put our focus on &quot;Need-Driven Development&quot; in order to &quot;discover the interfaces&quot;, or rather we should say - &quot;to discover roles and responsibilities&quot;.</p><p>This can be done with &quot;specification-driven development&quot; (if you are interested in what I am talking about, please check <a href="https://talesfrom.dev/blog/the-ambiguity-of-tdd">&quot;The ambiguity&quot; of TDD</a>) and orienting toward the usage - needs coming from the consumers that require such responsibilities.</p><p>Given that we are exploring the responsibilities and roles, or &quot;interfaces&quot;, with respect to requirements put by the service takers, they eventually become narrower and smaller.</p><p>Next time, dear Reader, <a href="https://talesfrom.dev/blog/slow-down">Slow down</a>, consciously whisper to yourself <a href="https://talesfrom.dev/blog/i-dont-know">&quot;I don&#x27;t know&quot;</a> and ask yourself an exploratory question:</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>Am I defining a bag of methods or a role with responsibilities?</p></div></div></div>]]></content:encoded>
    <pubDate>Sun, 02 Jul 2023 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>oop</category><category>object-oriented</category><category>programming</category><category>roles</category><category>language</category><category>modeling</category><category>model</category><category>contexts</category><category>representations</category><category>mental models</category><category>heuristics</category><category>blasphemy</category><category>principles</category><category>patterns</category><category>design-thinking</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/overdebugging</guid>
    <title>Overdebugging</title>
    <link>https://talesfrom.dev/blog/overdebugging</link>
    <description>Are you addicted to debugging?</description>
    <content:encoded><![CDATA[<h3 id="changes"><a href="#changes" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Changes</h3><p>Change, change never changes.</p><p>Imagine there was a new feature request and turns out that some of it needs to be &quot;added&quot; to existing parts.</p><p>Changing the existing code.</p><p>What feelings would you have?</p><p>Excitement?</p><p>Fear?</p><p>Joy?</p><p>We are professionals so it&#x27;s not daunting to work with such an event.</p><p>Requirements are pretty straightforward so it should be a breeze to find a proper solution.</p><h3 id="how-does-it-work"><a href="#how-does-it-work" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>How does it work?</h3><p>Depending on the habits, experience and approach, various people start from different positions.</p><p>Some are sketching (e.g. using <a href="https://excalidraw.com">excalidraw</a>) to perform more visual thinking.</p><p>Others are just rushing and jumping into the code and hack things around to test out some concepts and ideas.</p><p>Eventually, everything starts and ends in the code itself.</p><p>Let&#x27;s pretend, as we are changing existing code, that there is a massive legacy method (or a function).</p><p>Hundreds of lines.</p><p>Of course, there are some private methods (or non-exported functions), so there is some decomposition.</p><p>As it was long time that we&#x27;ve touched this code, we need to build mental representation of this code.</p><p>What could we do?</p><p>Probably, the simplest thing is to just run the system - whether it is an API endpoint, SPA application&#x27;s specific view or similar.</p><p>Turns out, in order to understand it better, we placed a bunch of log statements and few debugging breakpoints.</p><p>Quite familiar, isn&#x27;t it?</p><h3 id="not-working"><a href="#not-working" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Not working?</h3><p>After understanding how the system works at the current moment, we rushed to put some new code here and there.</p><p>Maybe we extracted some more private methods (or non-exported functions) and made the code a little bit &quot;cleaner&quot; (subjectively, of course).</p><p>Running the system again and boom - doesn&#x27;t work as we would expect it to.</p><p>Simple - let&#x27;s add more logging and breakpoints to see where did we fail with transferring our understanding.</p><p>Couple of more loops with such breakpoint/log steps, interleaved with running the system, and we are almost finished.</p><p>Finally, expectactions are met.</p><h3 id="what-problem-are-we-trying-to-solve"><a href="#what-problem-are-we-trying-to-solve" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What problem are we trying to solve?</h3><p>Whether we are running the system to understand how does it work or to check if the increments works as we want to - we keep expectactions in our mind.</p><p>We can put log statements, breakpoints, or other &quot;inspection&quot; tools, with a specific purpose - to check expected behavior.</p><p>So expecations are implicitly kept in our heads, whereas &quot;inspection&quot; instruments will provide the feedback about the functional state of the given part of the system.</p><p>Without neglecting the simplicitly of such approach, and pretty fast feedback coming from utilizing it, it has its flaws.</p><p>Log statement just informs us about inner state and we are then judging if it matches our expectations or not.</p><p>&quot;It&#x27;s just a log&quot;, one might say.</p><p>In <a href="https://talesfrom.dev/blog/essentially-bounded-accidentally-unlimited">Essentially bounded, Accidentally unlimited</a>, I concluded that:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>There is no single solution, but there is a single problem.</p></div></div></div><p>So actually, what problem do we want solve to right now? (if you are interested where does this question come from, please check <a href="https://talesfrom.dev/blog/software-engineering-for-busy-parents">Software Engineering for busy parents</a>)</p><p>whether the system is doing what we expect.</p><p>In other words, whether the system is satisfying our expectations, we specified in our mind through some mental representations.</p><h3 id="expectations"><a href="#expectations" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Expectations?</h3><p>One possible solution is to use debugging approach by placing log statements or breakpoints.</p><p>Run the system, let the debugger hit the breakpoint, we are at home. How many levels did we cross? Doesn&#x27;t matter, the problem is solved (of inspecting the system&#x27;s state).</p><p>For now.</p><p>We can inspect the state of the system to confirm or to falsify expectations.</p><p>This is probably the most straightforward approach.</p><p>What could be an alternative solution?</p><p>There are some key concepts we can enumerate: expectactions (or requirements), specification of them, feedback.</p><p>Does it ring a bell?</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>What problem are we trying to solve right now?</p></div></div></div><p>As you probably guessed, I am thinking about specifying expectations, of how the (sub)system should work, through tests (you might wonder why I am so expressive - if you are curious, please check <a href="https://talesfrom.dev/blog/the-ambiguity-of-tdd">&quot;The ambiguity&quot; of TDD</a>).</p><p>This is another way of how we can get the feedback from the system (or its part(s)).</p><h3 id="how-fast-can-you-write-a-specification"><a href="#how-fast-can-you-write-a-specification" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>How fast can you write a specification?</h3><p>&quot;But it might be slower than just putting a bunch of breakpoints or log statements.&quot;, one might say.</p><p>Creating a test file, thinking of proper cases and so on. It is an initial effort, an investment, one needs to do.</p><p>What if writing tests, for a particular part of the (sub)system, is difficult? Should we really blame tests for that?</p><p>Obstacles, obstacles everywhere.</p><p>As we are professionals, and we don&#x27;t like to waste time (do we?), it&#x27;s quicker to put those log statements.</p><p>It doesn&#x27;t require that much of the mental energy.</p><p>But aren&#x27;t we lying to ourselves?</p><p>As my friend, <a href="https://twitter.com/PrzemekWolnik">Przemek Wolnik</a>, says: &quot;head isn&#x27;t the best place to keep ideas&quot;, we could use similar reasoning and say:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Head isn&#x27;t the best place to keep expecations.</p></div></div></div><p>Soon, mentioned mental energy would be required to load the state of the system into our head, follow each line, understand bits and pieces.</p><p>So we are not getting read of thinking about the scenarios in which our system currently might be, we are just deferring it.</p><p>What&#x27;s more, we are not leaving any trace for others (including future ourselves), what was expected behavior.</p><h3 id="overdebugging"><a href="#overdebugging" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Overdebugging</h3><p>Placing logs here and there also doesn&#x27;t encourage decomposing our system into smaller, manageable parts.</p><p>It might be a band-aid for a broken arm - if our methods/classes/functions are large.</p><p>Breakpoints might be even much more &quot;effortless&quot;.</p><p>Yet again, they don&#x27;t give feedback about the structure of our system.</p><p>It&#x27;s easy to add breakpoint or log statement to get feedback from runtime state, but we won&#x27;t get any feedback on the architecture, structure, and coupling (and cohesion too).</p><p>Tests could tell us so (if we are actually listening to them!).</p><p>Sometimes I feel we are addicted to debugging (either through breakpoints or logging). Almost as if we were tempted to try out the narcotic called &quot;debugger&quot;.</p><p>It gives the dopamine rush, an immediate reward, leaving with an unspoken feeling of emptiness.</p><p>How to break out of this viscious circle?</p><h3 id="dont-keep-specifications-in-your-head"><a href="#dont-keep-specifications-in-your-head" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Don&#x27;t keep specifications in your head</h3><p>Firstly, you need to admit you are addicted.</p><p>Don&#x27;t be shy, tell it aloud: &quot;I am addicted to debugging&quot;.</p><p>Secondly, try to specify really simple, happy path cases, in the form of a plain text list, what do you expect from a part of your system, that you are currently working with.</p><p>Finally, start with the first item on the list and try to write a test for it.</p><p>It might not be that easy. Don&#x27;t get discouraged.</p><p>This is a signal, a feedback, a message from the friendly world (or test?) about your system - use it wisely!</p><ul><li>Does it take a lot of the time to set up and run the first test? Then maybe you need to work on making this processe easier and faster.</li><li>You can&#x27;t test a given piece of functionality? Then maybe you need to extract a smaller function/class and test just it.</li><li>Your code relies on external services (e.g. browser localstorage or 3rd party service)? Then maybe you are missing proper abstraction.</li></ul><p>There is no finite set of answers on where and how to start, but it boils down to finding the simplest possible case and not being afraid of writing the &quot;ugly&quot; code to satisfy it.</p><h3 id="no-debugging-more-testing"><a href="#no-debugging-more-testing" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>No debugging, more testing</h3><p>Next time, when you will feel the urge to run the entire (sub)system, place breakpoints or a bunch of log statements to inspect the state - <a href="https://talesfrom.dev/blog/slow-down">slow down</a>.</p><p>Take your time for explicitly specifying what are you expecting to see, e.g. in the log statements, and try to write your first specification through a test.</p><p>If it&#x27;s difficult and you feel miserable - you can be grateful and say &quot;thank you&quot; to this little hero - to a test.</p><p>It is your ally in design and development. If you treat it well and ask for help, soon you will be rich in information about the state of your system.</p><p>You can even use a specific discipline and restrict yourself from debugging and logging - only specifications.</p><p>Sooner or later, it (specification-driven development) will become a habit.</p><p>Of course, you can ask, dear Reader, &quot;should I always use this approach?&quot;.</p><p>My answer is stable - yes, my zealot, and now - give me fifty.</p><p>Treat it as a play or an exercise. The only thing you can lose are some ego points when you&#x27;ll be struggling.</p>]]></content:encoded>
    <pubDate>Wed, 07 Jun 2023 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>behavior</category><category>specification</category><category>intent</category><category>model</category><category>representations</category><category>mental models</category><category>principles</category><category>patterns</category><category>design-thinking</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/concept-maps</guid>
    <title>Concept maps</title>
    <link>https://talesfrom.dev/blog/concept-maps</link>
    <description>Why are we hiding the transformational nature of the problems?</description>
    <content:encoded><![CDATA[<h3 id="can-you-build-it"><a href="#can-you-build-it" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Can you build it?&quot;</h3><p>Imagine we were challenged to build a software for organizing workshops.</p><p>Investor came and suggested that they have a brilliant idea and their novel approach will make millions.</p><p>Because of being a &quot;yes-man&quot; type of people, we said &quot;yes&quot;.</p><p>We called them for another meeting in order to get proper details.</p><h3 id="what-is-the-relationship"><a href="#what-is-the-relationship" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What is the relationship?</h3><p>They started laying out the information (for your information: the &quot;speech&quot; is a raw stream of characters/words/sentences to simulate &quot;real-life&quot; conversation, or monologue if you wish - &quot;real-life&quot; means cognitive loading).</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><p>Investor: in our world, a workshop starts as an idea. An organizer tinkers about the possible schedule. By the way, this party is our target customer. Later, they will plan a detailed schedule, choose a premise and measure how many prospects are potentially interested in such a planned workshop. Each schedule will have a bunch of sessions, covered by teachers, but this will come only when they &quot;approve&quot; the workshop, based on the return of investment they can get. Given those workshop details, a workshop gets published so that people can sign up for it. Let&#x27;s imagine that 100 people signed up. Statistically, 40% won&#x27;t come so remaining 60% will be considered as &quot;attending&quot;. This constitutes a workshop - people attending to a session conducted by a teacher. When workshop is finished, we are almost done. The last piece is actually &quot;measuring&quot; the workshop reception by getting &quot;rates&quot; - of course this can be done only after the workshop is finished.</p></span></div><p>Apparently, they were technical IT folks, who built many enterprise solutions.</p><p>The investor suggested drawing a data model in order to provide clarity what is related to what.</p><p>As we are experienced too, we focused on the entities, or nouns, if you will.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/entities-nouns.png" class="max-h-[40rem]"/></div><div class="italic mx-24">What concepts are there?</div></div><p>We weren&#x27;t lazy so we got some additional questions about how those things are related to each other - as they suggested.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/entities-nouns-relations.png" class="max-h-[40rem]"/></div><div class="italic mx-24">How concepts are related to each other?</div></div><p>Now, the chaos started becoming tamed.</p><p>The orders began emerging.</p><p>As expected - a <code>Workshop</code> is a central entity there.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/entities-nouns-relations-main-entity.png" class="max-h-[40rem]"/></div><div class="italic mx-24">Main entity in our data model</div></div><p>What&#x27;s more, we listened carefully and our model includes a possibility that a <code>Workshop</code> can have no <code>Premise</code> or no <code>Attendee</code>s.</p><p>Only when an organizer has an &quot;idea&quot; for a <code>Workshop</code>.</p><p>Does our model cover that?</p><p>We are experienced developers and/or architects, we know how to deal with such a problem.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/entities-nouns-relations-main-concept-status.png" class="max-h-[40rem]"/></div><div class="italic mx-24">a <code>Workshop</code> has a <code>Status</code>.</div></div><p>Trivial! A <code>Status</code>.</p><p>Now, finally, everything is complete - our model is flexible - we can model &quot;a workshop, that is a mere idea, can have no attendees and no premise&quot;.</p><p>Good&#x27;n&#x27;old <code>Status</code> solves that and we can even write a specification, in the form of a test, for it: <code>should create a workshop with status &#x27;WorkshopIdea&#x27; having no premise and having no attendees</code>. (Curious why am I so explicit about specification and test? Please check <a href="https://talesfrom.dev/blog/the-ambiguity-of-tdd">&quot;The ambiguity&quot; of TDD</a>)</p><p>Terrific.</p><h3 id="how-it-evolves"><a href="#how-it-evolves" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>How it evolves?</h3><p>What do you feel right now?</p><p>Does it look familiar?</p><p>Can we, taking into account our data model, tell anything about what is possible? What activities, operations and rules are there?</p><p>We could argue - that&#x27;s only a <strong>data</strong> model, it&#x27;s a single view on the system.</p><p>Does it express what the investor was telling us? Sure - one might say.</p><p>If we wanted to look how the central &quot;entity&quot;, a <code>Workshop</code>, evolves - where could we find this information?</p><p>Possibly in the &quot;user story&quot; or in an &quot;issue&quot; in Github.</p><p>Maybe even in a executable specification as a test!</p><p>This <strong>data</strong> model expresses the static aspects of this small realm - a realm of how entities are related when thinking about workshop organizing.</p><p>When we look from a <a href="https://talesfrom.dev/blog/modeling-maturity-levels">Modeling Maturity Levels</a> perspective, we captured the reality in the form a <code>Being</code> aspect.</p><p>As a reminder for ourselves, each aspect is related to a set of questions one might use to model this aspect.</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">Being - related questions</div><div class="pb-2 px-3"><div class="break-words"><p>What it has? What does it consist of? What is it?</p></div></div></div><p>Clearly, we can say that, for instance:</p><ul><li>a <code>Workshop</code> has none or many <code>Attendee</code>s</li><li>a <code>Workshop</code> consists of none or many schedules</li><li>a <code>Session</code> has one to three <code>Teacher</code>s,</li><li>etc.</li></ul><p>Simple.</p><p>But can we capture the problem space from a different level - still focusing on the main concept? (please pay attention I deliberately used a &quot;concept&quot; word instead of an &quot;entity&quot;)</p><h3 id="look-ma---no-status"><a href="#look-ma---no-status" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Look Ma - no status!&quot;</h3><p>Let&#x27;s try to pay attention to the language.</p><p>Our investor haven&#x27;t used <code>Status</code> in their stream of words.</p><p>What have their used? (play with the discussion by clicking on the tab titles)</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Listen</div><div class="cursor-pointer border-2 border-l-0 border-b-0 border-gray-50 w-48 text-center text-gray-700">Listen carefully</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><p>Investor: in our world, a <span class="">workshop </span>starts as an <span class="">idea</span>. An organizer tinkers about the possible schedule. By the way, this party is our target customer. Later, they will plan a detailed schedule, choose a premise and measure how many prospects are potentially interested in such a <span class="">planned workshop</span>. Each schedule will have a bunch of sessions, covered by teachers, but this will come only when they <span class="">&quot;approve&quot; </span>the <span class="">workshop</span>, based on the return of investment they can get. Given those workshop details, <span class="">a workshop gets published </span>so that people can sign up for it. Let&#x27;s imagine that 100 people signed up. Statistically, 40% won&#x27;t come so remaining 60% will be considered as &quot;attending&quot;. This constitutes a <span class="">workshop </span>- people attending to a session conducted by a teacher. When <span class="">workshop is finished</span>, we are almost done. The last piece is actually &quot;measuring&quot; the <span class="">workshop </span>reception by getting <span class="">&quot;rates&quot;</span>- of course this can be done only after the <span class="">workshop is finished</span>.</p></span></div><p>By carefully listening, we were able to capture the following group of words:</p><ul><li>&quot;workshop idea&quot;</li><li>&quot;planned workshop&quot;</li><li>&quot;&#x27;approve&#x27; workshop&quot;</li><li>&quot;workshop gets published&quot;</li><li>&quot;workshop&quot;</li><li>&quot;workshop is finished&quot;</li><li>&quot;workshop &#x27;rates&#x27;&quot;</li></ul><p>Of course, there might be much more, but at least that&#x27;s what we were able to find.</p><p>Let&#x27;s draw them.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/various-workshops.png" class="max-h-[40rem]"/></div><div class="italic mx-24">Is there a single workshop?</div></div><p>We used &quot;nouns&quot; with a &quot;companion&quot; - an &quot;adjective&quot;. Just by doing so, the context got enriched.</p><h3 id="are-they-similar"><a href="#are-they-similar" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Are they similar?</h3><p>Based on the discussion we had, we know that each &quot;workshop&quot; might have some different details - or maybe differently <strong>named</strong> details?</p><p>Let&#x27;s take the first one - <code>Workshop &quot;Idea&quot;</code>.</p><p>We know that it comes from an <code>Organizer</code> and we can assume there&#x27;s nothing more than a <code>Schedule</code> (is it <strong>any</strong> Schedule?). Let&#x27;s model it further.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/workshop-idea.png" class="max-h-[40rem]"/></div><div class="italic mx-24">&quot;workshop idea&quot; has a...</div></div><p>We can assume, by knowing what our investor mentioned, when they think it&#x27;s a good &quot;idea&quot;, then they start working on a <code>Planned Workshop</code>.</p><p>An <code>Organizer</code> checks how many <code>Prospect</code>s might be interested for attending.</p><p>Let&#x27;s model that.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/workshop-idea-planned.png" class="max-h-[40rem]"/></div><div class="italic mx-24">&quot;planned workshop&quot; has a...</div></div><p>We know that when an <code>Organizer</code> feels it pays off to run a <code>Workshop</code>, they approve it and publish it so that people can sign up.</p><p>This is the time when teachers are appearing with a detailed schedule.</p><p>Let&#x27;s model that.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/workshop-idea-planned-published.png" class="max-h-[40rem]"/></div><div class="italic mx-24">&quot;published workshop&quot; has a...</div></div><p>Finally, when the time comes, a <code>Workshop</code> is run - there are <code>Session</code>s carried by a <code>Teacher</code> for <code>Attendee</code>s.</p><p>Then, when the time is up, <code>Workshop</code> becomes <code>Finished Workshop</code>.</p><p>Eventually, people can rate the <code>Finished Workshop</code> so it becomes <code>Rated Workshop</code>.</p><p>Let&#x27;s see it.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/workshop-all.png" class="max-h-[40rem]"/></div></div><h3 id="where-are-my-relations"><a href="#where-are-my-relations" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Where are my relations?&quot;</h3><p>I hear you, my dear Reader: &quot;where are the lines?&quot;, &quot;what are those floating gizmos?!&quot; (or am I hearing myself?)</p><p>Is there any point to put <strong>lines</strong>?</p><p>I believe one could get the feeling of what is communicated through this little &quot;model&quot;, even without &quot;lines&quot;.</p><p>Actually, the lines might no longer exist.</p><p>Why? Because we don&#x27;t need lines. We need <strong>arrows</strong>.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/organizing-workshop-process.png" class="max-h-[40rem]"/></div></div><p>Suddenly, instead of a &quot;static&quot; relations, we got a flow, a direction.</p><p>Our model stopped envisioning structures and started expressing the process.</p><p>It shows how &quot;things&quot; are getting transformed over a period of time (note that there&#x27;s no timeline drawn!)</p><p>And where is our &quot;friend&quot;, <code>Status</code>?</p><h3 id="there-is-no-spoon"><a href="#there-is-no-spoon" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;There is no spoon&quot;</h3><p>What if I told you there is no spoon, ekhm, status?</p><p>At least on this level.</p><p>We don&#x27;t need it because we tried modeling domain concepts by capturing the language. Our investor didn&#x27;t mention any status!</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/there-is-no-status.png" class="max-h-[40rem]"/></div></div><p>It still might appear and live a good life but in totally different plane.</p><p>What plane?</p><p>Infrastructure - think of sending it over the wire or storing it in a database - &quot;status&quot; is a word that &quot;infrastructure experts&quot; use when it comes to mentioned activities.</p><p>Domain-Driven Design encourages modeling solutions around the language - and &quot;status&quot; has its place too - in the &quot;domain&quot; of the infrastructure.</p><h3 id="nouns--bad-verbs--good"><a href="#nouns--bad-verbs--good" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Nouns = bad, Verbs = good</h3><p>Modeling around behaviors, hence &quot;verbs&quot;, was always a desired direction, however, not always followed.</p><p>We were skilled in &quot;looking for nouns&quot; when exposed to a problem to solve.</p><p>Focusing on <code>Behaving</code> level (you don&#x27;t know what I am talking about? Please check <a href="https://talesfrom.dev/blog/modeling-maturity-levels">Modeling Maturity Levels</a>) has its benefits when it comes to modeling.</p><p>Especially, when we compare it to <code>Being</code> level.</p><p>Nouns themselves are not &quot;bad&quot; or &quot;not suitable&quot;, when we think of providing a model to a given problem.</p><p>They &quot;just&quot; need a friend - adjective.</p><p>By using <strong>adjective noun collocation</strong>, we might explore the concepts in their natural habitats, capturing the context.</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">&quot;adjective noun collocation&quot; - definition</div><div class="pb-2 px-3"><div class="break-words"><p>Collocations are a pair or group of words which habitually appear together to convey a whole new meaning. We use adjectives and nouns collocations putting adjectives before nouns.</p></div></div></div><p>What naturally emerges from using this linguistic construct is a transformation of lines into arrows.</p><h3 id="semantic-mapping---static-perspective-on-vocabulary"><a href="#semantic-mapping---static-perspective-on-vocabulary" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Semantic mapping - static perspective on vocabulary</h3><p>There is a &quot;technique&quot; for mapping out all the words and vocabulary - it is called <strong>semantic mapping</strong> or <strong>semantic maps</strong>.</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">&quot;Semantic mapping&quot; - definition</div><div class="pb-2 px-3"><div class="break-words"><p>Semantic mapping is a visual strategy for vocabulary expansion and extension of knowledge by displaying in categories words related to one another.</p></div></div></div><p>Using it in the right context, brings clarity and understanding.</p><p>Various resources use something similar to explore and lay out vocabulary of the domain (for example: see in <a href="https://www.amazon.com/Object-Thinking-Developer-Reference-David/dp/0735619654">Object Thinking</a>).</p><p>We, developers and architects, are pretty familiar with &quot;entity relationship diagram&quot;, when it comes to &quot;modeling&quot; (modeling what?).</p><p>When we apply our knowledge about database tables design and semantic mapping - we might get something that resemble &quot;entity relationship diagram&quot;.</p><p>&quot;Lifeless&quot; structures that &quot;only&quot; capture what is the best way of archiving them so that retrieval and searching will be optimized (here I am generalizing and putting some assumptions, but I hope you bear with the direction of thinking).</p><p>Behaviors, responsibilities, evolution and transformational nature are kept somewhere else (if any).</p><h3 id="concept-mapping---transformational-perspective-on-vocabulary"><a href="#concept-mapping---transformational-perspective-on-vocabulary" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Concept Mapping - transformational perspective on vocabulary</h3><p>As we saw in this little example, there is an informal way of capturing the essence of the language, used by human beings.</p><p>Each of the concepts, we explored, could potentially be a subject of a process.</p><p>With high probability, most of them have &quot;CRUD&quot;-like lifecycle and their evolution does not have any restrictions.</p><p>Looking at the rest of the concepts, from a <code>Becoming</code> perspective, might reveal very interesting properties of the system that we are trying to model.</p><p>Let&#x27;s then focus on this transformational, processing aspects.</p><p>Even when we study &quot;process&quot; word definition, we might get interesting insights:</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">&quot;process&quot; - noun, definition</div><div class="pb-2 px-3"><div class="break-words"><p>a series of actions or steps taken in order to achieve a particular end.</p></div></div></div><p>Sequential in nature, actions driving &quot;a process&quot; to the terminal state. Pretty straightforward.</p><p>But this is a &quot;noun&quot;-based definition, and nouns are bad because they anchor ourselves at the &quot;entity&quot;-thinking, right?</p><p>Let&#x27;s check &quot;verb&quot;-based definition!</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">&quot;process&quot; - verb, definition</div><div class="pb-2 px-3"><div class="break-words"><p>perform a series of mechanical or chemical operations on (something) in order to change or preserve it.</p></div></div></div><p>Again, serial nature, but the end of the sentence sheds some light upon our thinking - &quot;to change or preserve it&quot;.</p><p>If we take our tiny tale and have &quot;transformational&quot; perspective in our head, a &quot;workshop&quot; is being processed in a serial steps and each step &quot;transforms&quot; it, in some way.</p><p>As mentioned before, we are not using &quot;lines&quot; but &quot;arrows&quot; to emphasize this aspect.</p><p>To distinguish such &quot;mapping&quot; from <strong>semantic map</strong> (which, in the scope of this tale, is considered capturing &quot;only&quot; static aspect), we could call it a <strong>concept mapping</strong>.</p><p>Those are just labels and we shouldn&#x27;t cling to them - names can come and go, meaning might remain the same.</p><h3 id="change-change-never-changes"><a href="#change-change-never-changes" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Change, change never changes</h3><p>Imagine that our investor comes and gives flattering comments about precise &quot;entity modeling&quot; by using adjectives, next to nouns.</p><p>They forgot to include one important fact, when it comes to organizing workshops.</p><p>&quot;Sometimes we need to cancel a workshop&quot;, said the investor.</p><p>As we have &quot;various workshops&quot; at our disposal, we can be very precise in asking what does it mean &quot;cancel&quot; and what are the consequences for:</p><ul><li>workshop idea?</li><li>planned workshop?</li><li>published workshop?</li><li>workshop?</li><li>rated workshop?</li></ul><p>After a brief thinking, one can be pretty confident that &quot;cancel&quot; has many meanings and consequences. So not every &quot;cancel&quot; is the same &quot;cancel&quot;.</p><p>When such a fact occurs, it might bring manifold of the effects - depending in which state a workshop currently is.</p><p>We could even say that a given workshop &quot;changes&quot; into another by transitioning from one state to another.</p><p>All this lingo around state, transitions, effects, facts - or if you like - events, can remind ourselves that we are talking about pretty well-established &quot;pattern&quot; of computation.</p><h3 id="from-concept-maps-to-state-machines"><a href="#from-concept-maps-to-state-machines" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>From concept maps to state machines</h3><p>Imagine, based on our investigation, that those states and transitions between them are possible:</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/organizing-workshop-cancelled.png" class="max-h-[40rem]"/></div></div><p>Could you name the &quot;operations&quot; that might happen between any two states?</p><p>I believe that in &quot;entity relationship diagram&quot; it would be a little bit harder.</p><p>Of course, we could argue that there are places and occurences where such a diagram shines.</p><p>No doubt on that.</p><p>But, more we go into the &quot;processing&quot; aspect of our little domain, the more it makes sense to use transformational-oriented modeling techniques.</p><p>It&#x27;s very easy to jump on the &quot;it is easy&quot; wagon and model (or even worse - start implementing, immediately!) solutions to the problems with &quot;simplicity&quot; in mind.</p><p>The worst part of this kind of reasoning is we are misinterpreting &quot;simple&quot; with &quot;naive&quot;.</p><p>With high chance, the most of the problems, we would need to find a solution to, will require CRUD-like model.</p><p>What about the rest?</p><p><a href="https://talesfrom.dev/blog/slow-down">Slow down</a>, don&#x27;t be afraid transitioning to <a href="https://talesfrom.dev/blog/i-dont-know">&quot;I don&#x27;t know&quot;</a>-state (pun intended!) and pay attention to <a href="https://talesfrom.dev/blog/language-of-the-problem">Language of the problem</a>!</p><h3 id="whats-next"><a href="#whats-next" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What&#x27;s next?</h3><p>It might sound trivial and simplistic approach but I find it useful - even when it &quot;just&quot; comes to thinking.</p><p><strong>Concept mapping</strong> might give a new life for using &quot;nouns&quot; when modeling.</p><p>It&#x27;s very common for &quot;business&quot; people too - they got &quot;infected&quot; (by &quot;us&quot; - technical people) with &quot;Status-Driven Thinking&quot; so it might be very interesting exercise to show an alternative.</p><p>Burying the transformational nature of the problems won&#x27;t magically vanish, as essential complexity might involve such a trait.</p><p>And, as mentioned during this tale, it might seem we are inducing a lot of effort and complexity. <a href="https://talesfrom.dev/blog/the-cost-of-modeling">The cost of modeling</a> will still be there.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>The complexity doesn&#x27;t disappear, it gets moved.</p></div></div></div><p>The question isn&#x27;t &quot;if&quot; but &quot;when&quot; and &quot;where&quot;.</p><p>Are you dare to pay, consciously?</p>]]></content:encoded>
    <pubDate>Mon, 15 May 2023 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>programming</category><category>paradigms</category><category>language</category><category>modeling</category><category>model</category><category>trade-offs</category><category>representations</category><category>mental models</category><category>domain-driven design</category><category>visual modeling</category><category>principles</category><category>patterns</category><category>design-thinking</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/rethinking-missingness</guid>
    <title>Rethinking &quot;missingness&quot;</title>
    <link>https://talesfrom.dev/blog/rethinking-missingness</link>
    <description>How can we model absence?</description>
    <content:encoded><![CDATA[<div class="bg-slate-600 rounded-xl "><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Attention!</span></div><div class="pb-2 px-3"><div class="break-words"><p>The code used in this blog post is a toy code which might be missing (pun intended) some aspects.</p>
<p>There are numerous solutions to the problems we will see, so just bear that in mind.</p>
<p>If you find yourself commenting it in your head, it&#x27;s a good sign.</p></div></div></div><h3 id="missingness"><a href="#missingness" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Missingness&quot;</h3><p>Imagine that we need to notify a customer (whatever it actually means). To achieve it, we are loading a notification template, from a place where it can be typically found, so that we can use it as a content for communication:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token keyword">class</span> <span class="token class-name">CustomerNotificationService</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token comment">/* declarations of the references to the collaborators from the constructor */</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token function">CustomerNotificationService</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token class-name">INotifier</span> nofitier<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">INotificationTemplate</span> notificationTemplate<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">ICustomerNotificationDetails</span> customerNotificationDetails<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">ILogger<span class="token punctuation">&lt;</span>CustomerNotificationService<span class="token punctuation">&gt;</span></span> logger
</span><span class="code-line">    <span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        _notifier <span class="token operator">=</span> notifier<span class="token punctuation">;</span>
</span><span class="code-line">        _notificationTemplate <span class="token operator">=</span> notificationTemplate<span class="token punctuation">;</span>
</span><span class="code-line">        _customerNotificationDetails <span class="token operator">=</span> customerNotificationDetails<span class="token punctuation">;</span>
</span><span class="code-line">        _logger <span class="token operator">=</span> logger<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">NotifyCustomer</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> customerId<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> details <span class="token operator">=</span> <span class="token keyword">await</span> _customerNotificationDetails<span class="token punctuation">.</span><span class="token function">GetBy</span><span class="token punctuation">(</span>customerId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> template <span class="token operator">=</span> <span class="token keyword">await</span> _notificationTemplate<span class="token punctuation">.</span><span class="token function">GetBy</span><span class="token punctuation">(</span>customerId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> notification <span class="token operator">=</span> template<span class="token punctuation">.</span><span class="token function">CreateNotificationWith</span><span class="token punctuation">(</span>details<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">await</span> _notifier<span class="token punctuation">.</span><span class="token function">Notify</span><span class="token punctuation">(</span>notification<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        _logger<span class="token punctuation">.</span><span class="token function">Information</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;Notification sent to </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">customerId</span><span class="token punctuation">}</span></span><span class="token string">&quot;</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Of course, such a code isn&#x27;t robust at all, since we know that <code>details</code> and <code>template</code> might be <code>null</code>.</p><p>And of course, it&#x27;s pretty easy to improve the method <code>NotifyCustomer</code> by checking against <code>null</code>s.</p><p>We will focus only on the <code>NotifyCustomer</code> so it will only be showed from now.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">NotifyCustomer</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> customerId<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> details <span class="token operator">=</span> <span class="token keyword">await</span> _customerNotificationDetails<span class="token punctuation">.</span><span class="token function">GetBy</span><span class="token punctuation">(</span>customerId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">if</span><span class="token punctuation">(</span>details <span class="token keyword">is</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        _logger<span class="token punctuation">.</span><span class="token function">Error</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;Notification not sent to </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">customerId</span><span class="token punctuation">}</span></span><span class="token string">. Missing details.&quot;</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        
</span><span class="code-line">        <span class="token keyword">return</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> template <span class="token operator">=</span> <span class="token keyword">await</span> _notificationTemplate<span class="token punctuation">.</span><span class="token function">GetBy</span><span class="token punctuation">(</span>customerId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">if</span><span class="token punctuation">(</span>template <span class="token keyword">is</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        _logger<span class="token punctuation">.</span><span class="token function">Error</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;Notification not sent to </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">customerId</span><span class="token punctuation">}</span></span><span class="token string">. Missing template.&quot;</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        
</span><span class="code-line">        <span class="token keyword">return</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> notification <span class="token operator">=</span> template<span class="token punctuation">.</span><span class="token function">CreateNotificationWith</span><span class="token punctuation">(</span>details<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">await</span> _notifier<span class="token punctuation">.</span><span class="token function">Notify</span><span class="token punctuation">(</span>notification<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    _logger<span class="token punctuation">.</span><span class="token function">Information</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;Notification sent to </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">customerId</span><span class="token punctuation">}</span></span><span class="token string">&quot;</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Now, we are safe. The operation we implemented is robust enough, in case of any exceptional situations.</p><p>The &quot;missingness&quot; of those pieces sounds like a probable fact to happen in any real-life scenario, so it might be not considered as an &quot;exception&quot;, but let&#x27;s move along.</p><p>Nevertheless, it looks pretty normal, isn&#x27;t it?</p><h3 id="what-does-it-mean-its-not-there"><a href="#what-does-it-mean-its-not-there" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What does it mean &quot;it&#x27;s not there&quot;?</h3><p>If we stop for a while and think - why are the details missing? Why notification template is not there?</p><p>This information might sound like a lower level, and we shouldn&#x27;t be bothered by it. With high chance, the collaborators, in the form of <code>INotifier</code> and <code>INotificationTemplate</code>, will handle noting <strong>why</strong> they are missing.</p><p>But as a consumer of their services - what do we still see? A <code>null</code>.</p><p>We can say that they are missing and do something with that fact.</p><p>So for sure, <code>null</code> means we lack customer notification details.</p><p>Also, <code>null</code> expresses that we don&#x27;t have notification template.</p><p>So somehow this four-letter beast magically communicates the intention of &quot;missingness&quot;.</p><p>In various programming languages, it is a first-class citizen that encodes such intention.</p><p>Can we do better?</p><p>Maybe.</p><h3 id="maybe-or-null"><a href="#maybe-or-null" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Maybe or null</h3><p>To be more verbose and compiler-safer, we could introduce a well-known &quot;pattern&quot; - <code>Maybe</code>.</p><p>Imagine that we installed one of the packages, providing such &quot;container&quot; (for example <a href="https://github.com/vkhorikov/CSharpFunctionalExtensions">CSharpFunctionalExtensions</a>).</p><p>To utilize it, we needed to teach upstream collaborators, <code>INotificationTemplate</code> and <code>ICustomerNotificationDetails</code>, to use <code>Maybe&lt;T&gt;</code> in their contracts.</p><p>This is how the code looks after doing the changes.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">NotifyCustomer</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> customerId<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> details <span class="token operator">=</span> <span class="token keyword">await</span> _customerNotificationDetails<span class="token punctuation">.</span><span class="token function">GetBy</span><span class="token punctuation">(</span>customerId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">if</span><span class="token punctuation">(</span>details<span class="token punctuation">.</span>HasNoValue<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        _logger<span class="token punctuation">.</span><span class="token function">Error</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;Notification not sent to </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">customerId</span><span class="token punctuation">}</span></span><span class="token string">. Missing details.&quot;</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        
</span><span class="code-line">        <span class="token keyword">return</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> template <span class="token operator">=</span> <span class="token keyword">await</span> _notificationTemplate<span class="token punctuation">.</span><span class="token function">GetBy</span><span class="token punctuation">(</span>customerId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">if</span><span class="token punctuation">(</span>template<span class="token punctuation">.</span>HasNoValue<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        _logger<span class="token punctuation">.</span><span class="token function">Error</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;Notification not sent to </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">customerId</span><span class="token punctuation">}</span></span><span class="token string">. Missing template.&quot;</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        
</span><span class="code-line">        <span class="token keyword">return</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> notification <span class="token operator">=</span> template<span class="token punctuation">.</span>Value<span class="token punctuation">.</span><span class="token function">CreateNotificationWith</span><span class="token punctuation">(</span>details<span class="token punctuation">.</span>Value<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">await</span> _notifier<span class="token punctuation">.</span><span class="token function">Notify</span><span class="token punctuation">(</span>notification<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    _logger<span class="token punctuation">.</span><span class="token function">Information</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;Notification sent to </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">customerId</span><span class="token punctuation">}</span></span><span class="token string">&quot;</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Now, at least, our service providers do not deceive us with their contract of what they give.</p><p>That&#x27;s a nice improvement.</p><p>Compiler effectively prevents us from using the underlying <code>details</code> and <code>template</code>, in case of their &quot;missingness&quot; status.</p><p>However, we altered the language we use - we now are talking about &quot;value&quot;. Code got a bit cluttered with <code>HasNoValue</code> and <code>Value</code>.</p><p>Our domain experts do not know what does <code>HasNoValue</code> mean, but at least they get assured by us it&#x27;s for having something like &quot;safety&quot;.</p><h3 id="business-business-always-changes"><a href="#business-business-always-changes" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Business, business always changes</h3><p>We are creating impactful software so our business evolves too.</p><p>Experts pointed out that our customers are a bit angry because they weren&#x27;t notified at the right moment.</p><p>To counteract this fact, our experts introduced a new concept - a default template. It will be always present. Its absence means an exceptional situation.</p><p>The rule is simple: in case of incomplete customer details, we need to use a default template.</p><p>Ha! That&#x27;s a trivial change.</p><p>A <code>boolean</code> flag would do the job.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">NotifyCustomer</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> customerId<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> details <span class="token operator">=</span> <span class="token keyword">await</span> _customerNotificationDetails<span class="token punctuation">.</span><span class="token function">GetBy</span><span class="token punctuation">(</span>customerId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">if</span><span class="token punctuation">(</span>details<span class="token punctuation">.</span>HasNoValue<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        _logger<span class="token punctuation">.</span><span class="token function">Error</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;Notification not sent to </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">customerId</span><span class="token punctuation">}</span></span><span class="token string">. Missing details.&quot;</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        
</span><span class="code-line">        <span class="token keyword">return</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> template <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">GetTemplateBy</span><span class="token punctuation">(</span>details<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">if</span><span class="token punctuation">(</span>template<span class="token punctuation">.</span>HasNoValue<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        _logger<span class="token punctuation">.</span><span class="token function">Information</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;Notification not sent to </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">customerId</span><span class="token punctuation">}</span></span><span class="token string">. Missing template.&quot;</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">return</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> notification <span class="token operator">=</span> template<span class="token punctuation">.</span>Value<span class="token punctuation">.</span><span class="token function">CreateNotificationWith</span><span class="token punctuation">(</span>details<span class="token punctuation">.</span>Value<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">await</span> _notifier<span class="token punctuation">.</span><span class="token function">Notify</span><span class="token punctuation">(</span>notification<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    _logger<span class="token punctuation">.</span><span class="token function">Information</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;Notification sent to </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">customerId</span><span class="token punctuation">}</span></span><span class="token string">&quot;</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">private</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>Maybe<span class="token punctuation">&lt;</span>INotificationTemplate<span class="token punctuation">&gt;</span><span class="token punctuation">&gt;</span></span> <span class="token function">GetTemplateBy</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token class-name">ICustomerNotificationDetails</span> details
</span><span class="code-line">    <span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">if</span><span class="token punctuation">(</span>details<span class="token punctuation">.</span>Incomplete<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            _logger<span class="token punctuation">.</span><span class="token function">Information</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;Incomplete customer template details for </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">customerId</span><span class="token punctuation">}</span></span><span class="token string">. Using default template.&quot;</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token class-name"><span class="token keyword">var</span></span> defaultTemplate <span class="token operator">=</span> <span class="token keyword">await</span> _notificationTemplate<span class="token punctuation">.</span><span class="token function">GetDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            
</span><span class="code-line">            <span class="token keyword">return</span> Maybe<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Some</span><span class="token class-name generic"><span class="token punctuation">&lt;</span>INotificationTemplate<span class="token punctuation">&gt;</span></span></span><span class="token punctuation">(</span>defaultTemplate<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token class-name"><span class="token keyword">var</span></span> template <span class="token operator">=</span> <span class="token keyword">await</span> _notificationTemplate<span class="token punctuation">.</span><span class="token function">GetBy</span><span class="token punctuation">(</span>customerId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token keyword">if</span><span class="token punctuation">(</span>template<span class="token punctuation">.</span>HasNoValue<span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token punctuation">{</span>
</span><span class="code-line">                _logger<span class="token punctuation">.</span><span class="token function">Information</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;Missing template for </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">customerId</span><span class="token punctuation">}</span></span><span class="token string">.&quot;</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">            <span class="token keyword">return</span> template<span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Commit. Push. Deploy. Profit.</p><p>Business is happy with the value delivered.</p><p>We applied our experience to introduce that change!</p><p>What about our flag? <code>Incomplete</code> deals with a different kind of &quot;missingness&quot;.</p><p>We have two ways of modeling &quot;missingness&quot;: we model all missing details with <code>Maybe</code> and some missing details with <code>Incomplete</code> flag.</p><h3 id="technically-correct-but-incorrect-technically"><a href="#technically-correct-but-incorrect-technically" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Technically correct, but incorrect, technically.</h3><p>As the model ought to communicate in the clear way, we could ask ourselves a question - based on the language, what is possible?</p><p>What is the language, available in the current context?</p><p>Are we really using <a href="https://talesfrom.dev/blog/language-of-the-problem">language of the problem</a>?</p><p><code>Incomplete</code> is pretty verbose, although the type, in compile-time, remains the same - <code>CustomerNotificationDetails</code>.</p><p><code>Maybe</code> informs us about &quot;missingness&quot; - for professionals like us, it makes sense, isn&#x27;t it?</p><p>It still gives the value we are looking for, but language-wise, is <code>Maybe</code> that verbose?</p><p>When in doubt, collaborate!</p><p>Imagine that we went to our experts and they were clear with their language: details might be available, incomplete or missing.</p><p>Clearly, their (mental) model includes such scenarios.</p><p>Our model, living in the code, covers them, but in a kind of convoluted fashion.</p><p>We can&#x27;t measure it like we measure time or voltage, but the language, used in the code, isn&#x27;t completely domain-centric.</p><p>What else could we do?</p><h3 id="language-driven-model"><a href="#language-driven-model" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Language-Driven Model</h3><p>Let&#x27;s say, we are wearing the disciplined software monk mask and we are obliged to model the language.</p><p>How the <code>NotifyCustomer</code> method could look like?</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">NotifyCustomer</span><span class="token punctuation">(</span><span class="token class-name">Guid</span> customerId<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> details <span class="token operator">=</span> <span class="token keyword">await</span> _customerNotificationDetails<span class="token punctuation">.</span><span class="token function">GetBy</span><span class="token punctuation">(</span>customerId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    details<span class="token punctuation">.</span><span class="token function">Match</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token punctuation named-parameter">missing</span><span class="token punctuation">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
</span><span class="code-line">            _logger<span class="token punctuation">.</span><span class="token function">Error</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;Notification not sent to </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">customerId</span><span class="token punctuation">}</span></span><span class="token string">. Missing details.&quot;</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>    
</span><span class="code-line">        <span class="token punctuation">}</span><span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token punctuation named-parameter">incomplete</span><span class="token punctuation">:</span> <span class="token keyword">async</span> <span class="token punctuation">(</span>incompleteDetails<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
</span><span class="code-line">            _logger<span class="token punctuation">.</span><span class="token function">Information</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;Incomplete customer template details for </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">customerId</span><span class="token punctuation">}</span></span><span class="token string">. Using default template.&quot;</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token class-name"><span class="token keyword">var</span></span> defaultTemplate <span class="token operator">=</span> <span class="token keyword">await</span> _notificationTemplate<span class="token punctuation">.</span><span class="token function">GetDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token class-name"><span class="token keyword">var</span></span> notification <span class="token operator">=</span> defaultTemplate<span class="token punctuation">.</span><span class="token function">CreateNotificationWith</span><span class="token punctuation">(</span>incompleteDetails<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token keyword">await</span> _notifier<span class="token punctuation">.</span><span class="token function">Notify</span><span class="token punctuation">(</span>notification<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            _logger<span class="token punctuation">.</span><span class="token function">Information</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;Notification sent to </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">customerId</span><span class="token punctuation">}</span></span><span class="token string">&quot;</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span><span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token punctuation named-parameter">available</span><span class="token punctuation">:</span> <span class="token keyword">async</span> <span class="token punctuation">(</span>details<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token class-name"><span class="token keyword">var</span></span> template <span class="token operator">=</span> <span class="token keyword">await</span> _notificationTemplate<span class="token punctuation">.</span><span class="token function">GetBy</span><span class="token punctuation">(</span>customerId<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token keyword">if</span><span class="token punctuation">(</span>template<span class="token punctuation">.</span>HasNoValue<span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token punctuation">{</span>
</span><span class="code-line">                _logger<span class="token punctuation">.</span><span class="token function">Information</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;Missing template for </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">customerId</span><span class="token punctuation">}</span></span><span class="token string">.&quot;</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
</span><span class="code-line">                <span class="token class-name"><span class="token keyword">var</span></span> notification <span class="token operator">=</span> template<span class="token punctuation">.</span>Value<span class="token punctuation">.</span><span class="token function">CreateNotificationWith</span><span class="token punctuation">(</span>details<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">                <span class="token keyword">await</span> _notifier<span class="token punctuation">.</span><span class="token function">Notify</span><span class="token punctuation">(</span>notification<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">                _logger<span class="token punctuation">.</span><span class="token function">Information</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$&quot;Notification sent to </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">customerId</span><span class="token punctuation">}</span></span><span class="token string">&quot;</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token punctuation">}</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre></div></div><p>It looks differently, that&#x27;s for sure. We decided to not use <code>Maybe</code> for modeling &quot;missingness&quot; of customer notification details, but rather model it explicitly.</p><p>Also, we captured the language used by our experts. Each of the cases is separately handled, so any time someone from domain personnel mentions &quot;missing notification details&quot;, we know where to look at.</p><p>Some accidental complexity, related to the technical solution we provided, is inevitable, being hidden behind <code>Match</code> method.</p><p>This might look intimidating, but we emphasized the essential matter - how it is communicated between people.</p><h3 id="the-code-now-isnt-idiomatic"><a href="#the-code-now-isnt-idiomatic" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The code now isn&#x27;t idiomatic</h3><p>It&#x27;s highly dependable, but the last iteration of code might be considered as complex/non-idiomatic/smart.</p><p>Also, it&#x27;s pretty known fact that the language we use, limits our cognition capabilities.</p><p>This phenomenon applies to any language - spoken or programming.</p><p>When the language we are currently using (or thinking with, to be precise), doesn&#x27;t provide a way of expressively emphasizing the intentions, it might be considered as unnecessary cost (what am I talking about? Check <a href="https://talesfrom.dev/blog/the-cost-of-modeling">The cost of modeling</a>).</p><p>Of course, this doesn&#x27;t mean that the essential complexity will disappear.</p><p>We can try to deceive ourselves by saying that we are complicating &quot;simple things&quot; (why do we consider them as &quot;simple&quot;, really?)</p><p>Even if the language treats <code>null</code> as its first citizen for modeling &quot;missingness&quot; (various level of it too), this doesn&#x27;t mean we shouldn&#x27;t look for other means for expressing it.</p><p><code>Maybe&lt;T&gt;</code> might shortsightedly look as the best and the final solution but this varies as the context changes.</p><p>Initially, it maybe won&#x27;t bring the havoc, but as soon as we don&#x27;t rethink our way of modeling, things might get implicit and intentions-hiding.</p><h3 id="either-you-pay-now-or-later"><a href="#either-you-pay-now-or-later" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Either you &quot;pay&quot; now or later</h3><p>I like the saying which states that the complexity doesn&#x27;t disappear, it gets moved.</p><p>In the past, I thought it says only about the place/the space, but this also includes time.</p><p>So complexity can move in time too.</p><p>One must &quot;pay&quot; the modeling cost and re-evaluate the model across the time.</p><p>Everything in this beautiful world is a target of entropy, and so do models.</p><p>It might be easier to put a flag on it or use <code>Maybe</code>, but as long as we don&#x27;t take modeling seriously, we&#x27;re putting &quot;payment&quot; off in time.</p><p>In our little tale, we saw various &quot;techniques&quot; for working with &quot;missingness&quot;:</p><ul><li>using <code>null</code></li><li>using <code>Maybe</code></li><li>using &quot;discriminated union&quot;-like construct</li></ul><p>Of course, depending on the context, they both gave different set of traits and incurred various cost-like qualities, that might be considered as &quot;trade-offs&quot;.</p><p>Additionally, we could, hypothetically, use <code>enum</code> to express what we achieved with <code>Match</code>, but will we be honest with the problem we are trying to solve?</p><h3 id="modeling-levels"><a href="#modeling-levels" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Modeling levels</h3><p>One could say we were modeling the solution to the problem on different levels. (levels? I wrote something about similar topic in <a href="https://talesfrom.dev/blog/modeling-maturity-levels">Modeling Maturity Levels</a>)</p><p>Inherently, problems we are facing might seem dull, superficial and simple. This is a matter of time when our solutions will get challenged by the world.</p><p>&quot;Shorter&quot; code might look simple and effective and &quot;longer&quot; code might seem as &quot;complicated&quot;, but when we use readability as our driver, it might be quite opposite.</p><p>There is the value in explicit modeling and we might not be used to that.</p><p>In our tiny tale, we explored three alternatives. I don&#x27;t know what you think, dear Reader, but I like options.</p><p>As an engineer, I want to have multiple possibilities at my disposal so that I am able to consciously make a decision. Different languages allow for different styles of expressiveness, that&#x27;s why it&#x27;s worth taking the effort of learning a language from a different paradigm.</p><p>Unlearning is a bliss.</p>]]></content:encoded>
    <pubDate>Sun, 23 Apr 2023 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>programming</category><category>paradigms</category><category>language</category><category>modeling</category><category>model</category><category>trade-offs</category><category>representations</category><category>mental models</category><category>discipline</category><category>SOLID</category><category>GRASP</category><category>principles</category><category>patterns</category><category>design-thinking</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/modularity-uncertainty-heuristic</guid>
    <title>Modularity Uncertainty Heuristic</title>
    <link>https://talesfrom.dev/blog/modularity-uncertainty-heuristic</link>
    <description>Can broken modularity be easily observed and easily fixed at the same time?</description>
    <content:encoded><![CDATA[<h3 id="the-organization"><a href="#the-organization" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The organization</h3><p>Imagine there&#x27;s a small (really, really small) organization that give consultancy services related to accounting and warehousing.</p><p>Accounting advisory is a bit special because it uses simulation methods to increase the value from the service.</p><p>Three-Man-Army needed to organize themselves to work toward same goal - that&#x27;s what organizations do, right? (what am I talking about? If you&#x27;re curious, please check <a href="https://talesfrom.dev/blog/organization-driven-design">&quot;Organization-Driven Design&quot;</a>)</p><p>Let&#x27;s introduce the crew!</p><p><span class=" text-[#1864ab]">Tom</span>, The Accounting Expert - doing the majority of the services.</p><p><span class=" text-[#2b8a3e]">Theo</span>, The Simulation Expert - bravely assisting <span class=" text-[#1864ab]">Tom</span>.</p><p>And finally <span class=" text-[#e7779e]">Tony</span>, The Warehousing Expert - quite independent.</p><p>As we now know our heroes, let&#x27;s move on!</p><h3 id="team-topology"><a href="#team-topology" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Team topology</h3><p><span class="mr-2 text-[#e7779e]">Tony</span>does his work separately, so he doesn&#x27;t need anything from either <span class="mr-2 text-[#1864ab]">Tom</span>or <span class=" text-[#2b8a3e]">Theo</span>.</p><p>Things look a bit differently for other two.</p><p><span class="mr-2 text-[#1864ab]">Tom</span>and <span class="mr-2 text-[#2b8a3e]">Theo</span>are closely collaborating. Any time <span class="mr-2 text-[#1864ab]">Tom</span>has any work related to accounting consultancy, he needs to ask <span class="mr-2 text-[#2b8a3e]">Theo</span>to provide him some simulations.</p><p><span class="mr-2 text-[#2b8a3e]">Theo</span>is actually very independent - he doesn&#x27;t require anything from either <span class="mr-2 text-[#1864ab]">Tom</span>or <span class=" text-[#e7779e]">Tony</span>.</p><p>One could ask - is everything fine?</p><h3 id="the-office"><a href="#the-office" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The office</h3><p>Our little team works together so they need to rent some office space.</p><p>Let&#x27;s imagine that the market is a bit turbulent and they are changing their office location multiple times.</p><p>We&#x27;re start with their first setup - a single room.</p><div class="flex justify-center items-center flex-col"><div><img class="max-h-[35rem]" src="https://talesfrom.dev/static/images/single-room.png"/></div><div>Little organization in a little room.</div></div><p>Typically, people are talking to each other to do their jobs, aren&#x27;t they? (hopefully!)</p><p>Pushing our imagination further, let&#x27;s simulate that <span class="mr-2 text-[#1864ab]">Tom</span>and <span class="mr-2 text-[#e7779e]">Tony</span>had a little discussion, during their lunch break (<span class="mr-2 text-[#2b8a3e]">Theo</span> wasn&#x27;t around).</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><span><span class="italic text-[#e7779e]">Tony</span>: I see you&#x27;re closely working with <span class="mr-2 text-[#2b8a3e]">Theo</span>- cool to see that.</span></span><span class="text-white"> </span><span class="text-white"><span><span class="italic text-[#1864ab]">Tom</span>: Yeah, that&#x27;s true. Each time I need to assist to our customer, both me and <span class="mr-2 text-[#2b8a3e]">Theo</span>need to talk.</span></span><span class="text-white"> </span><span class="text-white"><span><span class="italic text-[#e7779e]">Tony</span>: You mean - always?</span></span><span class="text-white"> </span><span class="text-white"><span><span class="italic text-[#1864ab]">Tom</span>: Yes.</span></span><span class="text-white"> </span><span class="text-white"><span><span class="italic text-[#e7779e]">Tony</span>: I don&#x27;t think those simulations are that hard - he&#x27;s using some programs - couldn&#x27;t you use the same?</span></span><span class="text-white"> </span><span class="text-white"><span><span class="italic text-[#1864ab]">Tom</span>: Maybe, but it&#x27;s not a problem at all. We are sitting in the same room, there are a few meters between us.</span></span><span class="text-white"> </span><span class="text-white"><span><span class="italic text-[#e7779e]">Tony</span>: If you say so.</span></span></div><p>Seems like everything is fine, isn&#x27;t it?</p><h3 id="the-new-office"><a href="#the-new-office" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The new office</h3><p>Due to various reasons, guys needed to distribute themselves across the office space.</p><p><span class="mr-2 text-[#1864ab]">Tom</span>and <span class="mr-2 text-[#e7779e]">Tony</span>stayed in the same room, whereas <span class="mr-2 text-[#2b8a3e]">Theo</span>went into another office room - but still in the same office building.</p><p>So now, our little team occupies two rooms.</p><div class="flex justify-center items-center flex-col"><div><img class="max-h-[35rem]" src="https://talesfrom.dev/static/images/two-rooms.png"/></div><div>Little organization in two rooms but in the same building.</div></div><p>As previously, <span class="mr-2 text-[#1864ab]">Tom</span>and <span class="mr-2 text-[#e7779e]">Tony</span>had a little discussion.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><span><span class="italic text-[#e7779e]">Tony</span>: Aren&#x27;t you tired?</span></span><span class="text-white"> </span><span class="text-white"><span><span class="italic text-[#1864ab]">Tom</span>: A bit. Both me and <span class="mr-2 text-[#2b8a3e]">Theo</span>had so many requests from our customers...</span></span><span class="text-white"> </span><span class="text-white"><span><span class="italic text-[#e7779e]">Tony</span>: I am not talking about the amount of work.</span></span><span class="text-white"> </span><span class="text-white"><span><span class="italic text-[#1864ab]">Tom</span>: Then what?</span></span><span class="text-white"> </span><span class="text-white"><span><span class="italic text-[#e7779e]">Tony</span>: Every time you got a call from a customer, you need to walk through the corridor, reach <span class=" text-[#2b8a3e]">Theo</span>&#x27;s room, ask for simulation, wait until he does all the magic and then come back.</span></span><span class="text-white"> </span><span class="text-white"><span><span class="italic text-[#1864ab]">Tom</span>: Ah, I see! It might look a bit strange when I am crossing the office space so many times each day. But you know - at least I have some movement - motion is lotion - haha!</span></span><span class="text-white"> </span><span class="text-white"><span><span class="italic text-[#e7779e]">Tony</span>: So it&#x27;s not a problem for you?</span></span><span class="text-white"> </span><span class="text-white"><span><span class="italic text-[#1864ab]">Tom</span>: Changing surrounding from time to time isn&#x27;t that bad, is it?</span></span></div><p>Guys delivered the value and customers were happy, although they sometimes gots feedback about slower response times.</p><p><span class="mr-2 text-[#1864ab]">Tom</span>promised that things get better when they properly settle in their new office, as they changed places.</p><p>Opinions like &quot;It isn&#x27;t that bad&quot; made <span class="mr-2 text-[#1864ab]">Tom</span>pretty confident.</p><h3 id="remote-work"><a href="#remote-work" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Remote work</h3><p>Again, things got a bit complicated. Big Corp&#x27;n&#x27;Slash came and offered higher price than our little heroes.</p><p>As they knew each other quite well, they decided to do the split - <span class="mr-2 text-[#2b8a3e]">Theo</span>was the one who said he could move to another office building</p><p>He was pretty independent, he didn&#x27;t need anything from the rest of the crew.</p><p>A great division happened.</p><div class="flex justify-center items-center flex-col"><div><img class="max-h-[35rem]" src="https://talesfrom.dev/static/images/two-offices.png"/></div><div>Little organization distributed across two buildings.</div></div><p>There was a physical distance between buildings, are they were located in the different parts of the city.</p><p>&quot;We are living in the internet era, no worries&quot;, <span class="mr-2 text-[#2b8a3e]">Theo</span>said.</p><p>Yet again, there was a tiny discussion between <span class="mr-2 text-[#1864ab]">Tom</span>and <span class=" text-[#e7779e]">Tony</span>.</p><div class="flex"><div class="cursor-pointer border-2 border-b-0 border-gray-50 w-48 text-center text-white">Discussion</div></div><div class="flex flex-col border-2 border-gray-300 p-2"><span class="text-white"><span><span class="italic text-[#e7779e]">Tony</span>: How is your collaboration now, when <span class="mr-2 text-[#2b8a3e]">Theo</span>is far than couple of meters?</span></span><span class="text-white"> </span><span class="text-white"><span><span class="italic text-[#1864ab]">Tom</span>: It isn&#x27;t thaaat bad. We are able to call each other via phone.</span></span><span class="text-white"> </span><span class="text-white"><span><span class="italic text-[#e7779e]">Tony</span>: Wait, how does he transfer the simulations?</span></span><span class="text-white"> </span><span class="text-white"><span><span class="italic text-[#1864ab]">Tom</span>: It depends - we try various ways - sometimes via email, sometimes he slowly gives me the numbers.</span></span><span class="text-white"> </span><span class="text-white"><span><span class="italic text-[#e7779e]">Tony</span>: You must be kidding, right? Honestly, doest it work?</span></span><span class="text-white"> </span><span class="text-white"><span><span class="italic text-[#1864ab]">Tom</span>: Actually...We&#x27;re getting more and more complains from the customers.</span></span><span class="text-white"> </span><span class="text-white"><span><span class="italic text-[#e7779e]">Tony</span>: Why?</span></span><span class="text-white"> </span><span class="text-white"><span><span class="italic text-[#1864ab]">Tom</span>: I thought it will be faster to call <span class="mr-2 text-[#2b8a3e]">Theo</span>than to walk to his room - like we had in the previous office. Sometimes he doesn&#x27;t pick up the phone, he&#x27;s doing something else. Also, he has really shitty internet connection there.</span></span><span class="text-white"> </span><span class="text-white"><span><span class="italic text-[#e7779e]">Tony</span>: Why aren&#x27;t you doing simulations by your own?</span></span><span class="text-white"> </span><span class="text-white"><span><span class="italic text-[#1864ab]">Tom</span>: You know <span class=" text-[#2b8a3e]">Theo</span>, he&#x27;s a good guy. Why should I take his responsibility?</span></span></div><p>Well, things are much more serious now. <span class="mr-2 text-[#1864ab]">Tom</span>is flooded with really not the best feedback about their services.</p><p>What previously took 3 minutes, now might take 10 minutes. And what&#x27;s worse - sometimes he can&#x27;t answer to the customer&#x27;s request.</p><p><span class="mr-2 text-[#2b8a3e]">Theo</span>seems unavailable. Probably, due to the internet connection issues.</p><p>So apparently their delivered value is diminishing. Why?</p><h3 id="knowledge-needs-and-collaboration"><a href="#knowledge-needs-and-collaboration" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Knowledge, needs and collaboration</h3><p>What the hell just happened? (you asked this question, did you?)</p><p>We saw the same topology of people, having their own duties and responsibilities, in three different scenarios.</p><p>There were interactions, communication and knowledge needed to deliver their services.</p><p>But something started happening when both <span class="mr-2 text-[#1864ab]">Tom</span>and <span class="mr-2 text-[#2b8a3e]">Theo</span>were getting physically separated.</p><p>Greater the distance, harder it was to deliver the value by their joint effort.</p><p>Closer the distance, harder it was to see &quot;the potential bottleneck&quot;.</p><p>Why?</p><h3 id="heisenbergs-uncertainty-principle"><a href="#heisenbergs-uncertainty-principle" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Heisenberg&#x27;s uncertainty principle?</h3><p>Let&#x27;s change a topic, for a while.</p><p>Have you heared about Werner Heisenberg? He formulated a very well-known principle that states:</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">Werner Heisenberg&#x27;s princinple</div><div class="pb-2 px-3"><div class="break-words"><p>Position and momentum of an electron cannot be determined simultaneously with absolute accuracy.</p></div></div></div><p>It can be <a href="https://en.wikipedia.org/wiki/Uncertainty_principle">expressed mathematically</a> as follows:</p><div class="math math-display"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi><mrow><mi mathvariant="bold">Δ</mi><mi mathvariant="bold-italic">x</mi><mi mathvariant="bold">Δ</mi><mi mathvariant="bold-italic">p</mi><mo>≥</mo><mi mathvariant="bold-italic">h</mi><mi mathvariant="bold">/</mi><mn mathvariant="bold">4</mn><mi mathvariant="bold-italic">π</mi></mrow></mi></mrow><annotation encoding="application/x-tex">\boldsymbol{\Delta x \Delta p \ge h/4 \pi}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-.25em"></span><span class="mord"><span class="mord"><span class="mord mathbf">Δ</span><span class="mord boldsymbol">x</span><span class="mord mathbf">Δ</span><span class="mord boldsymbol">p</span><span class="mspace" style="margin-right:.2778em"></span><span class="mathbf mrel">≥</span><span class="mspace" style="margin-right:.2778em"></span><span class="mord boldsymbol">h</span><span class="mord mathbf">/4</span><span class="mord boldsymbol" style="margin-right:.03704em">π</span></span></span></span></span></span></span></div><p>Equations are daunting (are they?), but what might it mean?</p><p>From the helicopter view it might mean one thing - a trade-off.</p><p>You cannot get two things at the same time - &quot;pick your own poison&quot;, one could say.</p><p>Either you get this or that. No free lunch.</p><p>Why am I bringing Mr. Heisenberg and his novel observation?</p><h3 id="modularity"><a href="#modularity" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Modularity?</h3><p>Our systems are not throwing modularization exception or they don&#x27;t produce compile-time modularization errors.</p><p>That&#x27;s a trait, a characteristic, we can experience directly (or indirectly).</p><p>It is well-known fact (not my invention) that systems are subjects of an unspoken ying-yang of software engineering: coupling and cohesion (ying-yang? I am giving an explanation in <a href="https://talesfrom.dev/blog/software-engineering-for-busy-parents">Software Engineering for busy parents</a>).</p><p>Low coupling and high cohesion looks like a holy grail of modularity heaven.</p><p>But how to define them? You probably know that I like definitions and semantics. Also, I don&#x27;t want to invent any sophisticated explanation.</p><p>I also like metaphores and analogies, so the best would be to use a metaphor.</p><p>As our little tale is about people, organization and effective communication - let&#x27;s use communication as a mean for describing them.</p><h3 id="talk-your-collaborators"><a href="#talk-your-collaborators" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Talk your collaborators</h3><p><span class="mr-2 text-[#1864ab]">Tom</span>requires knowledge from <span class="mr-2 text-[#2b8a3e]">Theo</span>and in order to do this job, he needs to talk to <span class=" text-[#2b8a3e]">Theo</span>.</p><p>We could say that in order to deliver the value, <span class="mr-2 text-[#1864ab]">Tom</span>depends on <span class=" text-[#2b8a3e]">Theo</span>.</p><p>But <span class="mr-2 text-[#e7779e]">Tony</span>doesn&#x27;t need anything from either <span class="mr-2 text-[#1864ab]">Tom</span>or <span class=" text-[#2b8a3e]">Theo</span>.</p><p>Then, a necessity of communication between peers can be expressed through coupling.</p><p>Shouldn&#x27;t we aim at &quot;loose coupling&quot;?</p><p>But what about cohesion?</p><h3 id="be-close-to-your-friends"><a href="#be-close-to-your-friends" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Be close to your friends</h3><p>We already noticed that <span class="mr-2 text-[#1864ab]">Tom</span>depends on <span class=" text-[#2b8a3e]">Theo</span>. They need to have a chat to satisfy their service and fulfill the contract with the customer.</p><p>As they need to talk very often, it makes sense to keep themselves close to each other.</p><p>What would happen when <span class="mr-2 text-[#2b8a3e]">Theo</span>would change format of his simulations, still being in the same room?</p><p>He would probably just mention that to <span class="mr-2 text-[#1864ab]">Tom</span>and they will adapt quite quickly.</p><p>But when they would sit in different rooms? Different buildings?</p><p>They would need to have a Zoom or Teams call, exchange much more words and sounds to eventually agree on the changes.</p><p>Keeping teammates and collaborators together can be expressed through cohesion.</p><h3 id="responsibilities"><a href="#responsibilities" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Responsibilities?</h3><p>In our little tale, high coupling between <span class="mr-2 text-[#1864ab]">Tom</span>and <span class="mr-2 text-[#2b8a3e]">Theo</span>wasn&#x27;t visible and wasn&#x27;t problematic as we &quot;increased&quot; the distance between them.</p><p>In other words, as we decreased the cohesion of the system, we made coupling much more visible (and painful).</p><p>By decreasing cohesion, we made fixing the problem with coupling much harder.</p><p>It would be the best to keep highly dependent collaborators close to each other.</p><p>I can hear you (was it you?) - &quot;but what if we can&#x27;t keep them together?&quot;</p><p>Possibly, when we need to separate the highly coupled collaborators, would it be an idea to reassign the responsibilities?</p><p>Could <span class="mr-2 text-[#1864ab]">Tom</span>learn how to run simulations, when <span class="mr-2 text-[#2b8a3e]">Theo</span>was far away?</p><h3 id="modularity-uncertainty-heuristic"><a href="#modularity-uncertainty-heuristic" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Modularity Uncertainty Heuristic</h3><p>It might seem difficult to observe high coupling when collaborators are close to each other - but when we notice it, it&#x27;s quite easy to &quot;fix&quot; the problem of responsibility reassignment.</p><p>On the other hand, when coupled collaborators are far from each other, it&#x27;s quite easy to observe this high coupling - but it&#x27;s difficult to reassign the responsibilities.</p><p>It has similar nature as Heisenberg&#x27;s Uncertainty Principle has - duality of mutually exclusive actions.</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">Modularity Uncertainty Heuristic</div><div class="pb-2 px-3"><div class="break-words"><p>(Re)Assigning responsibilities and noticing the high coupling in a system cannot be applied simultaneously with absolute ease</p></div></div></div><p>In other words, it&#x27;s challenging to change responsibilities when coupled collaborators are distributed throughout the code or throughout services - but it&#x27;s quite easy to notice it.</p><p>Contradictory, it&#x27;s challanging to observe high coupling between collaborators when they are close in the code or inside of a service - but it&#x27;s quite easy to change responsibilties.</p><p>What does it mean to us?</p><p>Don&#x27;t be hasty with distributing the responsibilities - <a href="https://talesfrom.dev/blog/slow-down">Slow down</a>, observe which collaborators are affected by the changes - when things settle, consider separation.</p><p>&quot;But what does it mean, <strong>practically</strong>?&quot;, you might wonder.</p><p>It&#x27;s quite popular in the .NET world to keep each related classes, interfaces, enums in separate files. This means low cohesion.</p><p>If a change in each subpart requires touching other subparts - it starts being a bit thorny. What if they are very distributed across codebase?</p><p>Keeping controllers, models, services, abstractions, repositories, dtos together, by their kind or technical functionality - this might get pretty painful.</p><p>A remedy would be - start small - everything in a single file. <a href="https://talesfrom.dev/blog/slow-down">Slow down</a>. Let the organization thrive and grow. When it&#x27;s too much, distribute the responsibilities. (what am I talking about? Please check <a href="https://talesfrom.dev/blog/microoffices-vs-officeolith">Microoffices&quot; vs &quot;Officeolith&quot;</a>)</p><p>Coupling and cohesion aren&#x27;t only the qualities of the code - they are qualities of systems. As we orgnize our code, code organization also forms a system. Think about that.</p><h3 id="what-now"><a href="#what-now" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What now?</h3><p>I command you to learn by heart the Modularity Uncertainty Heuristic. Tomorrow you have an exam.</p><p>Exaggerating, like always.</p><p>How it can help us in our daily job?</p><p>Before deciding to &quot;reuse&quot; something, wait, sense and experience to justify this common responsiblity. Watch the collaborators, check if peers are close to themselves.</p><p>There are statistical tools and approaches like <a href="https://codescene.com/blog/validation-for-behavioral-code-analysis/">Behavioral Code Analysis</a> that might work as a companion to old tools - discipline, analysis and awareness.</p><p>To not leave you, dear Reader, with nothing, here are the brainteasers:</p><ul><li>in the context of the architecture, what does &quot;physical distance&quot; mean?</li><li>in the context of the code, what does &quot;physical distance&quot; mean?</li><li>in the context of the architecture, what does an &quot;office room&quot; mean?</li><li>in the context of the code, what does an &quot;office room&quot; mean?</li><li>is it inherently bad for highly dependent collaborators to be far from each other?</li></ul>]]></content:encoded>
    <pubDate>Thu, 30 Mar 2023 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>programming</category><category>paradigms</category><category>language</category><category>modeling</category><category>model</category><category>trade-offs</category><category>metaphors</category><category>representations</category><category>mental models</category><category>discipline</category><category>modularity</category><category>coupling</category><category>cohesion</category><category>perspectives</category><category>architecture</category><category>design-thinking</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/solution-probleming</guid>
    <title>&quot;Solution-Probleming&quot;</title>
    <link>https://talesfrom.dev/blog/solution-probleming</link>
    <description>What one could learn from a broken coffee grinder?</description>
    <content:encoded><![CDATA[<h3 id="ah-coffee"><a href="#ah-coffee" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Ah, coffee!</h3><p>Typical day - started without any food and the &quot;right&quot; hour was coming to get the first &quot;warm&quot; meal in this day - a coffee with a spoon of coconut oil.</p><p>Nothing gives you that kick of energy.</p><p>I went into the kitchen and immediately navigated to the drawer, where the coffee grinder has its residence.</p><p>&quot;No coffee&quot; was the status written as string on it (What am I talking about? Check <a href="https://talesfrom.dev/blog/modeling-maturity-levels">Modeling Maturity Levels</a> or <a href="https://talesfrom.dev/blog/the-value-of-value-objects">The Value of Value Objects</a>), so I grabbed some beans.</p><p>Damped them in the right place in the appliance, pressed the button and...Nothing happened.</p><p>No &quot;bzzt&quot;, no mechanical squeaking. Almost like a tree, falling in the forest when no one is there.</p><h3 id="argh-no-coffee"><a href="#argh-no-coffee" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Argh, no coffee!</h3><p>After a quick inspection, it turned out that the coffee girinder&#x27;s lid was broken. There should be a small, plastic cam.</p><p>Its main purpose was to work as a mechanical safety breaker that prohibited coffee grinding when the lid wasn&#x27;t properly placed.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/coffee-grinder-lid.png" class="max-h-[30rem]"/></div><div class="italic mx-24">A picture with attached illustrative drawing of a plastic lid with a cam.</div></div><p>Turns out, that this small, plastic cam - wasn&#x27;t there. Or rather - it was there partially, which caused malfunctioning.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/coffee-grinder-broken-cam.png" class="max-h-[30rem]"/></div><div class="italic mx-24">An illustrative drawing of a cam and its function</div></div><p>So now, the mechanical button, working as a contactor, wasn&#x27;t doing its job too.</p><p>My coffee time was about to collapse.</p><h3 id="trust-me-im-an-engineer"><a href="#trust-me-im-an-engineer" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Trust me, I&#x27;m an engineer</h3><p>I couldn&#x27;t leave it with such a status - &quot;BROKEN&quot; - clearly written on the coffee grinder.</p><p>I started tinkering what I could to do solve this problem. I investigated the damaged cam and soon after that I found a missing piece of it.</p><p>&quot;Ok, how can I connect it to entire lid?&quot; - were the first thoughts of mine. Few seconds of happiness were destroyed after I noticed glueing isn&#x27;t an option.</p><p>&quot;It will soon be broken again&quot; - was my observation.</p><p>&quot;Is there any other option I can use to link it back to the lid?&quot;, I started exploring the solution space for my &quot;disconnection&quot; problem.</p><p>I got an idea - I could solder it back to the lid. I saw the pictures of victory, showing off with my soldering skills that can be applied to a plastic lid and a cam.</p><p>Immediately after that thought, I saw all the problems I could possibly have - going to the basement, finding the soldering iron kit, trying to solder it, etc.</p><p>Complexity almost creeped in!</p><p>&quot;So maybe a lighter instead?&quot;, another thought appeared.</p><p>I didn&#x27;t let the termal solution go. I felt how badly I clinged to it.</p><h3 id="trust-me-i-am-a-problem-solver"><a href="#trust-me-i-am-a-problem-solver" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Trust me, I am a problem solver</h3><p>I took a small break from debugging the issue.</p><p>Came back after few minutes and asked myself: &quot;what problem am I solving right now?&quot;</p><p>&quot;A coffee grinder cannot be used, because the mechnical contactor cannot be pressed by a lid&#x27;s cam&quot;, I restated the definition of the problem in my mind.</p><p>&quot;If I could press the contactor, I would be able to prepare my coffee!&quot;, I envisioned in my head.</p><p>I followed this deduction with the next question: &quot;what is the easiest possible way to make the contactor pressed?&quot;</p><p>I had an idea.</p><p>What if I could put there a cut wooden stick for skewers that is used for tasty BBQ meals?</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/coffee-grinder-fixed.png" class="max-h-[30rem]"/></div><div class="italic mx-24">An illustrative design of a wooden stick for skewers working as a static cam.</div></div><p>It seemed easy and pragmatic.</p><p>I took one of the wooden sticks for skewers and cut it correctly to fulfill my engineering&#x27;s vision.</p><p>After few seconds it was there.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/coffee-grinder-fixed-real.png" class="max-h-[30rem]"/></div><div class="italic mx-24">A solution to the &quot;broken lid&quot; problem</div></div><h3 id="are-we-done"><a href="#are-we-done" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Are we done?</h3><p>But I didn&#x27;t finish. The applied solution is only the half of the final solution.</p><p>What was left?</p><p>I was missing the new problems, created by my solution.</p><p>&quot;What problems my solution has introduced?&quot;, I asked myself.</p><p>I thought of safety issues that might happen - like grinding with no lid.</p><p>Or taking off the lid before the grinding was done so that coffee will be everywhere, but not in the coffee grinder.</p><p>Had a bunch of other ideas but I immediately communicated the most risky one - not enough safety. So my wife acknolwedged that such temporary solution is just fine (she wanted to get her coffee too).</p><p>It might seem that entire journey took days, but actually it was less than 10 minutes.</p><h3 id="is-it-the-best-solution"><a href="#is-it-the-best-solution" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Is it the best solution?</h3><p>You might think &quot;what the hell has just happened?&quot; (I hope you do). A coffee grinder? A wooden sticks for skewers?</p><p>&quot;I don&#x27;t have time to read such a nonsense, I am a serious architect/developer/team leader&quot; - such thoughts might arise.</p><p>During this short period of time we encountered several &quot;phenomena&quot; - I already wrote in this blog about some of them.</p><p>The first observation is how easily we fall into a trap of focusing on the solution, without understanding the problem we are facing.</p><p>Ideas around soldering and using a lighter weren&#x27;t bad in their nature, but they involved so much accidental complexity.</p><p>Soon, the accidental complexity would have become &quot;the accidentally essential complexity&quot; (I wrote a bit about it in <a href="https://talesfrom.dev/blog/essentially-bounded-accidentally-unlimited">Essentially bounded, Accidentally unlimited</a>).</p><p>I almost fell into this rabbit hole.</p><p>What&#x27;s more, The King of Kings, the context, matters as well. If I lived on an island and without a possibility to get a new appliance - was my solution the best of all possible? (let&#x27;s forget about not having electricity there, for a while).</p><h3 id="is-it-the-final-solution"><a href="#is-it-the-final-solution" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Is it the final solution?</h3><p>All the conditions - time of the day, future needs and ideas - made me thinking that it was the best suitable solution, <strong>in that context</strong>.</p><p>It&#x27;s similar to our design in the software work - whether we are talking about the architecture of a particular system, or an organization of classes that are collaborating together to solve a given problem (An organization? You might be interested in <a href="https://talesfrom.dev/blog/organization-driven-design">&quot;Organization-Driven Design&quot;</a> and in <a href="https://talesfrom.dev/blog/microoffices-vs-officeolith">&quot;Microoffices&quot; vs &quot;Officeolith&quot;</a>).</p><p>Applied solution is so dependent on the contextual environment. As I wrote in <a href="https://talesfrom.dev/blog/i-dont-know">I don&#x27;t know</a>:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Contextless evaluation is the root of (almost) all evil.</p></div></div></div><p>Try to understand the context you are operating in.</p><h3 id="trade-offs-what-trade-offs"><a href="#trade-offs-what-trade-offs" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Trade-offs? What trade-offs?</h3><p>What we also could observe, is the trade-off juggling.</p><p>A wooden stick for skewers was solving the problem of the connector not fulfilling its responsibility, but it introduced some other problems.</p><p>In one of his great books, <a href="https://www.amazon.com/Are-Your-Lights-Figure-Problem/dp/0932633161">Are Your Lights On?: How to Figure Out WHat the Problem Really Is</a>, Jerry Weinberg stated quite clearly:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>EACH SOLUTION IS THE SOURCE OF THE NEXT PROBLEM</p></div></div></div><p>Even if we find a perfectly viable &quot;hammer&quot; for a given &quot;nail&quot;, it will create a set of new issues.</p><p>As with the example of losing safety features - it&#x27;s not the best approach, but for that day of the coffee grinder breaking down, the clear communication was the key (it&#x27;s always the key, just for your notice).</p><p>That&#x27;s why it is so damn important to ask the fundamental question: &quot;what problems do I introduce by applying X as a solution?&quot; (if you are interested, I shared more of similar insights in <a href="https://talesfrom.dev/blog/software-engineering-for-busy-parents">Software Engineering for busy parents</a>)</p><p>It might give you the perspective what is the impact of &quot;this little tiny if down there&quot;.</p><h3 id="solution-probleming"><a href="#solution-probleming" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Solution probleming?</h3><p>There&#x27;s another quote of Jerry, from the same book, I like very much:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>If nothing else, there young computniks will acquire one valuable lesson from their unrelenting quest for problems to fit their solution - &quot;solution probleming&quot;, we call it. As they quest, so shall they learn. Mostly, they&#x27;ll learn about problem definition.</p></div></div></div><p>It&#x27;s easy to just go and think about the solutions, about the design, about the architecture, without putting enough time and effort for understanding the fundamentals, the context and the needs, about the problem we are trying to solve.</p><p>Jerry found a perfect name for such activity: &quot;solution probleming&quot;.</p><p>When we lose the focus on the problem, its definition, we might become &quot;a solution problemer&quot;. That&#x27;s a handy alternative for describing someone who got trapped in trying to solve the solution&#x27;s accidental complexity that he or she introduced.</p><p>React, Kafka, entangled setup of ocks, frequently breaking tests, using Event Sourcing, Cloud, rewriting legacy, wrong configuration, etc. - what is your problem? what are you trying to solve, <strong>really</strong>?</p><p>Another interesting question we might pose, to <a href="https://talesfrom.dev/blog/slow-down">Slow down</a>, is:</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>Am I solving a problem or am I probleming a solution?</p></div></div></div><p>It sounds very trivial and even funny, but tinker about it for a while.</p><p>It&#x27;s so easy to get &quot;into the zone&quot;, &quot;into the process&quot;, and have &quot;skin in the game&quot;. Tunnel vision is right around the corner.</p><p>As we are talking about the tunnel, <a href="https://www.amazon.com/Are-Your-Lights-Figure-Problem/dp/0932633161">are your lights on</a>?</p>]]></content:encoded>
    <pubDate>Sun, 12 Mar 2023 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>programming</category><category>paradigms</category><category>language</category><category>modeling</category><category>problem-solving</category><category>modeling</category><category>model</category><category>trade-offs</category><category>representations</category><category>mental models</category><category>discipline</category><category>aspects</category><category>perspectives</category><category>architecture</category><category>design-thinking</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/i-dont-know</guid>
    <title>I don&#39;t know</title>
    <link>https://talesfrom.dev/blog/i-dont-know</link>
    <description>Is there a benefit of not knowing?</description>
    <content:encoded><![CDATA[<h3 id="no-logic"><a href="#no-logic" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>No logic</h3><p>Imagine that someone from a &quot;business&quot; or a &quot;product&quot; team approaches us, the team, and asks about our &quot;feeling&quot; (that will become an feelstimation) of a new functionality in one of our products.</p><p>&quot;It seems fairly &quot;simple&quot; and almost no logic there, I sense a bunch of new CRUD endpoints&quot;, someone anonymously says.</p><p>&quot;I&#x27;ve something similar in the past, it looks almost identical&quot;, another person continued from the previous conclusion.</p><p>&quot;Yeah, it might be a couple of ifs here and there, and of course we need to write new k8s manifests&quot;, an unidentified voice, from the group of people, said.</p><h3 id="its-too-slow"><a href="#its-too-slow" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>It&#x27;s too slow</h3><p>Imagine that we hear a discussion of two young IT undergrads, in a local mall.</p><p>&quot;Jeez, should I pick JavaScript or Rust as the next curriculum?&quot;, one of them said.</p><p>&quot;I think Rust is the future. It&#x27;s fast, has borrow checker that teaches you tenets of memory management in the better way than C++. JavaScript is slow.&quot;, another one replied.</p><p>&quot;Hm, maybe you are right. &quot;</p><h3 id="too-complicated"><a href="#too-complicated" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Too complicated</h3><p>Imagine that we observe a pair programming session of two fellow craftsman.</p><p>&quot;And now the argument: length. I am creating a class for it.&quot;, said one of them.</p><p>&quot;Wait, a class? It&#x27;s a simple double. There are no rules, other than it must be positive.&quot;, quickly replied another one.</p><p>&quot;So maybe a record?&quot;, continued the first one.</p><p>&quot;Don&#x27;t overcomplicate, this gives us no benefits at the current moment. It&#x27;s overengineering.&quot;, urged the second one.</p><h3 id="sounds-familiar"><a href="#sounds-familiar" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Sounds familiar?</h3><p>I believe all of us witnessed similar scenarios. The content of the situations might have differed, but the form, the frame, was gravitating around the same thing.</p><p>What&#x27;s a common thing?</p><p>King of the Kings is missing - the context.</p><p>The great aspect of writing is that I cannot provide entire state of my mind so that even by this activity itself the King gets lost, somewhere.</p><p>Of course, each scenario is a bit exaggerated and no one would ever do such a naive assumptions (really?). I&#x27;ve heard once that &quot;exaggeration promotes understanding&quot; (thanks Anders!).</p><h3 id="contextless-evaluation"><a href="#contextless-evaluation" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Contextless evaluation</h3><p>It is easy to do premature evaluation without taking the details of the current situation into account.</p><p>It is easy to say that Angular is the best and alpinejs sucks, not asking the question what&#x27;s going to be built it with.</p><p>CUPID is wrong and SOLID is the way to go.</p><p>Unit tests are pointless, long live integration tests!</p><p>Opinions are good, until they are not.</p><p>Contextless evaluation is the root of (almost) all evil.</p><p>This does not mean we need to stop ourselves from evaluating tools, methods, components, etc. - remembering that next to the technical aspect, there are other too - like sociopsychological perspective (I wrote a bit about some useful approaches in <a href="https://talesfrom.dev/blog/software-engineering-for-busy-parents">Software Engineering for busy parents</a>)</p><h3 id="context-detectors"><a href="#context-detectors" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Context detectors</h3><p>Is it possible to orient ourselves toward context seeking? To seek it, desire it, like a drowning person wants to take a breath?</p><p>I am using two mental models that help get the details. (by the way, did you notice that I didn&#x27;t say WHEN I am using them? Did your brain add &quot;always&quot; somewhere? This is what I am talking about!)</p><p>They are not very imperative steps, more a declarative way of how one can operate.</p><h3 id="i-dont-know-ism"><a href="#i-dont-know-ism" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;I don&#x27;t know&quot;-ism</h3><p>The first one is actually really simple - it is enclosed in the title of this blog post. Putting yourself in the frame of not knowing. As it was adviced in the <a href="https://leanpub.com/introducing_eventstorming">Introduction to EventStorming</a> by Alberto, &quot;be the dumbest person in the room&quot;.</p><p>Becoming the student of the current moment is the key. A perfectly curious human being, watching all the gestures, facial expressions, and words used.</p><p>This is the mindset we want to employ. When I &quot;don&#x27;t know&quot;, things are getting magical because we actually we might get to know!</p><p>It also puts the perspective of being humble - as I &quot;don&#x27;t know&quot;, I need to pay attention.</p><p>Is it really a next CRUD-ish app, we will build? I don&#x27;t know.</p><p>Is Rust a better choice than JS? I don&#x27;t know.</p><p>Is double enough to represent a length? I don&#x27;t know.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Contextless evaluation is the root of (almost) all evil.</p></div></div></div><p>Of course, it doesn&#x27;t mean we &quot;don&#x27;t know&quot; <strong>technically</strong>. Widely opening your eyes, heart and arms to absorb, to feel and to understand what problem we are trying to solve right now - it doesn&#x27;t mean we need to leave our experience by the door.</p><p>What about <a href="https://en.wikipedia.org/wiki/Cynefin_framework">Cynefin</a>? Not all contexts are complex or complicated. And that&#x27;s also true. But without doing an initial analysis, openness for the exploration - we might be pretending that we know. That might be harmful.</p><p>&quot;I don&#x27;t know, let&#x27;s figure it out&quot; is one of the proper answers.</p><p>That&#x27;s also an interesting perspective in terms of agile thinking. Knowing things (or rather <strong>pretending</strong> knowing things) beforehand might make us stiff, fragile and not observing the reality. We are becoming <a href="https://talesfrom.dev/blog/fragile">(Fr)Agile</a>.</p><p>We need to start somewhere, that&#x27;s true, but rather than pouring concrete form, made of assumptions, what about sensing and feeling - knowing that you truly don&#x27;t know.</p><p>I like to call such a philosophy &quot;I don&#x27;t know&quot;-ism. It helps becoming compassionate, empathy-oriented one, that simply wants to understand!</p><h3 id="boring-i-dont-know-whats-that"><a href="#boring-i-dont-know-whats-that" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Boring? I don&#x27;t know what&#x27;s that&quot;</h3><p>I have been observing that starting with &quot;I don&#x27;t know, need to figure out&quot; gives space for exploration. It puts one in the position of a truth seeker.</p><p>On the other hand, starting with &quot;Yeah, that&#x27;s simple&quot; or &quot;I know how it works&quot; shrinks the possibilities and works as a great tool for reinforcing confirmation bias.</p><p>It is easy to assume, but it is hard to drop the anchor.</p><p>I want to be the beggar of understanding, asking for breadcrumbs of knowledge, and stop being the baron of assumptions, the richling of biases.</p><p>&quot;How?&quot;, that&#x27;s what I am imagining you are now asking me (I hope you do, don&#x27;t you?)</p><p>There&#x27;s one simple sentence that describes this attitude - <strong>&quot;That&#x27;s interesting, could you elaborate?&quot;</strong>.</p><p>It sounds naive and fairly simple, but the depth of this weaponry of curiosity is still being explored and discovered by me.</p><p>People are revealing their intentions, thought processes, contextual reasoning and many, many more.</p><p>Combined with &quot;I don&#x27;t know&quot;-ism, it is a perfect combination for becoming the curiosity-driven scientist, that is enthusiastically waiting to learn.</p><h3 id="coaching-like-bullshit"><a href="#coaching-like-bullshit" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Coaching-like bullshit?</h3><p>I might sound like a hoax life coach (please, don&#x27;t get me wrong, life coaching might be very, very useful method!) that tries to sell you his training for money (additionally with access to the great community of learners, along with lifetime access to the coaching platform!).</p><p>Remember, I am a beggar of understanding, so I don&#x27;t know your problem or situation (or, wait for it, context!).</p><p>&quot;I don&#x27;t know&quot;-ism and &quot;That&#x27;s interesting, could you elaborate?&quot;-ism might not suit you. And that&#x27;s fine.</p><p>But, if you find it doesn&#x27;t fit your case, that&#x27;s interesting! Could you elaborate? 🤔</p><p>How to move forward? How to train the muscle of &quot;I don&#x27;t know&quot;-ism? I don&#x27;t know so let&#x27;s figure out together!</p><ul><li>when you are getting a service from someone, ask about the work (e.g. electrical work) they do - what could you learn from it?</li><li>get yourself involved in pair programming! There&#x27;s enormously huge potential to use &quot;That&#x27;s interesting! Could you elaborate?&quot;-ism!</li><li>when you got a question about the area of expertise of yours, try restraining from giving an answer - instead just say &quot;I don&#x27;t know, let&#x27;s figure out together&quot; - and flow with the process.</li></ul><p>And one last thing. All those mental models we talked about do not mean we must drop being professionals, stop having an engineering mindset, or forget about behaving empathetically. This must deliver value to our recipients, customers, or relatives - by understanding what is the context we might provide an even bigger &quot;impact&quot; and help!</p>]]></content:encoded>
    <pubDate>Sun, 05 Mar 2023 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>programming</category><category>paradigms</category><category>language</category><category>modeling</category><category>problem-solving</category><category>modeling</category><category>model</category><category>code</category><category>representations</category><category>mental models</category><category>discipline</category><category>aspects</category><category>perspectives</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/modeling-maturity-levels</guid>
    <title>Modeling Maturity Levels</title>
    <link>https://talesfrom.dev/blog/modeling-maturity-levels</link>
    <description>How we can think of modeling?</description>
    <content:encoded><![CDATA[<h3 id="floor-panels"><a href="#floor-panels" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Floor panels</h3><p>Keith is responsible for providing the best floor panels installation experience in the world.</p><p>Of course, he is not working alone. His friend, Kim, started the journey in the floor panel business.</p><p>Kim needs to learn the jargon and the proper skills - he&#x27;s smart so there&#x27;s no doubt he won&#x27;t do so.</p><p>Both came to do a job in one newly built house.</p><p>When they entered, the material was laying on the concrete ground.</p><h3 id="the-valid-ones"><a href="#the-valid-ones" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The valid ones?</h3><p>They started planning the work and the first thing that Keith begun with was using a impermanent, black marker.</p><p>Kim was a bit confused because he saw that Keith wrote on each &quot;VALID&quot; panel. But maybe that&#x27;s the industry standard?</p><p>Each time after the panel got placed on the ground, Kim&#x27;s task was to go and erase &quot;VALID&quot; text. Keith advised to write &quot;INSTALLED&quot; on it instead.</p><p>It looked quite strange, but maybe it&#x27;s the industry standard?</p><p>Kim asked Keith what&#x27;s the point with &quot;VALID&quot; and &quot;INSTALLED&quot; markings and got a simple reply: when a floor panel has &quot;VALID&quot; text, it can be properly installed. When &quot;INSTALLED&quot; text is written on it, then no further work on it is possible.</p><p>Well, that sounded a bit straightforward - only not installed floor panels can be placed on the ground, whereas those ones already laying there can&#x27;t be installed anymore.</p><p>Still, Kim didn&#x27;t know why Keith names each one to be installed as &quot;VALID&quot;, but it might be the industry standard?</p><h3 id="what-do-to-with-invalid-ones"><a href="#what-do-to-with-invalid-ones" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What do to with invalid ones?</h3><p>From time to time, Kim and Keith needed to cut some floor panels to fit them into the right place in the room.</p><p>Just after cutting was completed, Keith advised Kim to erase &quot;VALID&quot; and put &quot;INVALID&quot; instead, provided that it cannot be further used.</p><p>Some of them were too short, too irregular or cut with a very strange shape. Kim was able visually distinguish them, but he did what Keith asked him for.</p><p>After couple of hours full of work, they finished they job.</p><p>The hourse owner appeared and was impressed by the outcome. However, he had two questions.</p><p>&quot;Why all the installed floor panels have &quot;VALID&quot; text on them?&quot;, asked the service taker.</p><p>&quot;Ah, that&#x27;s because we wanted to indicate they can be placed on the ground&quot;, Keith anwsered. He seemed very confident with his words, he wanted to sound very professional to impress Kim.</p><p>&quot;Well, couldn&#x27;t you just look at them? It&#x27;s pretty straightforward to know so?&quot;, the house owner was shocked a bit.</p><p>He urged both Kim and Keith to erase this marking from each installed floor panel.</p><p>After the task was finished, the house owner asked the second question.</p><p>&quot;What is about that pile of irregular and cut panels? Why do they have &quot;INVALID&quot; text written on each?&quot;, the house owner grilled them with quite logical reasoning, simultaneously pointing at the pile.</p><h3 id="do-you-like-art"><a href="#do-you-like-art" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Do you like art?</h3><p>&quot;Each floor panel with &quot;INVALID&quot; text, written on it, cannot be installed, but is still owned by the customer and can be further used.&quot;, Keith continued.</p><p>Keith told him that he can&#x27;t throw out the product that was bought by the customer.</p><p>Kim couldn&#x27;t believe in Keith&#x27;s words.</p><p>&quot;You must be kidding, right? IT IS A COMPLETE WASTE!&quot;, the house owner yelled vigorously.</p><p>&quot;WHAT CAN I DO WITH A FLOOR PANEL THAT IS CUT LIKE THAT?&quot;, the house owner got a bit angry while showing a bizzare looking shape.</p><p>&quot;Do you like art? You could think of a creative way of putting them together. If you take this...&quot;, Keith grabbed one.</p><p>&quot;Enough. Take all &quot;invalid&quot; ones and throw them out. It&#x27;s a complete waste&quot;, said the service taker.</p><p>Keith nodded and cleaned up the place from all the waste.</p><p>Kim and Keith left the house and were about to put leftovers into the trashbin, but Keith wanted to do the last thing with them.</p><p>&quot;What do you want to do, Keith?&quot;, asked Kim.</p><p>Keith advised to put &quot;WASTE&quot; text on each. &quot;That&#x27;s the industry standard, Kim. It informs about what its status.&quot;, said Keith.</p><h3 id="magical-thinking"><a href="#magical-thinking" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Magical thinking</h3><p>I wonder what would be your reaction to such &quot;an experience&quot;. Will you be shoked? Ashamed? Astonished?</p><p>Would you need written text to determine what a given floor panel could be used for? (it would be strange if you need 🤔)</p><p>I consider this exemplary, short tale, not as imaginary one. It&#x27;s quite opposite.</p><p>When collaborating with business stakeholders, we might often hear very precise verbal descriptions about the context and related rules.</p><p>Especially when talking about concepts with the lifecycles - like a floor panel in our small scenario.</p><p>Almost immediately, it gets magical &quot;status&quot; attached to it. Fellow technical people easily put &quot;a flag&quot; to represent a specific status (if you want to check why this might not be the best modeling method in this blog post <a href="https://talesfrom.dev/blog/bool-considered-harmful">Bool considered harmful?</a>).</p><p>The worst thing is that we &quot;polluted&quot; other minds with &quot;status thinking&quot;. It isn&#x27;t extraordinary to hear a domain expert saying &quot;it&#x27;s just a <code>IsValid</code> status in the database&quot;.</p><p>How does this &quot;status&quot; come from? Isn&#x27;t it our magical thinking that might make the given concept have &quot;status&quot; stitched to it?</p><p>A floor panel <strong>has</strong> a status.</p><p>Really? This is one perspective - description of the properties.</p><p>One could ask: what else a floor panel has?</p><p>Along with the status, it might have a nominal weight, an actual weight, a size, a color, a batch serial number, but maybe also a marketing name, an actual name of the material?</p><p>Still, it&#x27;s a single perspective.</p><h3 id="three-perspectives-of-modeling"><a href="#three-perspectives-of-modeling" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Three perspectives of modeling</h3><p>I mentioned them briefly in <a href="https://talesfrom.dev/blog/software-engineering-for-busy-parents">Software Engineering for busy parents</a> blog post, but now it&#x27;s time to give my perspective (pun intended) and observations.</p><p>Originally, it is mentioned in the book <a href="https://www.amazon.com/Rethinking-Systems-Analysis-General-Thinking-ebook/dp/B0054DW3KS">Rethinking Systems Analysis and General Thinking</a> by Gerald Weinberg, elaborated thorougly by various people (for example: in <a href="https://legacyfighter.pl/">Legacy Fighter</a> course, by Mariusz Gil in <a href="https://bettersoftwaredesign.pl/">Better Software Design podcast</a> and by <a href="https://bottega.com.pl/">Sławek Sobótka</a>).</p><p>But let&#x27;s hold on a second. You probably already noticed I like to focus on the language we use. So what does it mean <em>an aspect</em> or <em>a perspective</em>?</p><p>They both might be related to various forms, different point of views.</p><p>We sometimes say &quot;see it from a different angle&quot;, &quot;you need to distance yourself from it&quot; or &quot;let&#x27;s view it from a higher point&quot; - each of those phrases is related to the position of <strong>an observer</strong>.</p><p>My reasoning wasn&#x27;t clear - how to think about the three perspecitves? How to use them?</p><p>I haven&#x27;t still introduced the perspectives, so here they are:</p><ul><li>Being</li><li>Behaving</li><li>Becoming</li></ul><p>Each aspect has a set of associated questions:</p><ul><li><strong>Being</strong>: What it has? What does it consist of? What is it?</li><li><strong>Behaving</strong>: What does it do? How it can be used? What one can do with it?</li><li><strong>Becoming</strong>: What does it change into? What it becomes? what can be created out it?</li></ul><p>We could explore and find even more questions, related to the given aspect, especially those ones about the rules and invariants, but for now it&#x27;s secondary.</p><p>We might say that one could have three different perspectives on how to look upon a given concept (in our current example it&#x27;s a floor panel).</p><h3 id="what-is-the-perspective-about-the-perspective"><a href="#what-is-the-perspective-about-the-perspective" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What is the perspective about the perspective?</h3><p>As we discussed, it is important to envision an observer, when talking about the perspective. What metaphor would we use to visualize it?</p><p>Angle?</p><p>Distance?</p><p>Height?</p><p>The initial gut feeling was strongly related to an angle metaphor, hence the given visualization:</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/being-behaving-becoming-no-observer.png" class="max-h-[30rem]"/></div><div class="italic mx-24">A floor panel and the three perspectives.</div></div><p>Imagine we are placing the observer (represented as an eye in the next picture, visible below).</p><p>Such approach excludes other perspectives, if one decides to go with a specific one, e.g. <em>Being</em> aspect. It would mean we see the given concept through either <em>Being</em> <strong>or</strong> <em>Behaving</em> <strong>or</strong> <em>Becoming</em> perspective.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/being-behaving-becoming-observer.png" class="max-h-[30rem]"/></div><div class="italic mx-24">A floor panel perceived from <strong>Being</strong> angle (perspective).</div></div><p>We could look at something, but only from one aspect at the same time.</p><p>In our tale, a floor panel had &quot;status&quot; associated with it and later we also enumerated couple of other traits. In the code, it could look as follows:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">FloorPanel</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> Status <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">double</span></span> Width <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">double</span></span> Height <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> MaterialName <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> MarketingName <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">double</span></span> Price <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token comment">// ... other properties and answers to the question &quot;What it has?&quot;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>But wasn&#x27;t there any behavior related to such a floor panel? Oh yes, it was.</p><p>Even for such a toy example, thinking about &quot;the structure&quot; and answering the question &quot;What it has?&quot; made us focus on the static aspect of the concept.</p><p>We already know that both Keith and Kim were using floor panels across their workflow. So the behaviour didn&#x27;t disappear.</p><p>A floor panel traits like <code>Color</code>, <code>Width</code>, <code>MarketingName</code> do no convey the context. They are meaningless, useless. When we put them next to the behavior, they become more meaningful - <code>Install a floor panel</code>, <code>Cut a floor panel</code>, <code>Throw away a floor panel</code>.</p><p>So the answers to the questions, related to the <strong>Behaving</strong> aspect, &quot;What does it do?&quot; or &quot;How one can use it?&quot; are solved at some point, the only question is - where? On what level (or layer?)?</p><p>Taking into account a floor panel model presented above, in the code, we would probably express the <strong>Behaving</strong> aspect on the service layer - a typical anemic model and &quot;rich&quot; in logic service layer.</p><p>As with <strong>Being</strong> aspect and behavior, similar might applies to <strong>Behaving</strong> aspect and the description of what a given concept <em>has</em>. We wouldn&#x27;t be able to use only behaviors to express it completely.</p><h3 id="what-about-the-language"><a href="#what-about-the-language" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What about the language?</h3><p>Let&#x27;s focus on the language again.</p><p>All the questions related to each aspect, might imply a certain language that is going to be used when trying to look for the answers.</p><p>What are the types of words that might match each of the perspective?</p><p>We might naturally observe that <strong>Being</strong> aspect is related to <strong>nouns</strong> - a floor panel, a color, a size, a marketing name, a price, etc.</p><p><strong>Behaving</strong> aspect might correspond to <strong>verbs</strong> - install, throw away, cut, erase, write, etc.</p><p>The first observation might be that <strong>Being</strong> and <strong>Behaving</strong> aspect need to go hand in hand to provide a proper meaning - the King of Kings - the context.</p><p>What about <strong>Becoming</strong> aspect? (probably the most mysterious one 🤔)</p><p>The closest type of words I found describing it in a good way is <strong>adjective noun collocation</strong>. Let&#x27;s check it&#x27;s definition.</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">&quot;adjective noun collocation&quot; - definition</div><div class="pb-2 px-3"><div class="break-words"><p>Collocations are a pair or group of words which habitually appear together to convey a whole new meaning. We use adjectives and nouns collocations putting adjectives before nouns.</p></div></div></div><p>Examples of adjective noun collocation:</p><ul><li>installed floor panel</li><li>broken car</li><li>rich answer</li><li>approved document</li><li>completed task</li></ul><p>It&#x27;s very interesting - almost like attaching the context to the <strong>noun</strong>, without explicitly stating the <strong>verb</strong> that caused it.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/being-behaving-becoming-language.png" class="max-h-[30rem]"/></div><div class="italic mx-24">Language and modeling perspectives</div></div><p>As <strong>Being</strong> and <strong>Behaving</strong> aspects needed each other to provide a proper context, <strong>Becoming</strong> aspect isn&#x27;t perfect, but conveys the meaning and possible causes by building on top of the remaining aspects.</p><p>We could for example ask: What information and what actions are needed to have <code>approved document</code>?</p><h3 id="the-language-defines-the-context"><a href="#the-language-defines-the-context" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The language defines the context</h3><p>How could we actually use it in the code? This is something which most of us are interested in on daily basis.</p><p>We typically use <strong>nouns</strong> to describe data (or information), <strong>verbs</strong> to express behavior (or actions) and <strong>adjective noun collocations</strong> to manifest the consequence of a transformational behavior.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/being-behaving-becoming-coding.png" class="max-h-[30rem]"/></div></div><p>Also, throughout of this reasoning, one might notice that none of the perspective is sufficient alone (e.g. a noun without a verb - how useful is <code>Color</code> trait of a floor panel? We don&#x27;t know without putting it next to the verb).</p><p>That might mean that &quot;angle&quot;-like visualization and metaphor for those perspectices isn&#x27;t the most suitable one.</p><h3 id="lets-distance-ourselves-a-bit"><a href="#lets-distance-ourselves-a-bit" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Let&#x27;s distance ourselves a bit</h3><p>When we are examining a concept, we would need to look from all possible angles to evaluate its usefulness in a given context.</p><p>Should we try another metaphor for mentioned modeling perspectives?</p><p>Let&#x27;s go back, for a while, to the questions related to each perspective, but now putting accent on the rules that are relevant, we might get the following:</p><ul><li><strong>Being</strong>: What is the maximum size? What colors are available? How long marketing name can be?</li><li><strong>Behaving</strong>: Is it always possible to install a floor panel? What information we need to have to decide if it could be installed, e.g. the actual size in comparison to required size?</li><li><strong>Becoming</strong>: What we can do with a not installed floor panel? What can we do with an irregularly shaped, cut floor panel?</li></ul><p>Each of them use different language, and we already discussed it a bit. Rule-wise, <strong>Being</strong> is much more general, whereas <strong>Becoming</strong> sounds highly contextual.</p><p>What&#x27;s more, as <strong>Becoming</strong> attaches more of the consequential context to the verb, it induces the related behavioral causes based on the rules and implications of them.</p><p>Same works for <strong>Behaving</strong> that requires contextual information to satisfy the rules of a given behavior.</p><p>For <strong>Being</strong>, the rules are very primitive, almost a data-oriented.</p><p>Instead of looking from different points, let&#x27;s look from the same point, but from different distances.</p><p>So not <strong>from</strong> a different perspective, but look <strong>through</strong> a different perspective.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/being-behaving-becoming-levels.png" class="max-h-[30rem]"/></div><div class="italic mx-24">Looking and modeling <strong>through</strong> a different perspectives</div></div><h3 id="modeling-maturity-levels"><a href="#modeling-maturity-levels" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Modeling Maturity Levels</h3><p>This metaphor gives us some interesting properties because now we are positioning the observer (ourselves) almost like on the various heights, distances or levels.</p><p>One could say that when we are looking from a <em>Becoming</em> level, we have process perspective on a given concept. Such perspective require defining possible behaviors (or actions) to obey the transformational rules. Then, each behavior demands a set of information to satisy the invariants.</p><p>This might mean that observing a given concept from a specific level, requires including lower levels.</p><p>Distancing the observer gives the possibility to attach much more context to the analysis - either to <em>Being</em> or <em>Behavaing</em> aspects.</p><p>For example, when we have a cut floor panel then it might be installed if it fits the required size, or be thrown away if it has too irregular size and shape.</p><p>What&#x27;s even more interesting, when a floor panel is thrown away it becomes a waste. It&#x27;s no longer considered as <em>a floor panel</em>.</p><p>Such reasoning might constitute that Weinberg&#x27;s three perspectives of modeling might be actually closer to levels, rather than perspectives.</p><p>As we discussed, perspectives incorporate the notion of the angle, whereas height/distance opens a possibility to include all underlying levels while modeling.</p><p>Being inspired by <a href="https://en.wikipedia.org/wiki/Richardson_Maturity_Model">Richardson Maturity Model</a> for REST, I started thinking about modeling, using discussed levels, as <strong>Modeling Maturity Levels</strong>.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/being-behaving-becoming-levels-extended.png" class="max-h-[30rem]"/></div><div class="italic mx-24">Modeling levels</div></div><p>It could also be thought of as <strong>Model Maturity Levels</strong>, meaning that depending on what level (height or distance, as well) we &quot;place&quot; ourselves while modeling, the richer model we will get.</p><p>Also, it corresponds in an interesting way to the approached I already talked about in <a href="https://talesfrom.dev/blog/many-faces-of-ddd-aggregates-in-fsharp">Many faces of DDD Aggregates in F#</a>- one could say that <a href="https://talesfrom.dev/blog/many-faces-of-ddd-aggregates-in-fsharp#solution-3-functional-state-machine-like-approach">the functional FSM approach</a> incorporated Becoming level, pulling all &quot;lower&quot; levels into analysis and development.</p><p>It clearly shows the impact of using proper language and beyond &quot;status thinking&quot; approach (you can read more about such topics in <a href="https://talesfrom.dev/blog/language-of-the-problem">Language of the problem</a> and <a href="https://talesfrom.dev/blog/bool-considered-harmful">Bool considered harmful?</a>).</p><p>But let&#x27;s stop for a sec here, what about &quot;angle&quot;-like thinking about modeling - should it be that easily discarded and undervalued?</p><h3 id="is-there-a-single-modeling-context"><a href="#is-there-a-single-modeling-context" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Is there a single modeling context?</h3><p>&quot;Looking from a various angles&quot; is still valid, and required!</p><p>As <strong>Modeling Maturity Levels</strong> might provide a huge benefit for finding the richness for a given model, it applies to a single context.</p><p>It might mean that in installing service context, a floor panel might be behaviorally rich. Contrary to that, in product catalogue context, it might be shallow and work on the primitive data types level.</p><p>Those two contexts have totally different modeling levels and that is fine, as long as we manage the complexity of each context bounding it respectively.</p><p>When we combine two metaphors for modeling, levels and angles, we might have interesting mental model that can be visualized in the following way:</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/being-behaving-becoming-perspectives.png" class="max-h-[30rem]"/></div><div class="italic mx-24">Combining levels and perspectives when thinking of modeling</div></div><p>Knowing what are the business contexts, in which our concept gets materialized, we are able to analyze and determine the level of richness.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/being-behaving-becoming-angles-and-levels.png" class="max-h-[30rem]"/></div><div class="italic mx-24">Looking at a concept through various levels and from a different perspectives</div></div><p>Each &quot;eye&quot; (a process of observation), for a given angle, is placed on a certain level.</p><p>This might mean that we &quot;see&quot; contextually various sets of rules to satisfy, depending on the level we are &quot;standing&quot; and observing.</p><p>As it was once said, &quot;all models are wrong (=imperfect), but some are useful&quot;.</p><h3 id="final-words"><a href="#final-words" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Final words</h3><p>Should you start using <em>Becoming</em> level in your next CRUD? Sure, don&#x27;t forget to add Kubernetes to the stack.</p><p>As with everything, the context is the king. Simulation in your head and analysis doesn&#x27;t mean <em>Becoming</em> level need to materialize in your code.</p><p>You might have <code>InstalledFloorPanel</code>, <code>WastedFloorPanel</code>, <code>IrregularlyCutFloorPanel</code>, <code>CutFloorPanel</code> and <code>FloorPanel</code> concepts in your codebase and have only tiny gap between the language used by the business experts and your code.</p><p>Will it be free? Nope, it will require effort, skills and competence to utilize such mental model.</p><p>One might be also afraid of <a href="https://talesfrom.dev/blog/the-cost-of-modeling">The cost of modeling</a>, but simplification doesn&#x27;t mean the complexity of the reality disappears that easily.</p><p>We could happily model business concepts using data model (data structures) and say &quot;this is fine&quot; while sitting in the room full of fire.</p><p>The understanding, the reasoning, might suffer and this is the first step to hell.</p>]]></content:encoded>
    <pubDate>Sun, 19 Feb 2023 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>programming</category><category>paradigms</category><category>domain-driven design</category><category>modeling</category><category>problem-solving</category><category>modeling</category><category>model</category><category>code</category><category>representations</category><category>principles</category><category>discipline</category><category>aspects</category><category>perspectives</category><category>data structures</category><category>behaviors</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/the-ambiguity-of-encapsulation</guid>
    <title>The ambiguity of encapsulation</title>
    <link>https://talesfrom.dev/blog/the-ambiguity-of-encapsulation</link>
    <description>To protect or to hide?</description>
    <content:encoded><![CDATA[<h3 id="a-document-without-supervision"><a href="#a-document-without-supervision" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>A document without supervision</h3><p>Imagine there is a guy named Jerry.</p><p>He is working in an organization in which he is responsible for a very important matter: ordering office equipment like pens, notebooks, stickies, etc. whenever there is a need.</p><p>Jerry is massively busy with his work so he&#x27;s constantly absent in his room.</p><p>Other employees quickly understood and learned that Jerry is busy so that they need to take care of their needs themselves.</p><p>What they started doing was going to his room and filling in the &quot;office equipment needs&quot; sheet.</p><p>Jerry was confident that the format might change in the future so he considered this sheet as &quot;version 1&quot;.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">OfficeEquipmentNeed_Version_1</span> <span class="token punctuation">{</span> <span class="token comment">/*...*/</span> <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">OfficeEquipmentNeeds</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">IEnumerable<span class="token punctuation">&lt;</span>OfficeEquipmentNeed_Version_1<span class="token punctuation">&gt;</span></span> Sheet <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>This wouldn&#x27;t have been that worrisome, but this sheet started being passed here and there throughout the entire office.</p><h3 id="who-has-the-document"><a href="#who-has-the-document" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Who has the document?!</h3><p>Poor Jerry needed to track who is currently editting this document.</p><p>It took ages to find out where it is.</p><p>When finally Jerry found the document - it was full of unauthorized entires - people made jokes and ordered pizza, coca-cola.</p><p>Others put the actual needs, but in the wrong format. At least not the one that Jerry expected.</p><p>Jerry was pissed off. He was busy enough with coordinating shippings and ordering, so he couldn&#x27;t stand this kind of situation.</p><p>He thought of hiring an assistant for doing this job, but his manager said &quot;no&quot;.</p><h3 id="copy-is-all-what-you-need"><a href="#copy-is-all-what-you-need" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Copy is all what you need</h3><p>Suddenly, there was a corporate decision to change the format of the &quot;office equipment needs&quot; sheet.</p><p>Version 2 was rolled out.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token comment">//         ________ notice change: class into record</span>
</span><span class="code-line"><span class="token comment">//        /</span>
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">record</span> <span class="token class-name">OfficeEquipmentNeed_Version_2</span> <span class="token punctuation">{</span> <span class="token comment">/*...*/</span> <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">OfficeEquipmentNeeds</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">IReadOnlyList<span class="token punctuation">&lt;</span>OfficeEquipmentNeed_Version_2<span class="token punctuation">&gt;</span></span> Sheet <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token comment">/*...*/</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Jerry</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">OfficeEquipmentNeeds</span> OfficeEquipmentNeeds <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">void</span></span> <span class="token function">AddOfficeEquipmentNeed</span><span class="token punctuation">(</span><span class="token class-name">OfficeEquipmentNeed_Version_2</span> officeEquipmentNeed<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">/*...*/</span> <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>What&#x27;s more, Jerry decided to introduce one new rule: no possibility for adding anything to the list without Jerry&#x27;s knowledge.</p><p>Of course, people were able to ask about the existing needs - Jerry gave them the copy of such a sheet.</p><p>As they were using copies, no one was able to make jokes about pizza, etc.</p><p>Jerry was happy.</p><p>Even if an employee changed the copy, he had his own version.</p><p>But one thing he didn&#x27;t anticipate.</p><h3 id="any-pens"><a href="#any-pens" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Any pens?</h3><p>Turned out that people started abusing the information stored in each copy:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token comment">/*...*/</span>
</span><span class="code-line"><span class="token class-name">IReadOnlyList<span class="token punctuation">&lt;</span>OfficeEquipmentNeed_Version_2<span class="token punctuation">&gt;</span></span> sheetCopy <span class="token operator">=</span> needs<span class="token punctuation">.</span>Sheet<span class="token punctuation">;</span>
</span><span class="code-line"><span class="token class-name"><span class="token keyword">var</span></span> whoIsAnOfficeThief <span class="token operator">=</span> 
</span><span class="code-line">    sheetCopy
</span><span class="code-line">    <span class="token punctuation">.</span><span class="token function">Where</span><span class="token punctuation">(</span>need <span class="token operator">=&gt;</span> need<span class="token punctuation">.</span>Column <span class="token operator">==</span><span class="token operator">=</span> <span class="token number">6</span> <span class="token operator">&amp;&amp;</span> need<span class="token punctuation">.</span><span class="token function">Contains</span><span class="token punctuation">(</span><span class="token string">&quot;pen&quot;</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> need<span class="token punctuation">.</span>Count <span class="token operator">&gt;</span> <span class="token number">10</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">.</span><span class="token function">Select</span><span class="token punctuation">(</span>need <span class="token operator">=&gt;</span> need<span class="token punctuation">.</span>Requester<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">.</span><span class="token function">ToList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">await</span> <span class="token function">gossipAbout</span><span class="token punctuation">(</span>whoIsAnOfficeThief<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token comment">/*...*/</span>
</span></code></pre></div></div><p>Soon, Jerry and the famous &quot;thieves list&quot; were in the spotlight.</p><p>Other employees used other information too and they made decisions based on that:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token comment">/*...*/</span>
</span><span class="code-line"><span class="token class-name">IReadOnlyList<span class="token punctuation">&lt;</span>OfficeEquipmentNeed_Version_2<span class="token punctuation">&gt;</span></span> anotherSheetCopy <span class="token operator">=</span> needs<span class="token punctuation">.</span>Sheet<span class="token punctuation">;</span>
</span><span class="code-line"><span class="token class-name"><span class="token keyword">var</span></span> anyExpensiveEquipmentOrdered <span class="token operator">=</span> 
</span><span class="code-line">    anotherSheetCopy
</span><span class="code-line">    <span class="token punctuation">.</span><span class="token function">Any</span><span class="token punctuation">(</span>need <span class="token operator">=&gt;</span> 
</span><span class="code-line">        <span class="token punctuation">(</span>need<span class="token punctuation">.</span>Column <span class="token operator">==</span><span class="token operator">=</span> <span class="token number">10</span> <span class="token operator">||</span> need<span class="token punctuation">.</span>Column <span class="token operator">==</span><span class="token operator">=</span> <span class="token number">2</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token operator">&amp;&amp;</span> <span class="token punctuation">(</span>need<span class="token punctuation">.</span><span class="token function">Contains</span><span class="token punctuation">(</span><span class="token string">&quot;printer&quot;</span><span class="token punctuation">)</span> <span class="token operator">||</span> need<span class="token punctuation">.</span><span class="token function">Contains</span><span class="token punctuation">(</span><span class="token string">&quot;scanner&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">.</span><span class="token function">ToList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">if</span><span class="token punctuation">(</span>anyExpensiveEquipmentOrdered<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">await</span> <span class="token function">orderSomethingMoreExpensive</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line"><span class="token comment">/*...*/</span>
</span></code></pre></div></div><p>One problem solved, other problems added.</p><p>What was even worse, soon a new version was required, so Jerry changed it:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">record</span> <span class="token class-name">OfficeEquipmentNeed_Version_3</span> <span class="token punctuation">{</span> <span class="token comment">/*...*/</span> <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">OfficeEquipmentNeeds</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type">IReadOnlyList<span class="token punctuation">&lt;</span>OfficeEquipmentNeed_Version_3<span class="token punctuation">&gt;</span></span> Sheet <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token comment">/*...*/</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><h3 id="chaos-chaos-everywhere"><a href="#chaos-chaos-everywhere" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Chaos, chaos everywhere</h3><p>Introducing new version made things more complicated.</p><p>Some people used copies of the previous version (version 2), others tried to use copies of the new version (version 3).</p><p>Jerry needed to go to each desk and check what version is there, replace it in case of an outdated one.</p><p>He became massively delayed with ordering which impacted company&#x27;s KPIs.</p><p>Jerry&#x27;s manager was hugely disappointed that he couldn&#x27;t take his responsibility seriously.</p><h3 id="mind-your-own-business"><a href="#mind-your-own-business" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Mind your own business</h3><p>Jerry understood that even providing non-changeable copies didn&#x27;t solve the problem.</p><p>He became even more restrictive - no one is able to see his sheet.</p><p>&quot;Why they even need to know there is a sheet?!&quot; - he thought.</p><p>Jerry decided to change the strategy - he would accept a need in a very universal format so that later on he can make a decision how to deal with potential corporate format changes.</p><p>Also, he thought of changing the language, so that no one would tell him to &quot;add&quot; something to a sheet.</p><p>He taught others to &quot;request an equipment&quot;. As the language changed, the behaviors and results too.</p><p>Soon, people realized that a &quot;request&quot; might be rejected.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-cs code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Jerry</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">void</span></span> <span class="token function">RequestOfficeEquipment</span><span class="token punctuation">(</span><span class="token class-name">StandardOfficeEquipmentNeed</span> officeEquipmentNeed<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">/*...*/</span> <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Also Jerry had a little secret - there was no spoon, uhm, sorry - sheet.</p><p>At least a paper one. Jerry was very innovative so he decided to write a web application that will enable him to additionally generates raports, send notifications, etc.</p><p>Of course he deployed it to a multi-node Kubernetes cluster so that everything was scalable and ready for a production-grade traffic of a single user.</p><p>And no one even knew - Jerry was keeping this information for himself and even Jerry&#x27;s manager was amazed of the efficiency!</p><h3 id="details-of"><a href="#details-of" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Details of...?</h3><p>Encapsulation is one of the fundamental concepts in software engineering (generally in engineering too?).</p><p>In Object-Oriented Programming paradigm, encapsulation is typically used for protecting mutable state from being corrupted/changed externally (information hiding).</p><p>It also helps keeping the details of implementation hidden so that we might change our mind and use some different approach.</p><p>But what about Functional Programming paradigm? It is widely known that immutability is the one of its tenets.</p><p>OOP achieves &quot;state evolution&quot; through mutability (I tried to show differences in modeling in <a href="https://talesfrom.dev/blog/many-faces-of-ddd-aggregates-in-fsharp">Many faces of DDD Aggregates in F#</a> blogpost), whereas FP does it through immutability (is it not a &quot;state&quot; anymore?).</p><p>In OOP we <strong>must</strong> protect the mutable state so that it won&#x27;t get &quot;malformed&quot;, whereas in FP we are getting new one each time we apply some operation/behavior.</p><p>Does it mean that in FP we don&#x27;t need to &quot;hide the implementation&quot;?</p><h3 id="its-a-copy-but-still-a-detail"><a href="#its-a-copy-but-still-a-detail" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>It&#x27;s a copy, but still a detail!</h3><p>One could be a bit relaxed and toss immutable records here and there. Spill them all over the &quot;office&quot; (I meant codebase, but why I said &quot;the office&quot;? Please check <a href="https://talesfrom.dev/blog/organization-driven-design">&quot;Organization-Driven Design&quot;</a>).</p><p>Such information could always be discarded, in case of becoming corrupted.</p><p>But what happens if we decide to change the internal structure of such a record? Or change the way we are implementing some operation and other kind of information is needed?</p><p>As we saw with Jerry&#x27;s case, giving copies away resolves the problem partially. And it is not free from side-effects - &quot;people&quot; (functions, objects, etc.) might abuse/overuse copies (immutable records).</p><p>Even if we have immutability at our disposal, it&#x27;s good to use &quot;the second&quot; trait of encapsulation - implementation hiding. It will help us with localizing changes and building cohesive units (of what?).</p><p>This means that we shouldn&#x27;t be afraid of putting <code>private</code> modifiers (e.g. in F#, C# and TS) everywhere, use opaque types (you don&#x27;t know what I am talking about? Please check <a href="https://talesfrom.dev/blog/modeling-value-objects-in-typescript">Modeling Value Objects in TypeScript</a>) so that we are able control the details.</p><p>What&#x27;s more! We should be only using <code>private</code> modifiers and then question what is really needed to be visible publicly.</p><h3 id="to-abstract-or-to-encapsulate"><a href="#to-abstract-or-to-encapsulate" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>To abstract or to encapsulate?</h3><p>Wait, can one have encapsulation without abstraction? Or abstraction without encapsulation?</p><p>Ask a developer, you will get an answer.</p><p>Ask another one, you will get another answer.</p><p>For me, at the time of writing, those are two different things. And surely you can have one without another (and vice versa).</p><p>How?</p><p>As you probably recall, when Jerry realized that people need to <a href="#mind-your-own-business">&quot;mind their own business&quot;</a>, he did two things:</p><ul><li>he kept the &quot;sheet&quot; away from our sight</li><li>he changed the language of working with him (instead of &quot;adding&quot; he started using &quot;requesting&quot;)</li></ul><p>The main point of abstraction is to provide a certain language so that one can reason about on totally different level.</p><p>Reusability should not be the biggest &quot;selling point&quot; of abstraction (why? please check <a href="https://talesfrom.dev/blog/the-ambiguity-of-abstraction">The ambiguity of abstraction</a>). It might be a side-effect, but not the goal itself.</p><p>Could Jerry keep &quot;adding&quot; in his language, but hide the &quot;sheet&quot;?</p><p>Could Jerry change his language and use &quot;requesting&quot;, but leave the &quot;sheet&quot; visible and accesible?</p><p>Both concepts are tools for other kinds of problems.</p><h3 id="tell-dont-ask"><a href="#tell-dont-ask" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Tell, don&#x27;t ask</h3><p>Suddenly, when Jerry changed the language and when he made the details controlled by not mentioning the &quot;sheet&quot;, no one was able to ask him about the needs of other people.</p><p>He was again &quot;the boss&quot; of ordering. He decided which requests should be rejected and which poeple need to be warned that they might be seen as thieves (because of excessive number of pens requested).</p><p>So he accepted requests, but not all of them were turned into orders.</p><p>Be aware of change in terms of words used! (What to know what I am taking about? Please check <a href="https://talesfrom.dev/blog/software-engineering-for-busy-parents#6-do-not-start-with-the-persistence--three-aspects-of-modeling">Three aspects of modeling</a>)</p><p>A request <strong>might</strong> change into an order? That&#x27;s interesting - it sounds like we might actually using <a href="https://talesfrom.dev/blog/language-of-the-problem">Language of the problem</a>, isn&#x27;t it?</p><p>Nevertheless, from now on, Jerry doesn&#x27;t need to provide any details.</p><p>Of course, he can given answers to a various questions, but without telling how he knows about it. It&#x27;s again a combination of an abstraction (language) and details hiding (encapsulation).</p><p>Finally, Jerry got a responsibility assigned from his manager and he started operating in &quot;tell, don&#x27;t ask&quot; mode - &quot;tell me what you need and I will tell if it that&#x27;s possible&quot; (responsibility assignment? you might want to check <a href="https://talesfrom.dev/blog/a-solid-grasp-of-responsibility">A solid grasp of responsibility</a>).</p><h3 id="keep-everything-private-expose-only-whats-required"><a href="#keep-everything-private-expose-only-whats-required" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Keep everything private, expose only what&#x27;s required</h3><p>Even when you use code snippets from your favorite IDE - what class template does it use?</p><p>Are you getting public setters and getters by default?</p><p>When you create an object in TS - aren&#x27;t all properties mutable and visible?</p><p>We are begging for trouble from an early start. Create an environment that will support the habit of encapsulation - make your objects/functions/types ignorant, apathetic and selfish with help of your tools.</p><p>Once created, it&#x27;s hard to be changed - &quot;nah, I&#x27;m lazy, I might need it at some point&quot;.</p><p>It might look innocent, but without the discipline and the supervision it will soon become a problem.</p><p>The same applies to using primitives all down the way - <code>int</code>s, <code>string</code>s, <code>IEnumerable</code>s - it feels &quot;easy&quot; to use them and any other type or class might feel as &quot;overengineering&quot; or &quot;accidental complexity&quot;.</p><p>But aren&#x27;t we cheating ourselves? Aren&#x27;t we lying that things are that simplistic? Maybe we are afraid of <a href="https://talesfrom.dev/blog/the-cost-of-modeling">The cost of modeling</a>?</p>]]></content:encoded>
    <pubDate>Thu, 26 Jan 2023 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>programming</category><category>paradigms</category><category>grasp</category><category>problem-solving</category><category>solid</category><category>encapsulation</category><category>modeling</category><category>encapsulation</category><category>model</category><category>code</category><category>representations</category><category>principles</category><category>discipline</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/a-solid-grasp-of-responsibility</guid>
    <title>A solid grasp of responsibility</title>
    <link>https://talesfrom.dev/blog/a-solid-grasp-of-responsibility</link>
    <description>How to distribute responsibilities?</description>
    <content:encoded><![CDATA[<div class="bg-slate-600 rounded-xl "><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Attention!</span></div><div class="pb-2 px-3"><div class="break-words"><p>No person was harmed while preparing this blog post.</p></div></div></div> <div class="bg-slate-600 rounded-xl mt-10"><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Beware!</span></div><div class="pb-2 px-3"><div class="break-words"><p>Massive amount of conceptual code ahead, prepare!</p></div></div></div><h3 id="the-ministry-of-taste"><a href="#the-ministry-of-taste" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;The Ministry of Taste&quot;</h3><p>Meet Eddy.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">EddyTheTasteExpert</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Eddy is the expert in composing food so that the taste is splendid, marvelous and addictive.</p><p>He graduated from The University Of Taste (TUOT, you knew it, didn&#x27;t you?), worked with the most well-known chefs and other food experts in the world.</p><p>Living in various countries made him aware of the plethora of combinations, mixtures, and recipes.</p><p>He was tired of working in luxurious restaurants where only the profit mattered.</p><p>Eddy wanted to get challenges, to get freedom to decide about creative tastes.</p><p>That&#x27;s why he founded &quot;The Ministry of Taste&quot; startup.</p><p>The business model was fairly simple - a customer pays for getting custom, tasty dish based on description given.</p><p>How cool is that!</p><h3 id="sad-story"><a href="#sad-story" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Sad Story</h3><p>In fact, Eddy wasn&#x27;t interested in any business models - he wanted to think, sense, feel and respond with his vast experience to please the customer call for a splendid dish.</p><p>In his imagination, there was no chopping, cutting, boiling.</p><p>Just the pure, custom taste invention to give a heaven-like sensual experience for the customer.</p><p>Soon, Eddy was unsatisfied with the reality.</p><p>A part of his job was actual food experience design, but &quot;the boring stuff&quot; fell on his shoulders too.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">EddyTheTasteExpert</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">  <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">PrepareAndServeCustomizedDish</span><span class="token punctuation">(</span><span class="token class-name">TasteDescription</span> tasteDescription<span class="token punctuation">)</span>
</span><span class="code-line">  <span class="token punctuation">{</span> <span class="token comment">/*...*/</span> <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>He knew that to do what he love - discovering new taste recipes - he need to be stubborn and just do all the chopping, serving, etc.</p><p>But the part of his job wasn&#x27;t only sitting in the kitchen.</p><p>Eddy hated checking availability of the ingredients.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">EddyTheTasteExpert</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">  <span class="token comment">/* ...previous ones...*/</span>
</span><span class="code-line">
</span><span class="code-line">  <span class="token keyword">private</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>IngredientsAvailability<span class="token punctuation">&gt;</span></span> <span class="token function">CheckIngredientsAvailability</span><span class="token punctuation">(</span><span class="token class-name">TastyDishSuggestion</span> customizedTastyDishSuggestion<span class="token punctuation">)</span>
</span><span class="code-line">  <span class="token punctuation">{</span> <span class="token comment">/*...*/</span> <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Calling the nearby ingredients warehouses was driving him nuts.</p><p>But the worst non-food related activity was talking to the customer when there were no ingredients for the initial custom dish recommendation and no ingredients for the alternative dish (in case of the initial dish was impossible to be prepared because of the shortage on the ingredients).</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">EddyTheTasteExpert</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">  <span class="token comment">/* ...previous ones...*/</span>
</span><span class="code-line">
</span><span class="code-line">  <span class="token keyword">private</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>CustomerAnswer<span class="token punctuation">&gt;</span></span> <span class="token function">AskCustomerWhatToDo</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">  <span class="token punctuation">{</span> <span class="token comment">/*...*/</span> <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Then, depending on the customer answer, Eddy needed to do one of the following steps:</p><ul><li>return the money back</li><li>be creative and prepare highly creative taste, taking into account ingredients availability (actually, this is what Eddy loves!)</li><li>suggest a voucher for future visits</li></ul><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">EddyTheTasteExpert</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">  <span class="token comment">/* ...previous ones...*/</span>
</span><span class="code-line">
</span><span class="code-line">  <span class="token keyword">private</span> <span class="token class-name return-type">Task</span> <span class="token function">StartReturningMoney</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">  <span class="token punctuation">{</span> <span class="token comment">/*...*/</span> <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">  <span class="token keyword">private</span> <span class="token class-name return-type">TastyDishSuggestion</span> <span class="token function">RecommendCreativeCustomizedTastyDish</span><span class="token punctuation">(</span>
</span><span class="code-line">    <span class="token class-name">IngredientsAvailability</span> ingredientsAvailability<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">IngredientsAvailability</span> alternativeIngredientsAvailability
</span><span class="code-line">  <span class="token punctuation">)</span>
</span><span class="code-line">  <span class="token punctuation">{</span> <span class="token comment">/*...*/</span> <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">  <span class="token keyword">private</span> <span class="token class-name return-type">Task</span> <span class="token function">SuggestAVoucher</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">  <span class="token punctuation">{</span> <span class="token comment">/*...*/</span> <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>What&#x27;s more, each of the step required from Eddy being transparent and honest - meaning, Eddy needed to notify about the action taken.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">EddyTheTasteExpert</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">  <span class="token comment">/* ...previous ones...*/</span>
</span><span class="code-line">
</span><span class="code-line">  <span class="token keyword">private</span> <span class="token class-name return-type">Task</span> <span class="token function">NotifyAbout</span><span class="token punctuation">(</span><span class="token class-name">Notification</span> notification<span class="token punctuation">)</span>
</span><span class="code-line">  <span class="token punctuation">{</span> <span class="token comment">/*...*/</span> <span class="token punctuation">}</span>
</span><span class="code-line">  
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>You might be wondering - where is the food experience design? Where is Eddy&#x27;s gem hidden?</p><p>If everything was fine with the ingredients of the initial taste description or if the ingredients of an alternative dish were there, Eddy could do his virtuoso, masterpiece work and recommend the best food experience.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">EddyTheTasteExpert</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">  <span class="token comment">/* ...previous ones...*/</span>
</span><span class="code-line">  
</span><span class="code-line">  <span class="token keyword">private</span> <span class="token class-name return-type">TastyDishSuggestion</span> <span class="token function">RecommendAlternativeDishBasedOn</span><span class="token punctuation">(</span>
</span><span class="code-line">    <span class="token class-name">TasteDescription</span> tasteDescription<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">List<span class="token punctuation">&lt;</span>UnavailableIngredients<span class="token punctuation">&gt;</span></span> unavailableIngredients
</span><span class="code-line">  <span class="token punctuation">)</span>
</span><span class="code-line">  <span class="token punctuation">{</span> <span class="token comment">/*...*/</span> <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">  <span class="token keyword">private</span> <span class="token class-name return-type">TastyDishSuggestion</span> <span class="token function">RecommendTastyDishBy</span><span class="token punctuation">(</span><span class="token class-name">TasteDescription</span> tasteDescription<span class="token punctuation">)</span>
</span><span class="code-line">  <span class="token punctuation">{</span> <span class="token comment">/*...*/</span> <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Oh, there&#x27;s one interesting detail - Eddy was quite well-recognized persona in the cooking world so he had many &quot;important&quot; customers he needed to treat a bit differently.</p><p>People knew his creativity and sometimes folks were describing premium tastes - so Eddy needed to verify if they are VIP customers - because only VIP customers were allowed to ask for premium tastes.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">EddyTheTasteExpert</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">  <span class="token comment">/* ...previous ones...*/</span>
</span><span class="code-line">
</span><span class="code-line">  <span class="token keyword">private</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span><span class="token keyword">bool</span><span class="token punctuation">&gt;</span></span> <span class="token function">IsVipCustomer</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">  <span class="token punctuation">{</span> <span class="token comment">/*...*/</span> <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">  <span class="token keyword">private</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span><span class="token keyword">bool</span><span class="token punctuation">&gt;</span></span> <span class="token function">AnyPremiumTastes</span><span class="token punctuation">(</span><span class="token class-name">TasteDescription</span> tasteDescription<span class="token punctuation">)</span>
</span><span class="code-line">  <span class="token punctuation">{</span> <span class="token comment">/*...*/</span> <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>And finally, after all, Eddy needed to prepare the dish and serve it.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">EddyTheTasteExpert</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">  <span class="token comment">/* ...previous ones...*/</span>
</span><span class="code-line">
</span><span class="code-line">  <span class="token keyword">private</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>CustomizedTastyDish<span class="token punctuation">&gt;</span></span> <span class="token function">ServeDish</span><span class="token punctuation">(</span><span class="token class-name">CustomizedTastyDish</span> dish<span class="token punctuation">)</span>
</span><span class="code-line">  <span class="token punctuation">{</span> <span class="token comment">/*...*/</span> <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">  <span class="token keyword">private</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>CustomizedTastyDish<span class="token punctuation">&gt;</span></span> <span class="token function">PrepareDish</span><span class="token punctuation">(</span><span class="token class-name">TastyDishSuggestion</span> creativeTastyDishSuggestion<span class="token punctuation">)</span>
</span><span class="code-line">  <span class="token punctuation">{</span> <span class="token comment">/*...*/</span> <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Let&#x27;s sum up all the responsibilities that Eddy had on his shoulders:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">EddyTheTasteExpert</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">  <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">PrepareAndServeCustomizedDish</span><span class="token punctuation">(</span><span class="token class-name">TasteDescription</span> tasteDescription<span class="token punctuation">)</span>
</span><span class="code-line">  <span class="token punctuation">{</span> <span class="token comment">/*...*/</span> <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">  <span class="token keyword">private</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>IngredientsAvailability<span class="token punctuation">&gt;</span></span> <span class="token function">CheckIngredientsAvailability</span><span class="token punctuation">(</span><span class="token class-name">TastyDishSuggestion</span> customizedTastyDishSuggestion<span class="token punctuation">)</span>
</span><span class="code-line">  <span class="token punctuation">{</span> <span class="token comment">/*...*/</span> <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">  <span class="token keyword">private</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>CustomerAnswer<span class="token punctuation">&gt;</span></span> <span class="token function">AskCustomerWhatToDo</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">  <span class="token punctuation">{</span> <span class="token comment">/*...*/</span> <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">  <span class="token keyword">private</span> <span class="token class-name return-type">Task</span> <span class="token function">StartReturningMoney</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">  <span class="token punctuation">{</span> <span class="token comment">/*...*/</span> <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">  <span class="token keyword">private</span> <span class="token class-name return-type">TastyDishSuggestion</span> <span class="token function">RecommendCreativeCustomizedTastyDish</span><span class="token punctuation">(</span>
</span><span class="code-line">    <span class="token class-name">IngredientsAvailability</span> ingredientsAvailability<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">IngredientsAvailability</span> alternativeIngredientsAvailability
</span><span class="code-line">  <span class="token punctuation">)</span>
</span><span class="code-line">  <span class="token punctuation">{</span> <span class="token comment">/*...*/</span> <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">  <span class="token keyword">private</span> <span class="token class-name return-type">Task</span> <span class="token function">SuggestAVoucher</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">  <span class="token punctuation">{</span> <span class="token comment">/*...*/</span> <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">  <span class="token keyword">private</span> <span class="token class-name return-type">Task</span> <span class="token function">NotifyAbout</span><span class="token punctuation">(</span><span class="token class-name">Notification</span> notification<span class="token punctuation">)</span>
</span><span class="code-line">  <span class="token punctuation">{</span> <span class="token comment">/*...*/</span> <span class="token punctuation">}</span>
</span><span class="code-line">  
</span><span class="code-line">  <span class="token keyword">private</span> <span class="token class-name return-type">TastyDishSuggestion</span> <span class="token function">RecommendAlternativeDishBasedOn</span><span class="token punctuation">(</span>
</span><span class="code-line">    <span class="token class-name">TasteDescription</span> tasteDescription<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">List<span class="token punctuation">&lt;</span>UnavailableIngredients<span class="token punctuation">&gt;</span></span> unavailableIngredients
</span><span class="code-line">  <span class="token punctuation">)</span>
</span><span class="code-line">  <span class="token punctuation">{</span> <span class="token comment">/*...*/</span> <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">  <span class="token keyword">private</span> <span class="token class-name return-type">TastyDishSuggestion</span> <span class="token function">RecommendTastyDishBy</span><span class="token punctuation">(</span><span class="token class-name">TasteDescription</span> tasteDescription<span class="token punctuation">)</span>
</span><span class="code-line">  <span class="token punctuation">{</span> <span class="token comment">/*...*/</span> <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">  <span class="token keyword">private</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span><span class="token keyword">bool</span><span class="token punctuation">&gt;</span></span> <span class="token function">IsVipCustomer</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">  <span class="token punctuation">{</span> <span class="token comment">/*...*/</span> <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">  <span class="token keyword">private</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span><span class="token keyword">bool</span><span class="token punctuation">&gt;</span></span> <span class="token function">AnyPremiumTastes</span><span class="token punctuation">(</span><span class="token class-name">TasteDescription</span> tasteDescription<span class="token punctuation">)</span>
</span><span class="code-line">  <span class="token punctuation">{</span> <span class="token comment">/*...*/</span> <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">  <span class="token keyword">private</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>CustomizedTastyDish<span class="token punctuation">&gt;</span></span> <span class="token function">ServeDish</span><span class="token punctuation">(</span><span class="token class-name">CustomizedTastyDish</span> dish<span class="token punctuation">)</span>
</span><span class="code-line">  <span class="token punctuation">{</span> <span class="token comment">/*...*/</span> <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">  <span class="token keyword">private</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>CustomizedTastyDish<span class="token punctuation">&gt;</span></span> <span class="token function">PrepareDish</span><span class="token punctuation">(</span><span class="token class-name">TastyDishSuggestion</span> creativeTastyDishSuggestion<span class="token punctuation">)</span>
</span><span class="code-line">  <span class="token punctuation">{</span> <span class="token comment">/*...*/</span> <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Now you know why Eddy hated his job, don&#x27;t you?</p><h3 id="how-do-create-the-value"><a href="#how-do-create-the-value" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>How do create the value?</h3><p>What&#x27;s even more complicated is that Eddy needed to remember all the steps he need to perform in order to bring value to the customer - tasty, customized, and heavenly food.</p><p>Instead of focusing on the essence, immersing himself in the revolution of tastes, he needed to do &quot;the boring stuff&quot; - it was a drudgery.</p><h3 id="help-is-on-the-way"><a href="#help-is-on-the-way" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Help is on the way!</h3><p>How could we help poor Eddy?</p><p>What could we suggest doing, to relief the pain of doing &quot;the boring stuff&quot;?</p><p>We want to accelerate Eddy in his precious work so that he can save people from dull tastes!</p><p>Firstly, we need to understand all the steps Eddy needs to do.</p><p>Then we would be able to see what could be done.</p><h3 id="event-storming"><a href="#event-storming" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Event Storming</h3><p>Let&#x27;s imagine we figured out, collaboratively, together with Eddy, what he does to deliver the best food experience to his customers.</p><p>The outcome of such session is here:</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/event-storming.png" class="max-h-[30rem]"/></div><div class="italic mx-24">Food experience delivery process</div></div><p>Clearly, it is much more than just food experience design. It is food experience delivery, not only design.</p><p>After asking Eddy what are his desired main points of responsibility, he rapidly pointed at highlighted ones:</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/event-storming-eddys-desired-responsibility.png" class="max-h-[30rem]"/></div><div class="italic mx-24">Eddy&#x27;s desired responsibilities highlighted</div></div><p>It&#x27;s not hard to guess that Eddy does too much. He is simply overwhelmed and can&#x27;t focus on doing his best skill - food taste crafting.</p><p>Finally, here is the entire process that Eddy is responsible for:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">EddyTheTasteExpert</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">PrepareAndServeCustomizedDish</span><span class="token punctuation">(</span><span class="token class-name">TasteDescription</span> tasteDescription<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">await</span> <span class="token function">AnyPremiumTastes</span><span class="token punctuation">(</span>tasteDescription<span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token operator">!</span><span class="token keyword">await</span> <span class="token function">IsVipCustomer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">RegularCustomerAskingForPremiumTastesException</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> customizedTastyDishSuggestion <span class="token operator">=</span> <span class="token function">RecommendTastyDishBy</span><span class="token punctuation">(</span>tasteDescription<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> ingredientsAvailability <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">CheckIngredientsAvailability</span><span class="token punctuation">(</span>customizedTastyDishSuggestion<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">if</span> <span class="token punctuation">(</span>ingredientsAvailability<span class="token punctuation">.</span>SomeUnavailable<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token class-name"><span class="token keyword">var</span></span> alternativeTastyDishSuggestion <span class="token operator">=</span> <span class="token function">RecommendAlternativeDishBasedOn</span><span class="token punctuation">(</span>
</span><span class="code-line">                tasteDescription<span class="token punctuation">,</span> 
</span><span class="code-line">                ingredientsAvailability<span class="token punctuation">.</span>UnavailableIngredients
</span><span class="code-line">            <span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token class-name"><span class="token keyword">var</span></span> alternativeIngredientsAvailability <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">CheckIngredientsAvailability</span><span class="token punctuation">(</span>alternativeTastyDishSuggestion<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token keyword">if</span> <span class="token punctuation">(</span>alternativeIngredientsAvailability<span class="token punctuation">.</span>SomeUnavailable<span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token punctuation">{</span>
</span><span class="code-line">                <span class="token class-name"><span class="token keyword">var</span></span> customerAnswer <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">AskCustomerWhatToDo</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">                <span class="token keyword">if</span> <span class="token punctuation">(</span>customerAnswer<span class="token punctuation">.</span>ReturnMoney<span class="token punctuation">)</span>
</span><span class="code-line">                <span class="token punctuation">{</span>
</span><span class="code-line">                    <span class="token keyword">await</span> <span class="token function">NotifyAbout</span><span class="token punctuation">(</span>Notification<span class="token punctuation">.</span>MoneyReturn<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">                    <span class="token keyword">await</span> <span class="token function">StartReturningMoney</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">                <span class="token punctuation">}</span>
</span><span class="code-line">                <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>customerAnswer<span class="token punctuation">.</span>JustPrepareAnythingTasty<span class="token punctuation">)</span>
</span><span class="code-line">                <span class="token punctuation">{</span>
</span><span class="code-line">                    <span class="token keyword">await</span> <span class="token function">NotifyAbout</span><span class="token punctuation">(</span>Notification<span class="token punctuation">.</span>CreativeTasteDesign<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">                    <span class="token class-name"><span class="token keyword">var</span></span> creativeTastyDishSuggestion <span class="token operator">=</span> <span class="token function">RecommendCreativeCustomizedTastyDish</span><span class="token punctuation">(</span>
</span><span class="code-line">                        ingredientsAvailability<span class="token punctuation">,</span>
</span><span class="code-line">                        alternativeIngredientsAvailability
</span><span class="code-line">                    <span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">                    <span class="token class-name"><span class="token keyword">var</span></span> dish <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">PrepareDish</span><span class="token punctuation">(</span>creativeTastyDishSuggestion<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">                    <span class="token keyword">await</span> <span class="token function">ServeDish</span><span class="token punctuation">(</span>dish<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">                <span class="token punctuation">}</span>
</span><span class="code-line">                <span class="token keyword">else</span>
</span><span class="code-line">                <span class="token punctuation">{</span>
</span><span class="code-line">                    <span class="token keyword">await</span> <span class="token function">NotifyAbout</span><span class="token punctuation">(</span>Notification<span class="token punctuation">.</span>VoucherSuggestion<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">                    <span class="token keyword">await</span> <span class="token function">SuggestAVoucher</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">                <span class="token punctuation">}</span>
</span><span class="code-line">            <span class="token punctuation">}</span>
</span><span class="code-line">            <span class="token keyword">else</span>
</span><span class="code-line">            <span class="token punctuation">{</span>
</span><span class="code-line">                <span class="token keyword">await</span> <span class="token function">NotifyAbout</span><span class="token punctuation">(</span>Notification<span class="token punctuation">.</span>AlternativeDish<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">                <span class="token class-name"><span class="token keyword">var</span></span> dish <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">PrepareDish</span><span class="token punctuation">(</span>alternativeTastyDishSuggestion<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">                <span class="token keyword">await</span> <span class="token function">ServeDish</span><span class="token punctuation">(</span>dish<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token punctuation">}</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">        <span class="token keyword">else</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token class-name"><span class="token keyword">var</span></span> dish <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">PrepareDish</span><span class="token punctuation">(</span>customizedTastyDishSuggestion<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token keyword">await</span> <span class="token function">ServeDish</span><span class="token punctuation">(</span>dish<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span></code></pre></div></div><h3 id="ddd"><a href="#ddd" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>DDD</h3><p>We need to be clever here and apply DDD principle.</p><p>As you probably know (I hope you do), I am very much into DDD approach for solving problems (which sometimes ends up with producing software).</p><p>Unfortunately, this time I am talking about different DDD method - not Domain-Driven Design.</p><p>It&#x27;s a simple rule that says:</p><blockquote><p>Delegate, Delete, Do. &quot;Do&quot; is the last resort.</p></blockquote><p>We already know that Eddy can&#x27;t do everything, he&#x27;s simply not good at, e.g. talking to the warehouse folks.</p><p>Let&#x27;s imagine we talked to Eddy and he definitely said that all parts of the food experience delivery process must be there (so none can be deleted).</p><p>What are we left with?</p><p>Delegate.</p><h3 id="think-big-act-small"><a href="#think-big-act-small" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Think big, act small</h3><p>Turns out that the only thing we can do is to delegate some parts of the process so that Eddy can do what he really loves.</p><p>How?</p><p>We asked Eddy if he could ask his friends to help.</p><p>And that was a jackpot!</p><p>Turned out that thanks to Eddy&#x27;s massive network of known people, soon he found folks that would like to help him with his business!</p><p>In fact, business problems were secondary to Eddy, because we all know that he purely wanted to focus on the food experience design.</p><h3 id="the-ministry-of-taste-food-experience-delivery-crew"><a href="#the-ministry-of-taste-food-experience-delivery-crew" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;The Ministry of Taste&quot; food experience delivery crew</h3><p>After more sessions with Eddy (and other people from the startup), we established new way of assigning the responsibilities.</p><p>Event though it was a tiny company, multiple folks were happy to help!</p><p>It&#x27;s time to introduce the crew.</p><p>I think we should start with <code>ColeTheTasteExperienceDeliveryCoordinator</code>.</p><p>His main responsibility is to take care of handling orders and making sure that experience is delivered.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ColeTheTasteExperienceDeliveryCoordinator</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">HandleCustomizedDishOrder</span><span class="token punctuation">(</span><span class="token class-name">TasteDescription</span> tasteDescription<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> cirille <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">CirilleTheCustomerRelationshipManager</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">await</span> cirille<span class="token punctuation">.</span><span class="token function">AnyPremiumTastes</span><span class="token punctuation">(</span>tasteDescription<span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token operator">!</span><span class="token keyword">await</span> cirille<span class="token punctuation">.</span><span class="token function">IsVipCustomer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">RegularCustomerAskingForPremiumTastesException</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> eddy <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">EddyTheTasteExpert</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> will <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">WillFromTheWarehouse</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> fiona <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">FionaFromTheFrontDesk</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> cassidy <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">CassidyTheChef</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> walter <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">WalterTheWaiter</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> anna <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">AnnaTheAccountant</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> customizedTastyDishSuggestion <span class="token operator">=</span> eddy<span class="token punctuation">.</span><span class="token function">RecommendTastyDishBy</span><span class="token punctuation">(</span>tasteDescription<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> ingredientsAvailability <span class="token operator">=</span> <span class="token keyword">await</span> will<span class="token punctuation">.</span><span class="token function">CheckIngredientsAvailability</span><span class="token punctuation">(</span>customizedTastyDishSuggestion<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">if</span> <span class="token punctuation">(</span>ingredientsAvailability<span class="token punctuation">.</span>SomeUnavailable<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token keyword">await</span> <span class="token function">HandleRequestedTasteIngredientsUnavailable</span><span class="token punctuation">(</span>
</span><span class="code-line">                tasteDescription<span class="token punctuation">,</span>
</span><span class="code-line">                cirille<span class="token punctuation">,</span>
</span><span class="code-line">                eddy<span class="token punctuation">,</span>
</span><span class="code-line">                will<span class="token punctuation">,</span>
</span><span class="code-line">                fiona<span class="token punctuation">,</span>
</span><span class="code-line">                cassidy<span class="token punctuation">,</span>
</span><span class="code-line">                walter<span class="token punctuation">,</span>
</span><span class="code-line">                anna<span class="token punctuation">,</span>
</span><span class="code-line">                ingredientsAvailability<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">        <span class="token keyword">else</span>
</span><span class="code-line">        <span class="token punctuation">{</span>
</span><span class="code-line">            <span class="token class-name"><span class="token keyword">var</span></span> dish <span class="token operator">=</span> <span class="token keyword">await</span> cassidy<span class="token punctuation">.</span><span class="token function">PrepareDish</span><span class="token punctuation">(</span>customizedTastyDishSuggestion<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">            <span class="token keyword">await</span> walter<span class="token punctuation">.</span><span class="token function">ServeDish</span><span class="token punctuation">(</span>dish<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">/*...other actions...*/</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>You already know Eddy.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">EddyTheTasteExpert</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">internal</span> <span class="token class-name return-type">TastyDishSuggestion</span> <span class="token function">RecommendAlternativeDishBasedOn</span><span class="token punctuation">(</span>
</span><span class="code-line">      <span class="token class-name">TasteDescription</span> tasteDescription<span class="token punctuation">,</span>
</span><span class="code-line">      <span class="token class-name">List<span class="token punctuation">&lt;</span>UnavailableIngredients<span class="token punctuation">&gt;</span></span> unavailableIngredients
</span><span class="code-line">    <span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span><span class="token comment">/*...*/</span><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">internal</span> <span class="token class-name return-type">TastyDishSuggestion</span> <span class="token function">RecommendCreativeCustomizedTastyDish</span><span class="token punctuation">(</span>
</span><span class="code-line">      <span class="token class-name">IngredientsAvailability</span> ingredientsAvailability<span class="token punctuation">,</span>
</span><span class="code-line">      <span class="token class-name">IngredientsAvailability</span> alternativeIngredientsAvailability
</span><span class="code-line">    <span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span><span class="token comment">/*...*/</span><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">internal</span> <span class="token class-name return-type">TastyDishSuggestion</span> <span class="token function">RecommendTastyDishBy</span><span class="token punctuation">(</span><span class="token class-name">TasteDescription</span> tasteDescription<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span><span class="token comment">/*...*/</span><span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Eddy is finally happy. He can do only what he loves.</p><p>Now, say hi to <code>WillFromTheWarehouse</code>.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">WillFromTheWarehouse</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">internal</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>IngredientsAvailability<span class="token punctuation">&gt;</span></span> <span class="token function">CheckIngredientsAvailability</span><span class="token punctuation">(</span><span class="token class-name">TastyDishSuggestion</span> customizedTastyDishSuggestion<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span><span class="token comment">/*...*/</span><span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Will knows a lot of places where &quot;The Ministry of Taste&quot; can get the best quality ingredients.</p><p>Let&#x27;s go to <code>FionaFromTheFrontDesk</code> and greet her:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">FionaFromTheFrontDesk</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">internal</span> <span class="token class-name return-type">Task</span> <span class="token function">NotifyAbout</span><span class="token punctuation">(</span><span class="token class-name">Notification</span> notification<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span><span class="token comment">/*...*/</span><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">internal</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>CustomerAnswer<span class="token punctuation">&gt;</span></span> <span class="token function">AskCustomerWhatToDo</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span><span class="token comment">/*...*/</span><span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Her main responsibility is to support the customer along the food experience delivery.</p><p>Who do we have next? Ah yes, the ying-yang of the kitchen: <code>CassidyTheChef</code> and <code>WalterTheWaiter</code>:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">CassidyTheChef</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">internal</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>CustomizedTastyDish<span class="token punctuation">&gt;</span></span> <span class="token function">PrepareDish</span><span class="token punctuation">(</span><span class="token class-name">TastyDishSuggestion</span> creativeTastyDishSuggestion<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span><span class="token comment">/*...*/</span><span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">WalterTheWaiter</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">internal</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span>CustomizedTastyDish<span class="token punctuation">&gt;</span></span> <span class="token function">ServeDish</span><span class="token punctuation">(</span><span class="token class-name">CustomizedTastyDish</span> dish<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span><span class="token comment">/*...*/</span><span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>We should not forget <code>AnnaTheAccountant</code> who makes entire wheel spinning!</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">AnnaTheAccountant</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">internal</span> <span class="token class-name return-type">Task</span> <span class="token function">StartReturningMoney</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token comment">/*...*/</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>In the food experience delivery, she&#x27;s very focused on her single job.</p><p>Is there anyone left?</p><p><code>CirilleTheCustomerRelationshipManager</code>, very busy and important guy!</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">CirilleTheCustomerRelationshipManager</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">internal</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span><span class="token keyword">bool</span><span class="token punctuation">&gt;</span></span> <span class="token function">IsVipCustomer</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span><span class="token comment">/*...*/</span><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">internal</span> <span class="token class-name return-type">Task<span class="token punctuation">&lt;</span><span class="token keyword">bool</span><span class="token punctuation">&gt;</span></span> <span class="token function">AnyPremiumTastes</span><span class="token punctuation">(</span><span class="token class-name">TasteDescription</span> tasteDescription<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span><span class="token comment">/*...*/</span><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">internal</span> <span class="token class-name return-type">Task</span> <span class="token function">SuggestAVoucher</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span><span class="token comment">/*...*/</span><span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Here&#x27;s the summary who belongs to the team:</p><ul><li><code>AnnaTheAccountant</code></li><li><code>ColeTheTasteExperienceDeliveryCoordinator</code></li><li><code>CirilleTheCustomerRelationshipManager</code></li><li><code>CassidyTheChef</code></li><li><code>EddyTheTasteExpert</code></li><li><code>FionaFromTheFrontDesk</code></li><li><code>WalterTheWaiter</code></li><li><code>WillFromTheWarehouse</code></li></ul><p>I think it&#x27;s worth checking how do they collaborate to handle other scenarios from our delivery process.</p><h3 id="scarce-ingredients"><a href="#scarce-ingredients" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Scarce ingredients</h3><p>There are two scenarios that were painful just for Eddy - where there are no ingredients - both for initial dish and for alternative dish.</p><p>He really hated those. Here&#x27;s how <code>HandleRequestedTasteIngredientsUnavailable</code> looks like:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">private</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">HandleRequestedTasteIngredientsUnavailable</span><span class="token punctuation">(</span>
</span><span class="code-line">    <span class="token class-name">TasteDescription</span> tasteDescription<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">CirilleTheCustomerRelationshipManager</span> cirille<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">EddyTheTasteExpert</span> eddy<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">WillFromTheWarehouse</span> will<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">FionaFromTheFrontDesk</span> fiona<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">CassidyTheChef</span> cassidy<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">WalterTheWaiter</span> walter<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">AnnaTheAccountant</span> anna<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token class-name">IngredientsAvailability</span> ingredientsAvailability<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> alternativeTastyDishSuggestion <span class="token operator">=</span> eddy<span class="token punctuation">.</span><span class="token function">RecommendAlternativeDishBasedOn</span><span class="token punctuation">(</span>
</span><span class="code-line">        tasteDescription<span class="token punctuation">,</span>
</span><span class="code-line">        ingredientsAvailability<span class="token punctuation">.</span>UnavailableIngredients
</span><span class="code-line">    <span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> alternativeIngredientsAvailability <span class="token operator">=</span> 
</span><span class="code-line">        <span class="token keyword">await</span> will<span class="token punctuation">.</span><span class="token function">CheckIngredientsAvailability</span><span class="token punctuation">(</span>alternativeTastyDishSuggestion<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">if</span> <span class="token punctuation">(</span>alternativeIngredientsAvailability<span class="token punctuation">.</span>SomeUnavailable<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">await</span> <span class="token function">HandleAlternativeTasteIngredientsUnavailable</span><span class="token punctuation">(</span>
</span><span class="code-line">            ingredientsAvailability<span class="token punctuation">,</span>
</span><span class="code-line">            alternativeIngredientsAvailability<span class="token punctuation">,</span>
</span><span class="code-line">            cirille<span class="token punctuation">,</span>
</span><span class="code-line">            eddy<span class="token punctuation">,</span>
</span><span class="code-line">            fiona<span class="token punctuation">,</span>
</span><span class="code-line">            cassidy<span class="token punctuation">,</span>
</span><span class="code-line">            walter<span class="token punctuation">,</span>
</span><span class="code-line">            anna<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">else</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">await</span> fiona<span class="token punctuation">.</span><span class="token function">NotifyAbout</span><span class="token punctuation">(</span>Notification<span class="token punctuation">.</span>AlternativeDish<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> dish <span class="token operator">=</span> <span class="token keyword">await</span> cassidy<span class="token punctuation">.</span><span class="token function">PrepareDish</span><span class="token punctuation">(</span>alternativeTastyDishSuggestion<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">await</span> walter<span class="token punctuation">.</span><span class="token function">ServeDish</span><span class="token punctuation">(</span>dish<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Everyone does his or her job in the best possible way and <code>ColeTheTasteExperienceDeliveryCoordinator</code> ensures that everything is in the right order.</p><p>We should also check more &quot;interesting&quot; case, namely <code>HandleAlternativeTasteIngredientsUnavailable</code>:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">async</span> <span class="token class-name return-type">Task</span> <span class="token function">HandleAlternativeTasteIngredientsUnavailable</span><span class="token punctuation">(</span>
</span><span class="code-line">        <span class="token class-name">IngredientsAvailability</span> ingredientsAvailability<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">IngredientsAvailability</span> alternativeIngredientsAvailability<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">CirilleTheCustomerRelationshipManager</span> cirille<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">EddyTheTasteExpert</span> eddy<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">FionaFromTheFrontDesk</span> fiona<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">CassidyTheChef</span> cassidy<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">WalterTheWaiter</span> walter<span class="token punctuation">,</span>
</span><span class="code-line">        <span class="token class-name">AnnaTheAccountant</span> anna<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> customerAnswer <span class="token operator">=</span> <span class="token keyword">await</span> fiona<span class="token punctuation">.</span><span class="token function">AskCustomerWhatToDo</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">if</span> <span class="token punctuation">(</span>customerAnswer<span class="token punctuation">.</span>ReturnMoney<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">await</span> fiona<span class="token punctuation">.</span><span class="token function">NotifyAbout</span><span class="token punctuation">(</span>Notification<span class="token punctuation">.</span>MoneyReturn<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">await</span> anna<span class="token punctuation">.</span><span class="token function">StartReturningMoney</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>customerAnswer<span class="token punctuation">.</span>JustPrepareAnythingTasty<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">await</span> fiona<span class="token punctuation">.</span><span class="token function">NotifyAbout</span><span class="token punctuation">(</span>Notification<span class="token punctuation">.</span>CreativeTasteDesign<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> creativeTastyDishSuggestion <span class="token operator">=</span> eddy<span class="token punctuation">.</span><span class="token function">RecommendCreativeCustomizedTastyDish</span><span class="token punctuation">(</span>
</span><span class="code-line">            ingredientsAvailability<span class="token punctuation">,</span>
</span><span class="code-line">            alternativeIngredientsAvailability
</span><span class="code-line">        <span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token class-name"><span class="token keyword">var</span></span> dish <span class="token operator">=</span> <span class="token keyword">await</span> cassidy<span class="token punctuation">.</span><span class="token function">PrepareDish</span><span class="token punctuation">(</span>creativeTastyDishSuggestion<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">await</span> walter<span class="token punctuation">.</span><span class="token function">ServeDish</span><span class="token punctuation">(</span>dish<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token keyword">else</span>
</span><span class="code-line">    <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">await</span> fiona<span class="token punctuation">.</span><span class="token function">NotifyAbout</span><span class="token punctuation">(</span>Notification<span class="token punctuation">.</span>VoucherSuggestion<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        <span class="token keyword">await</span> cirille<span class="token punctuation">.</span><span class="token function">SuggestAVoucher</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>This is the most collaborative part of their work. It looks like an orchestra - and everything is done to get the best possible (and addictive) food experience.</p><h3 id="what-the-hell-have-just-happened"><a href="#what-the-hell-have-just-happened" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What the hell have just happened?!</h3><p>Believe me, my fingers hurt. But going back to the point!</p><p>Well, we brought happiness to the world and removed some pain and suffering. Our fellow food experience designer, Eddy, is massively overjoyed right now!</p><p>So what was the actual problem that Eddy had?</p><p>He was massively overwhelmed. He didn&#x27;t mention it, but he was close to quitting his startup dream.</p><p>Eddy simply did to much and got drowned in remembering all the bits and pieces.</p><p>We was the artist of taste - how the hell could he know every detail about returning money or vouchers?</p><p>In fact, he was a little bit egoistic - he just wanted to focus on things he was good at.</p><p>But, is it really a bad thing?</p><h3 id="responsibilities-assignment"><a href="#responsibilities-assignment" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Responsibilities assignment</h3><p>After understanding the problem (I can&#x27;t stress how important understanding the problem is!), we went into exploration mode and thanks to Event Storming we got the feeling of the process.</p><p>Clear signals from Eddy, that he didn&#x27;t want other responsibilities than food experience design, guided us into the responsibilities assignment task.</p><p>Initially, Eddy was responsible for:</p><ul><li>knowing when to suggest a voucher</li><li>deciding what to do when there are no ingredients</li><li>doing the dish preparation</li><li>doing the dish serving</li><li>knowing what taste to recommend</li><li>deciding how to respond to customer&#x27;s answer</li><li>and so on.</li></ul><p>He got too many responsibilities assigned to himself.</p><h3 id="driving-the-design-through-responsibilities"><a href="#driving-the-design-through-responsibilities" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Driving the design through responsibilities</h3><p>Turns out Rebecca Wirfs Brock already figured out that thinking about responsibilities is so important when we design our systems. She coined the term &quot;Responsibility-Driven Design&quot; (you should definitely read her book, it&#x27;s <b>a w e s o m e</b>!)</p><p>We could generalize and say that there are three major types of responsibilities. One could say that &quot;people&quot; might be responsible for:</p><ul><li>doing</li><li>knowing</li><li>deciding</li></ul><p>Referring to the &quot;Responsibility-Driven Design&quot;, a responsibility could be defined as &quot;a contract or an obligation&quot; for doing/knowing/deciding.</p><p>Having such a mindset, collaborating &quot;people&quot; are giving or taking services, based on a contract or an obligation. (Why do I say &quot;people&quot;? Please check <a href="https://talesfrom.dev/blog/organization-driven-design">&quot;Organization-Driven Design&quot;</a>)</p><p>In other words, some &quot;people&quot; expect a certain level of service, knowing the provided contract.</p><h3 id="distribute-the-responsibilities"><a href="#distribute-the-responsibilities" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Distribute the responsibilities!</h3><p>Craig Larman, in his great book &quot;Applying UML and Patterns&quot;, presented an approach for designing software: <strong>G</strong>eneral <strong>R</strong>esponsibility <strong>A</strong>ssignment <strong>S</strong>oftware <strong>P</strong>rinciples - GRASP.</p><p>So yet again, responsibilities, and their proper distribution, is the key element.</p><p>What might be implicit here, is focus on the <strong>behavior</strong>. What &quot;a person&quot; can do. What service can be provided by it.</p><p>And if we now recall &quot;The Ministry of Taste&quot; crew - each &quot;person&quot; could contribute with a very precise set of skills - meaning, &quot;behaviors&quot;.</p><p>No discussion about data structures, statuses - only about responsibilities, contracts and operations. (if you are curious why I specified statuses? Please check <a href="https://talesfrom.dev/blog/bool-considered-harmful">Bool considered harmful?</a>). These are secondary, as the behavior is defining them. (Why secondary? Please check <a href="https://talesfrom.dev/blog/the-cost-of-modeling">The cost of modeling</a> and/or <a href="https://talesfrom.dev/blog/language-of-the-problem">Language of the problem</a>).</p><h3 id="solid-grasp-of-responsibility"><a href="#solid-grasp-of-responsibility" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>SOLID GRASP of Responsibility</h3><p>In fact, the first letter in <strong>S</strong>OLID stands for &quot;Single Responsibility Principle&quot;.</p><p>It suits nicely the cluster of best practices, harvested during building the commercial software. I have a feeling that it&#x27;s not the major focus on SOLID.</p><p>The topic of &quot;responsibility&quot; is a part of SOLID, but in &quot;only&quot; 1/5 (I know, such quantification is so shabby), whereas GRASP and RDD are both all about responsibility.</p><p>Don&#x27;t get me wrong, I am not devaluing or disregarding SOLID, it contributed so much to many people in our industry (at the same time doing some harm).</p><p>What I try to explore and suggest here is to go further with &quot;single responsibility&quot; and jump into RDD and GRASP, to broaden the understanding.</p><p>Seems like in most cases (every time?) it boils down to distributing doing/knowing/deciding responsibilities.</p><h3 id="software-design-from-human-perspective"><a href="#software-design-from-human-perspective" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Software Design from human perspective</h3><p>As Dan North wrote in the blog post about <a href="https://dannorth.net/2022/02/10/cupid-for-joyful-coding/">CUPID</a></p><blockquote><p>To be human, properties need to read from the perspective of people, not code. CUPID is about what it feels like to work with code, not an abstract description of code in itself.</p></blockquote><p>One could sum up that Responsibility-Driven Design and GRASP focus on responsibilities - as they are &quot;assigned&quot; to various &quot;people&quot; (collaborators), they need to agree what is expected from them and what they can expect from others.</p><p>Does it resemble how people organize themselves to work collaboratively toward a bigger goal?</p><h3 id="design-drama"><a href="#design-drama" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Design Drama</h3><p>What if we could play how our software components would interact so that we see if it makes sense?</p><p>You probably (I hope so) heard about so-called <a href="https://en.wikipedia.org/wiki/Class-responsibility-collaboration_card">CRC cards</a> - (Candidate) <strong>C</strong>lass - <strong>R</strong>esponsibilities - <strong>C</strong>ollaborators.</p><p>Briefly, they were used as a method for conceptual modeling and design. By assiging various roles to the people inside of the room/in the team, we would be able to see how they interact with each other, see bottlenecks or possible problems.</p><p>Going back to the merit, yet again, &quot;responsibilities&quot; are mentioned. Not data structures, not statuses - &quot;what can you do for me?&quot;.</p><h3 id="the-trinity-of-responsibility-types"><a href="#the-trinity-of-responsibility-types" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The Trinity of Responsibility Types</h3><p>One could arrive at interesting observation - assigning mentioned &quot;fundamental&quot; responsibilities creates three roles:</p><ul><li>information expert (knowing/deciding)</li><li>executor or doer (doing)</li><li>coordinator (deciding/knowing)</li></ul><p>Such roles can be found on various levels, for instance on application level (F# functions or C# classes) or architecture level (services).</p><p>This might sound a bit &quot;theoretical&quot;, but spend some time in your current project and try to identify roles, hence responsibilities.</p><p>Can they be classified with those three &quot;fundamental&quot; ones?</p><h3 id="software-design--responsibility-assignment"><a href="#software-design--responsibility-assignment" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Software Design = Responsibility Assignment?</h3><p>Our job as a software architects or software engineers is to design the solution for a particular problem, operating within a specific context.</p><p>We went through a journey - we started with a large and overwhelming set of mixed responsibilities, put on a single &quot;person&quot;.</p><p>Finally, we ended up with nicely segregated responsibilities.</p><p>It wasn&#x27;t &quot;free&quot; or &quot;easy&quot; - it required learning and reflection.</p><p>We might &quot;lie&quot; to ourselves that understanding will magically pop-up or become &quot;visible&quot; out of the box.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Programming is fun, but developing high quality software is hard.</p></div></div></div><p>I believe it really matters how we think about the surrounding world - what metaphors we use (consciously or subconsciously) - including software engineering and software design.</p><p>We are very skilled in reasoning about people, their stories and people topologies - that&#x27;s possibly why &quot;playing&quot; the roles of &quot;objects&quot; was so damn useful and effective.</p><p><a href="https://talesfrom.dev/blog/conversation-driven-design">Conversation-Driven Design</a>, <a href="https://talesfrom.dev/blog/organization-driven-design">&quot;Organization-Driven Design&quot;</a> or <a href="https://talesfrom.dev/blog/microoffices-vs-officeolith">&quot;Microoffices&quot; vs &quot;Officeolith&quot;</a> might be a nice extension for this kind of reasoning.</p><p>Treating software components as collaborating experts, each having defined responsibility (according to the contract), working inside of an organization, might be an interesting &quot;routine thinking&quot; break.</p><h3 id="questions"><a href="#questions" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Questions</h3><p>Final and closing words - let&#x27;s have some additional questions to broaden the example:</p><ul><li>Could &quot;The Ministry of Taste&quot; crew do the same or a better job without <code>ColeTheTasteExperienceDeliveryCoordinator</code>?</li><li>Is returning money back need to happen &quot;immediately&quot;? Could it be done a bit later?</li><li>Does the work of <code>CassidyTheChef</code> and <code>WalterTheWaiter</code> be coordinated or could they just &quot;shout&quot; loudly, expressing what happened?</li><li>Who needs to &quot;be in the same room&quot;? Does it make sense for <code>FionaFromTheFrontDesk</code> to &quot;sit&quot; together with <code>WillFromTheWarehouse</code>?</li><li>Who should be responsible for calling customers and inviting them for &quot;Tasty Jam Session&quot;?</li></ul>]]></content:encoded>
    <pubDate>Sat, 21 Jan 2023 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>programming</category><category>paradigms</category><category>problem-solving</category><category>language</category><category>learning</category><category>model</category><category>modeling</category><category>domain-driven-design</category><category>responsibility-driven design</category><category>GRASP</category><category>SOLID</category><category>software design</category><category>software engineering</category><category>metaphors</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/slow-down</guid>
    <title>Slow down</title>
    <link>https://talesfrom.dev/blog/slow-down</link>
    <description>How to gain speed by slowing down?</description>
    <content:encoded><![CDATA[<h3 id="its-a-nonsense"><a href="#its-a-nonsense" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>It&#x27;s a nonsense</h3><p>There are seventeen youtube videos waiting in the &quot;to watch queue&quot;.</p><p>Books are piling up mercilessly.</p><p>New tool here, new tool there.</p><p>Take a breath. Observe.</p><p>And then a random guy (me) posted a clustered group of pixels, viewed as characters by our eyes (brain?), on twitter, referring to this post. Yet another article to read?</p><p>The title isn&#x27;t helping - &quot;what a BS, slowing down?&quot;</p><p>Did I go crazy or something?</p><h3 id="the-non-renewable-resource"><a href="#the-non-renewable-resource" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The non-renewable resource</h3><p>The perception of time is a massively interesting topic (the perception itself is interesting too!), there are vast number of perspectives and symbols how time can be represented (modeled?).</p><p>One of such views is the time as a resource - something you are not able to produce yourself.</p><p>In theory you can&#x27;t, in practice you can, but you need other people, machines, intelligence and so forth.</p><p>Typically in IT business, we want to optimize the usage of this resource to quickly deliver the value to our users by shipping software so that we can gain the feedback.</p><p>The shorter the feedback loop, the faster we can learn.</p><p>The faster we can learn, the more adjustments and actions we can do.</p><p>One could say that&#x27;s what Agile mindset strives for (What is agility? How does it position itself against fragility? Please check <a href="https://talesfrom.dev/blog/fragile">(Fr)Agile</a>)</p><p>Speed is good, isn&#x27;t it?</p><h3 id="attention"><a href="#attention" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Attention!</h3><p>As always, everything is contextual. All need to obey the laws of The King of All Kings - The Context.</p><p>The same is with the time.</p><p>In <a href="https://talesfrom.dev/blog/fragile">(Fr)Agile</a>, I wanted to convey a message that ceremonies without understanding of the problem we are working on, thinking how to properly (what does it mean?) distribute responsibilities, will only make us fragile, rather than agile.</p><p>And for sure we&#x27;re going to specify those responsibilities, draw boundaries incorrectly, at some point, even initially.</p><p>So we shouldn&#x27;t trap ourselves in so-called &quot;analysis paralysis&quot;. This might lead to another &quot;dreaded&quot; beast named as &quot;big analysis upfront&quot;.</p><p>(it&#x27;s funny that we humans tend to slide from one extrema to another extrema, but that&#x27;s a topic for another tale.)</p><p>Nevertheless, who are the friends of the analysis? Knowledge and understanding.</p><p>I like Feynman&#x27;s perspective on knowledge:</p><div class="flex justify-center items-center"><img src="https://talesfrom.dev/static/images/knowledge.png"/></div><p>So to gain the knowledge, to explore the topic, and to build up intuition, understanding - we need to <strong>pay</strong> (with) our attention.</p><p>We need to use our non-renewable resource in order to decompose the problem so that later we would be able to compose, but this time <strong>knowing</strong>.</p><p>The final composition will be the act of design. Crafting the subsystems so that their collaboration brings something bigger than the sum of them. The system (which is a subsystem of another system, etc.).</p><p>But this needs...Attention.</p><h3 id="the-time---the-apex-predator-of-the-design"><a href="#the-time---the-apex-predator-of-the-design" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The time - the apex predator of the design</h3><p>I love how <a href="https://grugbrain.dev">The Grug, Brained Developer</a> stated:</p><blockquote><p>apex predator of grug is complexity</p></blockquote><p>Any <em>complexity</em>? I believe our fellow Grug was talking about the accidental complexity, which is limitless (What am I talking about? Please check <a href="https://talesfrom.dev/blog/essentially-bounded-accidentally-unlimited">Essentially bounded, accidentally unlimited</a>).</p><p>Still we are left with essential complexity, the nature of the problem we are working with.</p><p>To properly understand what a beast are we going to dance with, we need time.</p><p>We need to focus on learning, building up the confidence so that we would be able to change our mind later on, when the level of ignorance will go down.</p><p>But again, it&#x27;s a cost.</p><p>To understand how subsystems, or &quot;boxes&quot;, collaborate, so then later we can assign responsibilities - it requires our time.</p><p>This sounds a bit contradictory to be fast, isn&#x27;t it?</p><h3 id="slow-down-to-be-fast"><a href="#slow-down-to-be-fast" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Slow down to be fast?</h3><p>Dissecting bigger subsystems into smaller subsystems is here for quite a long time (pun intended). (You don&#x27;t have time, because of learning next gen framework? Please check <a href="https://talesfrom.dev/blog/software-engineering-for-busy-parents">Software Engineering for busy parents</a>)</p><p>Specifying how they need to work together, organize themselves, so that they achieve the overall goal - isn&#x27;t it how we, humans, operate? (Are software components like humans? You can read more here <a href="https://talesfrom.dev/blog/organization-driven-design">&quot;Organization-Driven Design&quot;</a>)</p><p>Exploring the problem by specifying the contractors, the nature of their collaboration, is a pure learning exercise, experimenting with various models.</p><p>Of course I am talking about TDD (Why did I use &quot;specifying&quot;? Please check <a href="https://talesfrom.dev/blog/the-ambiguity-of-tdd">&quot;The ambiguity&quot; of TDD</a>).</p><p>Writing the specification declaratively, before any &quot;behavior&quot; happens.</p><p>We don&#x27;t know <strong>how</strong> things are going to work, but we need to pay attention on the observable behavior.</p><p>It literally slows us down, because no production code is written until we imagine what we want to get out of it.</p><p>And I consider it as a good thing.</p><p>I believe that this understanding is what we often miss. It&#x27;s easier to add &quot;just another if&quot;, &quot;new private method&quot; or whatever we need do to achieve &quot;done&quot; status of our task.</p><p>Slowing down, devoting time to build up the internal model of the problem in our heads, is crucial to move fast later on.</p><p>Especially in times when everything is bubbling up so rapidly, shouting to get your attention even louder than before.</p><h3 id="what-are-you-optimizing-for"><a href="#what-are-you-optimizing-for" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What are you optimizing for?</h3><p>There are a lot of pitfalls and potential traps a TDD practitioner can set up for oneself.</p><p>But testability of a subsystem is a widely advocated trait that when pursued, should pay off quite soon.</p><p>I like the statement from <a href="https://www.amazon.com/Effective-Software-Testing-developers-guide/dp/1633439933">&quot;Effective Software Testing: A developer&#x27;s guide&quot;</a>:</p><blockquote><p>Some developers argue that designing for testability is harder and costs too many extra lines of code. This may be true. Writing spaghetti code is easier than developing cohesive classes that collaborate and are easily tested</p></blockquote><p>Working toward testability (&quot;replaceability&quot; or &quot;removability&quot; - it has different names) costs, but what do we really optimize for? For the lowest number of keystrokes? For not too many classes or functions?</p><p>The currency is time and &quot;frustration&quot; might pop up - suddenly we are forced (by ourselves) to <strong>think</strong>, to analyze, to pose various questions.</p><p>Be slow to get flow.</p><p>Is it easy? Oh no. It&#x27;s so entertaining to grab your IDE and start typing keywords of your favorite language, but as it was written in <a href="https://www.amazon.com/Applying-UML-Patterns-Introduction-Object-Oriented/dp/0131489062">Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development</a>:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Programming is fun, but developing high quality software is hard.</p></div></div></div><p>High quality software is &quot;hard&quot; to achieve, because you need to pay (with) attention.</p><p>We can&#x27;t ran away from putting the effort in decomposition, design, composition. How much time you will or can &quot;pay&quot; depends on the...Context.</p><p>Investing &quot;time coins&quot; in problem exploration, solution exploration (some models are going to be thrown away!) the readibility of the code, &quot;just-enough&quot; design (which means <strong>some</strong> design!) - I believe this is what we should put attention to (pun intended).</p><p>To be prepared for the flow of changes we need to learn, slowly.</p><p>Slow.</p><p>Down.</p>]]></content:encoded>
    <pubDate>Mon, 09 Jan 2023 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>programming</category><category>paradigms</category><category>problem-solving</category><category>language</category><category>learning</category><category>model</category><category>modeling</category><category>domain-driven-design</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/bool-considered-harmful</guid>
    <title>Bool considered harmful?</title>
    <link>https://talesfrom.dev/blog/bool-considered-harmful</link>
    <description>Can bool be considered as non-modeling friendly?</description>
    <content:encoded><![CDATA[<div class="bg-slate-600 rounded-xl mb-10"><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Attention!</span></div><div class="pb-2 px-3"><div class="break-words"><p>This article is based on the conversation I had with a fellow craftsman, a friend of mine - <a href="https://twitter.com/PrzemekWolnik">Przemek Wolnik</a></p>
<p>Kudos to Przemek!</p></div></div></div> <div class="bg-slate-600 rounded-xl "><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Attention!</span></div><div class="pb-2 px-3"><div class="break-words"><p>No bool was harmed during writing this article.</p></div></div></div><h3 id="can-nothing-be-active"><a href="#can-nothing-be-active" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Can nothing be active?</h3><p>Imagine we have the following problem in front of us: we are getting a collection of users that has the following shape:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">User</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">readonly</span> name<span class="token operator">:</span> <span class="token builtin">string</span>
</span><span class="code-line">    <span class="token keyword">readonly</span> isActive<span class="token operator">:</span> <span class="token builtin">boolean</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>We need to check that current collection contains only active users. Seems easy, we need to write a simple function - let&#x27;s name it <code>areAllUsersActive</code>.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">const</span> <span class="token function function-variable">isActive</span> <span class="token operator">=</span> <span class="token punctuation">(</span>user<span class="token operator">:</span> User<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> user<span class="token punctuation">.</span>isActive
</span><span class="code-line"><span class="token keyword">const</span> <span class="token function function-variable">areAllUsersActive</span> <span class="token operator">=</span> 
</span><span class="code-line">    <span class="token punctuation">(</span>users<span class="token operator">:</span> User<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> users<span class="token punctuation">.</span><span class="token function">every</span><span class="token punctuation">(</span>isActive<span class="token punctuation">)</span>
</span></code></pre></div></div><p>So far, so good.</p><p>We are utilizing this function in another level, e.g. to send some Christmas gifts.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">function</span> <span class="token function">handleSendingChristmasGifts</span><span class="token punctuation">(</span>users<span class="token operator">:</span> User<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token function">areAllUsersActive</span><span class="token punctuation">(</span>users<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token keyword">const</span> giftsDelivery <span class="token operator">=</span> <span class="token function">startGiftsDeliveryProcess</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// 👈 very expensive operation!</span>
</span><span class="code-line">        <span class="token keyword">const</span> deliveries <span class="token operator">=</span> giftsDelivery<span class="token punctuation">.</span><span class="token function">to</span><span class="token punctuation">(</span>users<span class="token punctuation">)</span> <span class="token comment">// all users will get happiness and joy</span>
</span><span class="code-line">        <span class="token function">trackDeliveries</span><span class="token punctuation">(</span>deliveries<span class="token punctuation">)</span> <span class="token comment">// we track what is the state of delivering joy and happiness</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">    <span class="token comment">// ... some other important stuff</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Turns out that to deliver happiness and joy, we need to start a special process. It is quite expensive (resource-wise: money, time, CPU, whatever you think of as expensive) so it&#x27;s better to be cautious.</p><p>We started getting complains from delivery department that they have a lot of opened deliveries, but none of them is completed.</p><p>Strange. Gifts should be delivered and delivery tracking service should report them as completed.</p><p>After hours of detective work, talking to various people in the organization, outside of the organization, we decided to make a hypothesis: there is a bug.</p><p>From the logical standpoint, everything seems correct. As delivery department complained there are many opened deliveries, maybe it is something with the delivery process service that is broken?</p><p>Worth checking.</p><p>Hours pass, days move along and it seems like the behemoth, gift delivery process service, is also fine.</p><p>Ok, logs checking time.</p><p>Hours pass and turns out that delivery process is <strong>always</strong> started, even if no users were selected to send gifts to.</p><p>Wait, WHAT?!</p><p>Ok, now it seems &quot;the business logic&quot;, the single <code>if</code> causes this disruption in the business process.</p><p>Let&#x27;s put our hypothesis in the form of a specification:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token function">describe</span><span class="token punctuation">(</span><span class="token string">&quot;areAllUsersActive&quot;</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">const</span> noUsers<span class="token operator">:</span> User<span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
</span><span class="code-line">    <span class="token function">it</span><span class="token punctuation">(</span><span class="token string">&quot;returns false given no users&quot;</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
</span><span class="code-line">        <span class="token function">expect</span><span class="token punctuation">(</span><span class="token function">areAllUsersActive</span><span class="token punctuation">(</span>noUsers<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toBe</span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">}</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">}</span><span class="token punctuation">)</span>
</span></code></pre></div></div><p>Running the specification gives...</p><div class="flex flex-col w-full justify-center items-center"><div><div>Expected: <span class="text-green-600">false</span></div> <div>Actual: <span class="text-red-600">true</span></div></div></div><p>Turns out that built-in <code>Array.prototype.every</code> method returns <code>true</code> when used on an empty array. Impressive, isn&#x27;t it?</p><p>We could verbalize this scenario with the following reasoning: <em>&quot;There are no inactive users so all users are active&quot;</em>. But is this actually true (pun intended)?</p><h3 id="what-is-the-problem"><a href="#what-is-the-problem" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What is the problem?</h3><p>In <a href="https://talesfrom.dev/blog/essentially-bounded-accidentally-unlimited">&quot;Essentially bounded, accidentally unlimited&quot;</a>, I said something like this:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>There is no single solution, but there is a single problem.</p></div></div></div><p>Initial thought might be: <em>&quot;the problem is with a function returning true to empty users collection given&quot;</em>.</p><p>Let&#x27;s create multiple solutions to have something to choose from.</p><p>We could think of the solution as: <em>&quot;the function should return false when empty users collection given&quot;</em>.</p><p>That would be easy win.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">const</span> <span class="token function function-variable">isActive</span> <span class="token operator">=</span> <span class="token punctuation">(</span>user<span class="token operator">:</span> User<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> user<span class="token punctuation">.</span>isActive
</span><span class="code-line"><span class="token keyword">const</span> <span class="token function function-variable">areAllUsersActive</span> <span class="token operator">=</span> 
</span><span class="code-line">    <span class="token punctuation">(</span>users<span class="token operator">:</span> User<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> users<span class="token punctuation">.</span>length <span class="token operator">&gt;</span> <span class="token number">0</span> <span class="token operator">&amp;&amp;</span> users<span class="token punctuation">.</span><span class="token function">every</span><span class="token punctuation">(</span>isActive<span class="token punctuation">)</span>
</span></code></pre></div></div><p>Our test turns green:</p><div class="flex flex-col justify-center items-center"><div><div><span class="bg-green-700">PASS</span> ./users.test.ts</div> <div class="italic ml-6">areAllUsersActive</div> <div class="ml-12"><span class="text-green-700">✓</span> returns false given no users (54 ms)</div></div></div><p>Is this the <em>actual</em> problem?</p><h3 id="no-users---no-problem"><a href="#no-users---no-problem" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>No users - no problem?</h3><p>What else could we do?</p><p>Even if we placed additional guard against empty collection, still something isn&#x27;t right.</p><p>Imagine other places in the code, where no users might be a special, edgy case.</p><p>Our lovely <code>areAllUsersActive</code> function can answer: &quot;yes, all active&quot; or &quot;no, some active&quot;.</p><p>But empty users collection does not fit into any of those answers.</p><p>Unfortunately, the return type of <code>areAllUsersActive</code> is <code>boolean</code>.</p><p>Let&#x27;s imagine that alternative solution is to extend the answers set with additional answer: &quot;no users given&quot;.</p><p>How could we model that?</p><p>We need to change the implementation of this function. Let&#x27;s start with defining the output type, according to the answers we are expecting to get:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">AllUsersActive</span> <span class="token operator">=</span> <span class="token string">&#x27;NO_USERS_GIVEN&#x27;</span> <span class="token operator">|</span> <span class="token string">&#x27;ALL_ACTIVE&#x27;</span> <span class="token operator">|</span> <span class="token string">&#x27;SOME_NOT_ACTIVE&#x27;</span>
</span></code></pre></div></div><p>Then writing a specification of the new behavior:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token function">describe</span><span class="token punctuation">(</span><span class="token string">&#x27;areAllUsersActive&#x27;</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
</span><span class="code-line">  <span class="token keyword">const</span> noUsers<span class="token operator">:</span> User<span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
</span><span class="code-line">  <span class="token keyword">type</span> <span class="token class-name">AreAllUsersActive</span> <span class="token operator">=</span> ReturnType<span class="token operator">&lt;</span><span class="token keyword">typeof</span> areAllUsersActiveDU<span class="token operator">&gt;</span>
</span><span class="code-line">  <span class="token function">it</span><span class="token punctuation">(</span><span class="token string">&#x27;returns &quot;NO_USERS_GIVEN given no users&#x27;</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token function">expect</span><span class="token punctuation">(</span><span class="token function">areAllUsersActiveDU</span><span class="token punctuation">(</span>noUsers<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token generic-function"><span class="token function">toBe</span><span class="token class-name generic"><span class="token operator">&lt;</span>AreAllUsersActive<span class="token operator">&gt;</span></span></span><span class="token punctuation">(</span><span class="token string">&#x27;NO_USERS_GIVEN&#x27;</span><span class="token punctuation">)</span> <span class="token comment">// 👈 not yet defined!</span>
</span><span class="code-line">  <span class="token punctuation">}</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">}</span><span class="token punctuation">)</span>
</span></code></pre></div></div><p>After a small number of TDD cycles, we arrive at the following implementation:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">AllUsersActive</span> <span class="token operator">=</span> <span class="token string">&#x27;NO_USERS_GIVEN&#x27;</span> <span class="token operator">|</span> <span class="token string">&#x27;ALL_ACTIVE&#x27;</span> <span class="token operator">|</span> <span class="token string">&#x27;SOME_NOT_ACTIVE&#x27;</span>
</span><span class="code-line"><span class="token keyword">const</span> areAllUsersActiveDU <span class="token operator">=</span> <span class="token punctuation">(</span>users<span class="token operator">:</span> User<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token operator">:</span> AllUsersActive <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
</span><span class="code-line">  <span class="token keyword">if</span> <span class="token punctuation">(</span>users<span class="token punctuation">.</span>length <span class="token operator">===</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token string">&#x27;NO_USERS_GIVEN&#x27;</span>
</span><span class="code-line">
</span><span class="code-line">  <span class="token keyword">return</span> users<span class="token punctuation">.</span><span class="token function">every</span><span class="token punctuation">(</span>isActive<span class="token punctuation">)</span> <span class="token operator">?</span> <span class="token string">&#x27;ALL_ACTIVE&#x27;</span> <span class="token operator">:</span> <span class="token string">&#x27;SOME_NOT_ACTIVE&#x27;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>And this makes the specification green:</p><div class="flex flex-col justify-center items-center"><div><div><span class="bg-green-700">PASS</span> ./users.test.ts</div> <div class="italic ml-6">areAllUsersActiveDU</div> <div class="ml-12"><span class="text-green-700">✓</span> returns &quot;NO_USERS_GIVEN given no users (50 ms)</div></div></div><p>Further on, we need to adjust the guy who utilizes this function:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">function</span> <span class="token function">handleSendingChristmasGifts</span><span class="token punctuation">(</span>users<span class="token operator">:</span> User<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">  <span class="token keyword">const</span> allActive <span class="token operator">=</span> <span class="token function">areAllUsersActiveDU</span><span class="token punctuation">(</span>users<span class="token punctuation">)</span>
</span><span class="code-line">  <span class="token keyword">if</span> <span class="token punctuation">(</span>allActive <span class="token operator">===</span> <span class="token string">&#x27;ALL_ACTIVE&#x27;</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">const</span> giftsDelivery <span class="token operator">=</span> <span class="token function">startGiftsDeliveryProcess</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// 👈 very expensive operation!</span>
</span><span class="code-line">    <span class="token keyword">const</span> deliveries <span class="token operator">=</span> giftsDelivery<span class="token punctuation">.</span><span class="token function">to</span><span class="token punctuation">(</span>users<span class="token punctuation">)</span> <span class="token comment">// all users will get happiness and joy</span>
</span><span class="code-line">    <span class="token function">trackDeliveries</span><span class="token punctuation">(</span>deliveries<span class="token punctuation">)</span> <span class="token comment">// we track what is the state of delivering joy and happiness</span>
</span><span class="code-line">  <span class="token punctuation">}</span>
</span><span class="code-line">  <span class="token comment">// ... some other important stuff</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>You might wonder what does &quot;DU&quot; suffix mean, at the end of the function name. For those of you who does not recognize it, it stands for &quot;Discriminated Union&quot;. Technically speaking, It might be 100% accurate, but I believe you got the point.</p><h3 id="faster-feedback"><a href="#faster-feedback" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Faster feedback?</h3><p>Any other options?</p><p>We could ask our friend, the compiler, to help guiding us to the pits of success.</p><p>Let&#x27;s try to prevent calling <code>areAllUsersActive</code> functions if there are no users available.</p><p>We need to define <code>NonEmptyArray&lt;TType&gt;</code> type:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">NonEmptyArrayOf<span class="token operator">&lt;</span>TType<span class="token operator">&gt;</span></span> <span class="token operator">=</span> <span class="token punctuation">[</span>TType<span class="token punctuation">,</span> <span class="token operator">...</span>TType<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">]</span>
</span></code></pre></div></div><p>Then we would need to change the signature of our function to accept <code>NonEmptyArrayOf&lt;User&gt;</code>, instead of just an array.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">const</span> <span class="token function function-variable">isActive</span> <span class="token operator">=</span> <span class="token punctuation">(</span>user<span class="token operator">:</span> User<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> user<span class="token punctuation">.</span>isActive
</span><span class="code-line"><span class="token keyword">const</span> <span class="token function function-variable">areAllUsersActive</span> <span class="token operator">=</span> <span class="token punctuation">(</span>users<span class="token operator">:</span> NonEmptyArrayOf<span class="token operator">&lt;</span>User<span class="token operator">&gt;</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
</span><span class="code-line">  users<span class="token punctuation">.</span><span class="token function">every</span><span class="token punctuation">(</span>isActive<span class="token punctuation">)</span>
</span></code></pre></div></div><p>Immediately after doing so, the compiler friendly gives us the reminder that there are two places to apply fixes:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token function">describe</span><span class="token punctuation">(</span><span class="token string">&#x27;areAllUsersActiveDU&#x27;</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
</span><span class="code-line">  <span class="token keyword">const</span> noUsers<span class="token operator">:</span> User<span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
</span><span class="code-line">  <span class="token function">it</span><span class="token punctuation">(</span><span class="token string">&#x27;returns false given no users&#x27;</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token function">expect</span><span class="token punctuation">(</span><span class="token function">areAllUsersActive</span><span class="token punctuation">(</span>noUsers<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toBe</span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">)</span> <span class="token comment">// ❌ &quot;Argument of type &#x27;User[]&#x27; is not assignable to parameter of type &#x27;NonEmptyArrayOf&lt;User&gt;&#x27;&quot;</span>
</span><span class="code-line">  <span class="token punctuation">}</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">}</span><span class="token punctuation">)</span>
</span></code></pre></div></div><p>aaaaand here:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">function</span> <span class="token function">handleSendingChristmasGifts</span><span class="token punctuation">(</span>users<span class="token operator">:</span> User<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">areAllUsersActive</span><span class="token punctuation">(</span>users<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// ❌ &quot;Source provides no match for required element at position 0 in target.&quot;</span>
</span><span class="code-line">    <span class="token keyword">const</span> giftsDelivery <span class="token operator">=</span> <span class="token function">startGiftsDeliveryProcess</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token keyword">const</span> deliveries <span class="token operator">=</span> giftsDelivery<span class="token punctuation">.</span><span class="token function">to</span><span class="token punctuation">(</span>users<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token function">trackDeliveries</span><span class="token punctuation">(</span>deliveries<span class="token punctuation">)</span>
</span><span class="code-line">  <span class="token punctuation">}</span>
</span><span class="code-line">  <span class="token comment">// ... some other important stuff</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>We still need to deal with <code>boolean</code> answer from our function, but we are gently &quot;reminded&quot; to think of such scenario.</p><p>I am leaving completing this solution to you, dear Reader.</p><h3 id="bool-considered-harmful"><a href="#bool-considered-harmful" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a><code>bool</code> considered harmful</h3><p>Why considering <code>bool</code> harmful?</p><p>Maybe I should be more precise here.</p><p><code>bool</code> might be considered harmful when trying to model states/precise answers.</p><p>This was a trivial, toy example, but imagine getting anwsers in the form of <code>bool</code>s from various operations and the need of interpreting:</p><ul><li>what does the <code>false</code> mean?</li><li>or what does the <code>true</code> mean?</li></ul><p>We might get into a paranoia quite fast, don&#x27;t we?</p><p>One might say I am exaggerating now and there is additional, accidental complexity introduced.</p><p>I would say we are easily getting lured by the &quot;simple&quot; solutions. Being attracted to such approach might be a consequence of <a href="https://talesfrom.dev/blog/the-cost-of-modeling">The cost of modeling</a>.</p><p>It reminds me the first sentence from the great book, written by Craig Larman, &quot;Applying UML and Patterns&quot; (paraphrasing):</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Programming is fun, but building maintainable software is hard.</p></div></div></div><p>Creating maintainable, readable, evolvable software is damn difficult - it requires putting effort into thinking, analyzing and capturing our thoughts in the form the code.</p><p>We <strong>can</strong> superficially approach problems we see, but what are the consequences? Aren&#x27;t we &quot;trivializing&quot; the complexity of the reality?</p><p>Yet again, instead of rushing to write production code, it&#x27;s vital and worthy to spend time on doing analysis, thought process to understand the problem we are going to solve.</p><h3 id="bool-hater"><a href="#bool-hater" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a><code>bool</code> hater?</h3><p>Am I a &quot;bool hater&quot;? Would I like to destroy all the bools?</p><p>Of course not.</p><p>It&#x27;s not all good or all bad, but it is so easy to underestimate the scenario we are working with.</p><p>I think we, programmers, architects, have &quot;status thinking&quot; installed into our mind.</p><p>Primitive types like <code>bool</code> share similar trait: they are very eager to &quot;summon&quot; their primitive friends at disposal.</p><p>Soon, a single <code>isActive</code> status might attract another <code>isRecommended</code> status, which then can invite yet another <code>isInvalid</code> status to the party.</p><p>Such three amigos can bring havoc rapidly. Primitive types replicate with the speed of light.</p><h3 id="status-thinking-considered-harmful"><a href="#status-thinking-considered-harmful" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Status thinking&quot; considered harmful</h3><p>So maybe it&#x27;s not about <code>bool</code> that can be considered harmful, but &quot;status thinking&quot;?</p><p>What&#x27;s more, <code>bool</code> statuses do not scale.</p><p>What do I mean by &quot;scaling&quot; in this context?</p><p>As you, dear Reader, saw in our toy example and the solution suggested in <a href="#no-users---no-problem">No users - no problem?</a>, we couldn&#x27;t fit another &quot;answer&quot; in the two-case type.</p><p>Did I say &quot;two-case&quot;?</p><p>That&#x27;s right. <code>bool</code> can be &quot;represented&quot; as a union of two cases:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">bool_</span> <span class="token operator">=</span> <span class="token string">&#x27;true&#x27;</span> <span class="token operator">|</span> <span class="token string">&#x27;false&#x27;</span>
</span></code></pre></div></div><p>Adding &quot;another&quot; case sounds bad, isn&#x27;t it?</p><p>If there is another &quot;answer&quot; a function might give as a result of computation, <code>bool</code> can&#x27;t hold it. It is not the level of abstraction <code>bool</code> is operating on.</p><p>The language that <code>bool</code> &quot;knows&quot; forbids that.</p><p>I like to think of programming constructs as people (Am I crazy? Please check <a href="https://talesfrom.dev/blog/organization-driven-design">&quot;Organization-Driven Design&quot;</a>, <a href="https://talesfrom.dev/blog/conversation-driven-design">Conversation-Driven Design</a> and <a href="https://talesfrom.dev/blog/microoffices-officeolith">&quot;Microoffices&quot; vs &quot;Officeolith&quot;</a>!). By using this reasoning model, in order a <code>bool</code> status to &quot;give&quot; all possible answers, such guy needs to get help from his friend: another <code>bool</code> status. I hope you see where it leads, right?</p><p>One could say we infected our minds with &quot;status thinking&quot; and what&#x27;s even worse - we taught our friends from product/business to communicate with statuses too.</p><p>To heal such &quot;mental wounds&quot; done by &quot;status thinking&quot; damage, we need to start from ourselves. There is no other option.</p><p>How to prevent summoning daemons from &quot;Primitive Type&quot; universe?</p><h3 id="model-states-not-statuses"><a href="#model-states-not-statuses" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Model states, not statuses</h3><p>One of possible ways is to model states explicitly.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>States are for the essential complexity, for representing the concepts available in the domain you are designing the software for.</p></div></div></div><p>Aforementioned &quot;domain&quot;, does not always need to mean &quot;business domain&quot;. A problem space varies depending on the plane we are marching on. In our toy example, our problem space was related to rules regarding active users.</p><p>One of the suggested solutions incorporated &quot;states modeling&quot; approached.</p><p>As I mentioned in <a href="https://talesfrom.dev/blog/the-cost-of-modeling">The cost of modeling</a>:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>(...) statuses are reserved for infrastructure side - one might say they are &quot;optimized&quot; for it.</p></div></div></div><p><code>bool</code> statues have their place, don&#x27;t get me wrong. Infrastructure components love primitive types, because they are representing a &quot;generic domain&quot;.</p><p>In &quot;their&quot; language there is no <code>InactiveUser</code> or <code>RecommendedSubscription</code> concepts. They know technical language and we need to align to that when speaking with an Infrastructure component.</p><p>One might argue that modeling states might bring performance-issues - that&#x27;s why we, engineers, need to apply the proper solution to the given problem, including the nature of the problem and context we are working with.</p><h3 id="modeling-states--state-machines"><a href="#modeling-states--state-machines" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Modeling states = state machines</h3><p>Modeling states soon might get us into a whole new world of finite state machines. I firmly believe that we humans, by the bias of our minds, treat continuous, analogous world with in a discrete fashion.</p><p>Hence thinking with discrete states, events (facts) and processes driving transitions between the set number of states, is very natural to us (blogpost on this topic will come soon!)</p><p>Somehow, working with the infrastructure tools placed ourselves in using low-level primitive types when communicating/thinking.</p><p>Such an approach is not optimized for how we describe the world we see, we influence and we live in.</p><p>Next time dear Reader, try to ask yourself:</p><ul><li>are there are some hidden states that got buried under <code>bool</code> statuses?</li><li>what states are possible?</li><li>what is impossible?</li><li>how would <code>bool</code> status(es) evolve/&quot;scale&quot;?</li></ul><p>Happy thinking!</p>]]></content:encoded>
    <pubDate>Sat, 24 Dec 2022 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>programming</category><category>paradigms</category><category>problem-solving</category><category>language</category><category>learning</category><category>encapsulation</category><category>value objects</category><category>code</category><category>model</category><category>modeling</category><category>type-driven thinking</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/many-faces-of-ddd-aggregates-in-fsharp</guid>
    <title>Many faces of DDD Aggregates in F#</title>
    <link>https://talesfrom.dev/blog/many-faces-of-ddd-aggregates-in-fsharp</link>
    <description>How could we represent Aggregates, in the tactical DDD sense, using F#?</description>
    <content:encoded><![CDATA[<div class="bg-slate-600 rounded-xl "><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Attention!</span></div><div class="pb-2 px-3"><div class="break-words"><p>This tale is a tiny contribution to the great <a href="https://sergeytihon.com/2022/10/28/f-advent-calendar-in-english-2022/">F# Advent Calendar 2022</a>.</p>
<p>Take your time and check other contributions too (of course, after reading this tale)!</p></div></div></div> <div class="bg-slate-600 rounded-xl mt-10"><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Kudos! 🙏🏻</span></div><div class="pb-2 px-3"><div class="break-words"><p>This tale wouldn&#x27;t be here if I didn&#x27;t have conversations with <a href="https://mobile.twitter.com/Savlambda">borar</a>.</p>
<p>We had a lot of discussions (or rather me asking tons of questions and learning from <a href="https://mobile.twitter.com/Savlambda">borar</a>), especially on functional topics.</p>
<p>Thanks <a href="https://mobile.twitter.com/Savlambda">borar</a> for your patience, your wisdom and sharing your thoughts with me!</p></div></div></div><h3 id="plan"><a href="#plan" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Plan?</h3><p>In this little tale, we are going to explore an interesting building block, coming from &quot;tactical design&quot; of Domain-Driven Design approach, called <em>Aggregate</em>.</p><p>The key aspect will be the language I personally love - F#. We will see (opinionated) way of representing this model for solving a particular set of problems.</p><p>To make it more &quot;real&quot; (i.e. close to the business), we are going to help our customer (we&#x27;ll meet him soon!). So we&#x27;ll be challenged with the real business problem!</p><p>So, what is our plan? Here is a list of topics we are going to sequentially visit:</p><ul><li><a href="#problem">Problem?</a></li><li><a href="#ddd-101-strategic-and-tactical-design">DDD 101: strategic and tactical design</a></li><li><a href="#aggregate">Aggregate?!</a></li><li><a href="#problem-analysis">Problem Analysis</a></li><li>Solution Recommendations (<a href="#solution-1-object-oriented-approach">Solution #1</a> <a href="#solution-2-functional-oriented-approach">Solution #2</a> <a href="#solution-3-functional-state-machine-like-approach">Solution #3</a>)</li><li><a href="#what-the-hell-just-happened">Summary</a></li></ul><p>This tale grew a bit, so I might divide it into smaller tales based on the bullet points above.</p><p>But for now my dear Reader, just sit comfortably in your chair, take a deep breath and immerse.</p><h3 id="problem"><a href="#problem" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Problem?</h3><p>Who has the problem?</p><p>Meet Tom.</p><p>(this is the time when we are simulating a vivid discussion with Tom)</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/business-man.png" class="max-h-[30rem]"/><div class="italic flex flex-col justify-between text-left"><span class="my-4">&quot;Hi, my name is Tom.</span> <span class="my-4">I am an owner of a luxurious disco clubs.</span> <span class="my-4">I have a problem with <b>consistency</b> on counting how many people are partying and limiting it.</span> <span class="my-4">Can you help me?&quot;</span></div></div><div>Tom, the businessman. <a href="https://commons.wikimedia.org/wiki/File:A_Humble_Cartoon_Businessman.svg">Source</a></div></div><p>What do you think, can we help? Good that we paid attention to the language, used by Tom, which resulted in catching the important word. Let&#x27;s try to ask a bit more about the details, maybe we will learn something?</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/business-man.png" class="max-h-[30rem]"/><div class="italic flex flex-col justify-between text-left"><span class="my-4 italic">&quot;Briefly, we are testing new ways of reporting on how many people are having fun in our clubs.</span> <span class="my-4 italic">Club bouncers are responsible for counting, but they are not satisfying the hard requirements we are giving them.</span> <span class="my-4 italic">They need to secure the limits so that people wanting to enter think of it as a luxury.&quot;</span></div></div><div>Tom&#x27;s business problem. <a href="https://commons.wikimedia.org/wiki/File:A_Humble_Cartoon_Businessman.svg">Source</a></div></div><p>This sounds serious, isn&#x27;t it? Seems like we need to do some analysis and try to figure out what it is all about with those bouncers. Shall we?</p><p>There are multiple ways of approaching such activity, but in this particular example we will try to practice DDD.</p><h3 id="ddd-101-strategic-and-tactical-design"><a href="#ddd-101-strategic-and-tactical-design" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>DDD 101: strategic and tactical design</h3><p>Let me give an &quot;extended&quot; version of the DDD shortcut, I personally like:</p><div class="flex justify-center w-full"><div class="flex flex-col text-3xl items-center"><span>Business <b>D</b>omain</span> <span><b>D</b>riven</span> <span>Software <b>D</b>esign</span></div></div><p>It is not a definition, but rather a formula, I find particuarly interesting.</p><p>A function, when fed with domain knowledge, should yield an understanding that might lead to the problem-adjusted software design.</p><p>Exploring the problem, its nature, its essential complexity, might bring us closer to suggesting a proper solution (or solutions) - so-called models.</p><p>Models are related to the accidental complexity, our approach for providing value by solving the problem (what&#x27;s the difference between those two type of complexity? Please check <a href="https://talesfrom.dev/blog/essentially-bounded-accidentally-unlimited">&quot;Essentially bounded, Accidentally unlimited&quot;</a>).</p><p>From the helicopter view, we can divide &quot;the design&quot; into two categories: strategic design and tactical design (you can find more about it in the original <a href="https://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215">&quot;Blue Book&quot;</a> by Eric Evans).</p><p>Both of them consist of various techniques, building blocks, or methods that one can utilize to model different aspects of the problem space.</p><p>What is very important, strategic perspective <strong>should</strong> drive the tactical perspective, not the other way around (then we might arrive at Design-Driven Domain, one of the two evil sibilings of Domain-Driven Design - what is the second evil twin? Database-Driven Design)</p><p>But jumping into the tactical design without exploring and analyzing the strategic aspect might be dangerous.</p><h3 id="ddd-101-the-language"><a href="#ddd-101-the-language" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>DDD 101: the language</h3><p>The essence of strategic design is the language, called <strong>Ubiquitous Language</strong>.</p><div class="w-full justify-center flex"><blockquote><div>Talk to me in your language.</div> <div>I will talk to you in your language.</div> <div>Code will express your language.</div></blockquote></div><p>In other words, we are going to capture the language of &quot;the problem&quot;, that Tom speaks about. This language will be the central piece of our work.</p><h3 id="aggregate"><a href="#aggregate" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Aggregate?!</h3><p>I must admit I misunderstood this concept, or rather a building block, in 100%. The name might be a bit...Misleading?</p><p>I like to go down to definitions (I used the same approach in the tale <a href="https://talesfrom.dev/blog/fragile">&quot;(Fr)Agile&quot;</a>), to check if we can refine the understanding.</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">an aggregate - definition</div><div class="pb-2 px-3"><div class="break-words"><p>a cluster of domain objects that can be treated as <strong>a single unit</strong>.</p></div></div></div><p>Googling for a definition made me lucky because this one sounds interesting.</p><p>Especially the highlighted part.</p><p>One could ask: a single unit of what?</p><p>With my current understanding (this assumes it might change in the future so bear with me), it is a single unit of <strong>consistency</strong> (also referred to a unit of bussines transaction).</p><p>Wasn&#x27;t Tom mentioning some issues with consistency?</p><h3 id="aggregate---whoa-there-cowboy"><a href="#aggregate---whoa-there-cowboy" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Aggregate?! - &quot;whoa there cowboy&quot;</h3><p>As it got mentioned before, if we look down into a further analysis of the &quot;aggregate&quot; word, its main purpose might be depicted as data aggregation.</p><p>As an example, we could take C# LINQ <code>Aggregate</code> method that is related to data transformation. Next examples might be SQL Aggregate Functions: <code>SUM</code>, <code>MIN</code>, <code>AVG</code>.</p><p>As information or data is mentioned, the understanding might orbit around entities or &quot;bags of data structures&quot;.</p><p>But data is the secondary citizen here.</p><p>Aggregate protects (or enforces) the <strong>consistency rules</strong>. Such rules might be also called <strong>invariants</strong>.</p><p>The internal integrity is guarded by those rules.</p><p>One could ask: the integrity of what? This is hidden, taken away from the sight.</p><p>Hence there&#x27;s another, supplementary building block - Aggregate Root - that is the interface to the underlying world. Typically <code>Aggregate</code> and <code>Aggregate Root</code> is used interchangeably to refer to the same thing - consistency rules guard.</p><h3 id="aggregate---real-example"><a href="#aggregate---real-example" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Aggregate?! - &quot;real&quot; example</h3><p>Working with abstract terms like &quot;abstraction&quot;, &quot;loose coupling&quot; might be intimidating and I am a huge beliver for finding corresponding real world examples that are more &quot;tangible&quot; (thus tales like <a href="https://talesfrom.dev/blog/organization-driven-design">&quot;Organization-Driven Design&quot;</a> and <a href="https://talesfrom.dev/blog/microoffices-vs-officeolith">&quot;Microoffices&quot; vs &quot;Officeolith&quot;</a>).</p><p>Then, what could be possible example of an aggregate, in &quot;real world&quot;?</p><p>Any parents there?</p><p>Imagine a kid having a high fever - they need to get ibuprofen or paracetamol. You measure the temperature, note it down on the piece of paper.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/drug-intake.png" class="max-h-[20rem]"/></div><div class="italic mx-24">Body temperature measurements for each hour, on a piece of paper. Source: generated using DALL·E</div></div><p>There is a hard rule that the intake must have to comply with a particular time regime.</p><p>Where is the aggregate? A parent is enforcing (&quot;protecting&quot;) this rule, so parent represents the aggregate here.</p><p>Taking into account what we just discussed, isn&#x27;t the name &quot;aggregate&quot; misleading?</p><p>How could we name such a &quot;guy&quot;? What would you say for a bouncer?</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/bouncer.png" class="max-h-[20rem]"/></div><div class="italic mx-24">A bouncer.</div></div><h3 id="problem-analysis"><a href="#problem-analysis" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Problem Analysis</h3><p>Let&#x27;s go back to our friend, Tom. We still have some learning to do!</p><p>Hey Tom! Could you please tell us more about your problem? (let&#x27;s pretend we have a conversation here).</p><p>(hint: you can interact with Tom in two different ways by using buttons below)</p><div class="flex flex-col mb-20"><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/business-man.png" class="max-h-[30rem]"/><div class="italic flex flex-col justify-between text-left"><span class="my-4 italic">&quot;Well, each bouncer is either guarding or having a break.</span><span class="my-4 italic">Then a bouncer can report new people coming only when he is guarding.</span><span class="my-4 italic">Each shift requires at least three bouncers.</span><span class="my-4 italic">When scheduling a break for a bouncer, we need to ensure at least two bouncers are guarding.</span><span class="my-4 italic">To keep our clubs luxurious, we are limiting the number of partying people to 100.</span><span class="my-4 italic">So when new people are coming and there is more than 100 people, we don&#x27;t allow entering to the club.&quot;</span></div></div></div><div class="flex justify-around mt-10 mx-32"><button class="false bg-green-700 border-2 p-2 rounded">Just talk</button><button class="bg-gray-300 border-gray-100 text-gray-400 bg-green-700 border-2 p-2 rounded">Listening carefully</button></div></div><p>By carefully listening to Tom&#x27;s speech, we found out some rules.</p><p>How to proceed?</p><ul><li>all rules need to be satisfied</li> <li>we need to suggest aggregate boundary and check if rules are satisfied</li> <li>align to the language used by the Tom</li></ul><p>Let&#x27;s go!</p><div class="bg-slate-600 rounded-xl "><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Attention!</span></div><div class="pb-2 px-3"><div class="break-words"><p>Note that this is a toy example and all the solutions are provided in order to show various perspectives.</p>
<p>I am totally aware that there are other ways of approaching this modeling task - if you have your preferred one, please share! 🙏🏻</p></div></div></div><h3 id="solution-1-object-oriented-approach"><a href="#solution-1-object-oriented-approach" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Solution #1: Object-oriented approach</h3><p>Firstly, as a warm-up, let us start with &quot;typical&quot; OO way of modeling.</p><p>What a bouncer can do?</p><ul><li>have a break</li> <li>start guarding</li> <li>report new people coming, only when guarding.</li></ul><p>Let put those behaviors in a proper place.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">Bouncer</span><span class="token punctuation">(</span>name<span class="token punctuation">:</span> <span class="token class-name">string</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">    <span class="token keyword">member</span> this<span class="token punctuation">.</span><span class="token function">HaveABreak</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">        <span class="token comment">// details</span>
</span><span class="code-line">    <span class="token keyword">member</span> this<span class="token punctuation">.</span><span class="token function">StartGuarding</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">        <span class="token comment">// details</span>
</span><span class="code-line">    <span class="token keyword">member</span> this<span class="token punctuation">.</span><span class="token function">ReportNewPeople</span><span class="token punctuation">(</span>newPeopleCount<span class="token punctuation">:</span> <span class="token class-name">int</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">        <span class="token comment">// details</span>
</span></code></pre></div></div><p>I like to focus on behaviors firstly, to see how they drive the inforomation needed.</p><p>Clearly, we need some &quot;status&quot; to indicate whether a bouncer is guarding or not.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">Bouncer</span><span class="token punctuation">(</span>name<span class="token punctuation">:</span> <span class="token class-name">string</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">    <span class="token keyword">let</span> <span class="token keyword">mutable</span> isGuarding <span class="token operator">=</span> <span class="token keyword">false</span> <span class="token comment">// 👈 new!</span>
</span><span class="code-line">    <span class="token keyword">member</span> this<span class="token punctuation">.</span><span class="token function">HaveABreak</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">        isGuarding <span class="token operator">&lt;-</span> <span class="token keyword">false</span> <span class="token comment">// 👈 new!</span>
</span><span class="code-line">    <span class="token keyword">member</span> this<span class="token punctuation">.</span><span class="token function">StartGuarding</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">        isGuarding <span class="token operator">&lt;-</span> <span class="token keyword">true</span> <span class="token comment">// 👈 new!</span>
</span><span class="code-line">    <span class="token keyword">member</span> this<span class="token punctuation">.</span><span class="token function">ReportNewPeople</span><span class="token punctuation">(</span>newPeopleCount<span class="token punctuation">:</span> <span class="token class-name">int</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">        <span class="token comment">// details</span>
</span></code></pre></div></div><p>Great. What about <code>ReportNewPeople</code> and information needed?</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">Bouncer</span><span class="token punctuation">(</span>name<span class="token punctuation">:</span> <span class="token class-name">string</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">    <span class="token keyword">let</span> <span class="token keyword">mutable</span> isGuarding <span class="token operator">=</span> <span class="token keyword">false</span>    
</span><span class="code-line">    <span class="token keyword">let</span> <span class="token keyword">mutable</span> peopleCount <span class="token operator">=</span> <span class="token number">0</span> <span class="token comment">// 👈 new!</span>
</span><span class="code-line">    <span class="token keyword">member</span> this<span class="token punctuation">.</span><span class="token function">HaveABreak</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">        isGuarding <span class="token operator">&lt;-</span> <span class="token keyword">false</span>
</span><span class="code-line">    <span class="token keyword">member</span> this<span class="token punctuation">.</span><span class="token function">StartGuarding</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">        isGuarding <span class="token operator">&lt;-</span> <span class="token keyword">true</span>
</span><span class="code-line">    <span class="token keyword">member</span> this<span class="token punctuation">.</span><span class="token function">ReportNewPeople</span><span class="token punctuation">(</span>newPeopleCount<span class="token punctuation">:</span> <span class="token class-name">int</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">        <span class="token comment">// details</span>
</span></code></pre></div></div><p>Finally, let&#x27;s apply the first consistency rule.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">Bouncer</span><span class="token punctuation">(</span>name<span class="token punctuation">:</span> <span class="token class-name">string</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">    <span class="token keyword">let</span> <span class="token keyword">mutable</span> isGuarding <span class="token operator">=</span> <span class="token keyword">false</span> 
</span><span class="code-line">    <span class="token keyword">let</span> <span class="token keyword">mutable</span> peopleCount <span class="token operator">=</span> <span class="token number">0</span>   
</span><span class="code-line">    <span class="token keyword">member</span> this<span class="token punctuation">.</span><span class="token function">HaveABreak</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">        isGuarding <span class="token operator">&lt;-</span> <span class="token keyword">false</span>
</span><span class="code-line">    <span class="token keyword">member</span> this<span class="token punctuation">.</span><span class="token function">StartGuarding</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">        isGuarding <span class="token operator">&lt;-</span> <span class="token keyword">true</span>
</span><span class="code-line">    <span class="token keyword">member</span> this<span class="token punctuation">.</span><span class="token function">ReportNewPeople</span><span class="token punctuation">(</span>newPeopleCount<span class="token punctuation">:</span> <span class="token class-name">int</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">        <span class="token keyword">if</span> isGuarding <span class="token comment">// 👈 new!</span>
</span><span class="code-line">          <span class="token keyword">then</span> peopleCount <span class="token operator">&lt;-</span> peopleCount <span class="token operator">+</span> newPeopleCount <span class="token comment">// 👈 new!</span>
</span><span class="code-line">          <span class="token keyword">else</span> failwith $<span class="token string">&quot;Bouncer {name} is not guarding at the moment&quot;</span> <span class="token comment">// 👈 new!</span>
</span></code></pre></div></div><p>Note that a <code>Bouncer</code> starts with a break!</p><p>We got it, isn&#x27;t it?</p><p>But let&#x27;s come back to our rules. Can <i>a Bouncer</i> satisfy all of them?</p><div class="flex flex-col"><span>✅ bouncer can be either guarding or having a break</span> <span>✅ bouncer can report new people only when guarding</span> <span>❌ when scheduling a break, at least two bouncers needs to be guarding</span> <span>❌ no more than 100 people partying</span> <span>❌ at least three bouncers</span></div><p>There are at least three rules we are clearly missing. Let&#x27;s implement them and see where they fit in.</p><span class="mb-8">Rule: <span class="italic">when scheduling a break, at least two bouncers needs to be guarding</span></span><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> atLeastTwoGuarding <span class="token punctuation">(</span>bouncers<span class="token punctuation">:</span> <span class="token class-name">Bouncer</span> list<span class="token punctuation">)</span><span class="token punctuation">:</span> bool <span class="token operator">=</span>
</span><span class="code-line">    <span class="token keyword">let</span> guardingBouncersCount <span class="token operator">=</span>
</span><span class="code-line">        bouncers <span class="token comment">// Bouncer list</span>
</span><span class="code-line">        <span class="token operator">|&gt;</span> List<span class="token punctuation">.</span>filter <span class="token punctuation">(</span><span class="token keyword">fun</span> bouncer <span class="token operator">-&gt;</span> bouncer<span class="token punctuation">.</span>IsGuarding<span class="token punctuation">)</span> <span class="token comment">// bool list</span>
</span><span class="code-line">        <span class="token operator">|&gt;</span> List<span class="token punctuation">.</span>length <span class="token comment">// int</span>
</span><span class="code-line">
</span><span class="code-line">    guardingBouncersCount <span class="token operator">&gt;</span> <span class="token number">2</span>
</span></code></pre></div></div><p>Easy. NEXT!</p><span class="mb-8">Rule: <span class="italic">no more than 100 people partying</span></span><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> reportedLessThan100PeopleWith <span class="token punctuation">(</span>newPeopleComing<span class="token punctuation">:</span> <span class="token class-name">int</span><span class="token punctuation">)</span> <span class="token punctuation">(</span>bouncers<span class="token punctuation">:</span> <span class="token class-name">Bouncer</span> list<span class="token punctuation">)</span><span class="token punctuation">:</span> bool <span class="token operator">=</span>
</span><span class="code-line">    <span class="token keyword">let</span> currentlyPartyingPeople <span class="token operator">=</span>
</span><span class="code-line">        bouncers <span class="token comment">// Bouncers list</span>
</span><span class="code-line">        <span class="token operator">|&gt;</span> List<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token keyword">fun</span> bouncer <span class="token operator">-&gt;</span> bouncer<span class="token punctuation">.</span>PeopleCounted<span class="token punctuation">)</span> <span class="token comment">// int list</span>
</span><span class="code-line">        <span class="token operator">|&gt;</span> List<span class="token punctuation">.</span>sum <span class="token comment">// int</span>
</span><span class="code-line">    
</span><span class="code-line">    currentlyPartyingPeople <span class="token operator">+</span> newPeopleComing <span class="token operator">&lt;=</span> <span class="token number">100</span>
</span></code></pre></div></div><p>Business rules might be interesting, isn&#x27;t it? Next please!</p><p>We have exposed to the external world some new information, let&#x27;s add them to the <code>Bouncer</code>.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">Bouncer</span><span class="token punctuation">(</span>name<span class="token punctuation">:</span> <span class="token class-name">string</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">    <span class="token keyword">let</span> <span class="token keyword">mutable</span> isGuarding <span class="token operator">=</span> <span class="token keyword">false</span> 
</span><span class="code-line">    <span class="token keyword">let</span> <span class="token keyword">mutable</span> peopleCount <span class="token operator">=</span> <span class="token number">0</span>
</span><span class="code-line">    <span class="token keyword">member</span> this<span class="token punctuation">.</span>IsGuarding <span class="token keyword">with</span> <span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span> isGuarding <span class="token comment">// 👈 new!</span>
</span><span class="code-line">    <span class="token keyword">member</span> this<span class="token punctuation">.</span>PeopleCount <span class="token keyword">with</span> <span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span> peopleCount <span class="token comment">// 👈 new!</span>
</span><span class="code-line">    <span class="token keyword">member</span> this<span class="token punctuation">.</span><span class="token function">HaveABreak</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">        isGuarding <span class="token operator">&lt;-</span> <span class="token keyword">false</span>
</span><span class="code-line">    <span class="token keyword">member</span> this<span class="token punctuation">.</span><span class="token function">StartGuarding</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">        isGuarding <span class="token operator">&lt;-</span> <span class="token keyword">false</span>
</span><span class="code-line">    <span class="token keyword">member</span> this<span class="token punctuation">.</span><span class="token function">ReportNewPeople</span><span class="token punctuation">(</span>newPeopleCount<span class="token punctuation">:</span> <span class="token class-name">int</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">        <span class="token keyword">if</span> isGuarding
</span><span class="code-line">          <span class="token keyword">then</span> peopleCount <span class="token operator">&lt;-</span> peopleCount <span class="token operator">+</span> newPeopleCount
</span><span class="code-line">          <span class="token keyword">else</span> failwith $<span class="token string">&quot;Bouncer {name} is not guarding at the moment&quot;</span>
</span></code></pre></div></div><p>Finally, the last missing rule!</p><span class="mb-8">Rule: <span class="italic">at least three bouncers</span></span><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> ensureAtLeastThreeBouncers <span class="token punctuation">(</span>bouncerNames<span class="token punctuation">:</span> <span class="token class-name">string</span> list<span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">    <span class="token keyword">let</span> bouncersCount <span class="token operator">=</span> List<span class="token punctuation">.</span>length bouncerNames
</span><span class="code-line">    <span class="token keyword">if</span> bouncersCount <span class="token operator">&lt;</span> <span class="token number">3</span>
</span><span class="code-line">        <span class="token keyword">then</span> failwith <span class="token string">&quot;At least three bouncers are required!&quot;</span> <span class="token comment">// ⛔ consistency violation</span>
</span></code></pre></div></div><p>No way a single bouncer could satisfy those three rules. We need something &quot;bigger&quot;.</p><p>Thanks to carefully listening to Tom&#x27;s explanation, we know that bouncers work together on a shift.</p><p>Let&#x27;s model that and see if this makes any sense!</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">BouncersShift</span><span class="token punctuation">(</span>bouncerNames<span class="token punctuation">:</span> <span class="token class-name">string</span> list<span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">    <span class="token keyword">do</span> ensureAtLeastThreeBouncers bouncerNames <span class="token comment">// 👈 consistency rule</span>
</span><span class="code-line">    <span class="token keyword">let</span> <span class="token keyword">mutable</span> bouncers <span class="token operator">=</span> bouncerNames <span class="token operator">|&gt;</span> List<span class="token punctuation">.</span>map <span class="token punctuation">(</span><span class="token keyword">fun</span> name <span class="token operator">-&gt;</span> <span class="token punctuation">(</span>name<span class="token punctuation">,</span> Bouncer name<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">|&gt;</span> dict
</span><span class="code-line">      <span class="token comment">// Dictionary&lt;string, Bouncer&gt;</span>
</span><span class="code-line">    <span class="token keyword">member</span> <span class="token keyword">private</span> this<span class="token punctuation">.</span>Bouncers <span class="token keyword">with</span> <span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span> bouncers<span class="token punctuation">.</span>Values <span class="token operator">|&gt;</span> Seq<span class="token punctuation">.</span>cast <span class="token operator">|&gt;</span> List<span class="token punctuation">.</span>ofSeq
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">member</span> this<span class="token punctuation">.</span><span class="token function">ScheduleBreakFor</span><span class="token punctuation">(</span>bouncerName<span class="token punctuation">:</span> <span class="token class-name">string</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">        <span class="token keyword">let</span> bouncer <span class="token operator">=</span> bouncers<span class="token punctuation">[</span>bouncerName<span class="token punctuation">]</span>
</span><span class="code-line">        <span class="token keyword">if</span> atLeastTwoGuarding this<span class="token punctuation">.</span>Bouncers <span class="token comment">// 👈 consistency rule</span>
</span><span class="code-line">            <span class="token keyword">then</span> bouncer<span class="token punctuation">.</span><span class="token function">HaveABreak</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token keyword">else</span> failwith <span class="token string">&quot;Can&#x27;t schedule break because less than two bouncers are guarding&quot;</span> <span class="token comment">// ⛔ consistency violation</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">member</span> this<span class="token punctuation">.</span><span class="token function">StartGuarding</span><span class="token punctuation">(</span>bouncerName<span class="token punctuation">:</span> <span class="token class-name">string</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">        <span class="token keyword">let</span> bouncer <span class="token operator">=</span> bouncers<span class="token punctuation">[</span>bouncerName<span class="token punctuation">]</span>
</span><span class="code-line">        bouncer<span class="token punctuation">.</span><span class="token function">Guard</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">member</span> this<span class="token punctuation">.</span><span class="token function">ReportNewPeopleComing</span><span class="token punctuation">(</span>bouncerName<span class="token punctuation">:</span> <span class="token class-name">string</span><span class="token punctuation">,</span> newPeopleComing<span class="token punctuation">:</span> <span class="token class-name">int</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">        <span class="token keyword">let</span> bouncer <span class="token operator">=</span> bouncers<span class="token punctuation">[</span>bouncerName<span class="token punctuation">]</span>
</span><span class="code-line">        <span class="token keyword">if</span> this<span class="token punctuation">.</span>Bouncers <span class="token operator">|&gt;</span> reportedLessThan100PeopleWith newPeopleComing <span class="token comment">// 👈 consistency rule</span>
</span><span class="code-line">            <span class="token keyword">then</span> bouncer<span class="token punctuation">.</span><span class="token function">ReportNewPeople</span><span class="token punctuation">(</span>newPeopleComing<span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token keyword">else</span> failwith <span class="token string">&quot;Can&#x27;t allow more people enter the club&quot;</span> <span class="token comment">// ⛔ consistency violation</span>
</span></code></pre></div></div><p>In this example we can safely assume that visibility of the <code>Bouncer</code> class is scoped only to <code>BouncersShift</code> class.</p><p>Cool, <code>BouncersShift</code> captures the three missing rules, the rest is delegated to a specific <code>Bouncer</code>.</p><p>How could we use such a model?</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> shift <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">BouncersShift</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string">&quot;mike&quot;</span><span class="token punctuation">;</span><span class="token string">&quot;john&quot;</span><span class="token punctuation">;</span><span class="token string">&quot;derek&quot;</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
</span><span class="code-line">
</span><span class="code-line">shift<span class="token punctuation">.</span><span class="token function">StartGuarding</span><span class="token punctuation">(</span><span class="token string">&quot;mike&quot;</span><span class="token punctuation">)</span>
</span><span class="code-line">shift<span class="token punctuation">.</span><span class="token function">StartGuarding</span><span class="token punctuation">(</span><span class="token string">&quot;derek&quot;</span><span class="token punctuation">)</span>
</span><span class="code-line">shift<span class="token punctuation">.</span><span class="token function">StartGuarding</span><span class="token punctuation">(</span><span class="token string">&quot;john&quot;</span><span class="token punctuation">)</span>
</span><span class="code-line">shift<span class="token punctuation">.</span><span class="token function">ReportNewPeopleComing</span><span class="token punctuation">(</span><span class="token string">&quot;mike&quot;</span><span class="token punctuation">,</span> <span class="token number">20</span><span class="token punctuation">)</span>
</span><span class="code-line">shift<span class="token punctuation">.</span><span class="token function">ScheduleBreakFor</span><span class="token punctuation">(</span><span class="token string">&quot;mike&quot;</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token keyword">try</span> shift<span class="token punctuation">.</span><span class="token function">ReportNewPeopleComing</span><span class="token punctuation">(</span><span class="token string">&quot;mike&quot;</span><span class="token punctuation">,</span> <span class="token number">20</span><span class="token punctuation">)</span> <span class="token keyword">with</span> ex <span class="token operator">-&gt;</span> printfn $<span class="token string">&quot;{ex}&quot;</span>
</span><span class="code-line"><span class="token comment">// \__ System.Exception: mike bouncer is not guarding at the moment</span>
</span><span class="code-line">shift<span class="token punctuation">.</span><span class="token function">ReportNewPeopleComing</span><span class="token punctuation">(</span><span class="token string">&quot;derek&quot;</span><span class="token punctuation">,</span> <span class="token number">40</span><span class="token punctuation">)</span>
</span><span class="code-line">shift<span class="token punctuation">.</span><span class="token function">ReportNewPeopleComing</span><span class="token punctuation">(</span><span class="token string">&quot;derek&quot;</span><span class="token punctuation">,</span> <span class="token number">40</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token keyword">try</span> shift<span class="token punctuation">.</span><span class="token function">ReportNewPeopleComing</span><span class="token punctuation">(</span><span class="token string">&quot;derek&quot;</span><span class="token punctuation">,</span> <span class="token number">40</span><span class="token punctuation">)</span> <span class="token keyword">with</span> ex <span class="token operator">-&gt;</span> printfn $<span class="token string">&quot;{ex}&quot;</span> 
</span><span class="code-line"><span class="token comment">// \__ System.Exception: Can&#x27;t allow more people enter the club</span>
</span><span class="code-line"><span class="token keyword">try</span> shift<span class="token punctuation">.</span><span class="token function">ScheduleBreakFor</span><span class="token punctuation">(</span><span class="token string">&quot;derek&quot;</span><span class="token punctuation">)</span> <span class="token keyword">with</span> ex <span class="token operator">-&gt;</span> printfn $<span class="token string">&quot;{ex}&quot;</span>
</span><span class="code-line"><span class="token comment">// \__ System.Exception: Can&#x27;t schedule break because less than two bouncers are guarding</span>
</span><span class="code-line">shift<span class="token punctuation">.</span><span class="token function">StartGuarding</span><span class="token punctuation">(</span><span class="token string">&quot;mike&quot;</span><span class="token punctuation">)</span>
</span><span class="code-line">shift<span class="token punctuation">.</span><span class="token function">ScheduleBreakFor</span><span class="token punctuation">(</span><span class="token string">&quot;john&quot;</span><span class="token punctuation">)</span>
</span></code></pre></div></div><p>Whenever there is a consistency violation, our shift shouts with an exception.</p><p>How about the rules, is the <code>BouncersShift</code> satisfying all of them?</p><div class="flex flex-col"><span>✅ bouncer can be either guarding or having a break</span> <span>✅ bouncer can report new people only when guarding</span> <span>✅ when scheduling a break, at least two bouncers needs to be guarding</span> <span>✅ no more than 100 people partying</span> <span>✅ at least three bouncers</span></div><p>&quot;Whatever happens during the shift, stays in the shift&quot; one might say, but it is quite visible that the shift protects the rules we defined, so the aggregate boundary is suitable for this particular problem.</p><p>We found good boundaries!</p><p>From now on, we are going to work with both <code>Bouncer</code> and <code>BouncersShift</code>.</p><p>Ok, let&#x27;s move on to the next model.</p><h3 id="solution-2-functional-oriented-approach"><a href="#solution-2-functional-oriented-approach" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Solution #2: Functional-oriented approach</h3><p>This time, we are going to do some lightweight functional acrobatics in order to encode invariants in types.</p><p>Type definitions first!</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token annotation"><span class="token punctuation">[&lt;</span><span class="token class-name">RequireQualifiedAccess</span><span class="token punctuation">&gt;]</span></span>
</span><span class="code-line">  <span class="token keyword">module</span> BouncersShift <span class="token operator">=</span>
</span><span class="code-line">      <span class="token annotation"><span class="token punctuation">[&lt;</span><span class="token class-name">RequireQualifiedAccess</span><span class="token punctuation">&gt;]</span></span>
</span><span class="code-line">      <span class="token keyword">module</span> <span class="token keyword">internal</span> Bouncers <span class="token operator">=</span>
</span><span class="code-line">          <span class="token keyword">type</span> <span class="token class-name">GuardingBouncer</span> <span class="token operator">=</span> <span class="token keyword">private</span> GuardingBouncer <span class="token keyword">of</span> peopleCount<span class="token punctuation">:</span> <span class="token class-name">int</span> <span class="token operator">*</span> name<span class="token punctuation">:</span> <span class="token class-name">string</span>
</span><span class="code-line">          <span class="token keyword">type</span> <span class="token class-name">BouncerHavingABreak</span> <span class="token operator">=</span> <span class="token keyword">private</span> BouncerHavingABreak <span class="token keyword">of</span> peopleCount<span class="token punctuation">:</span> <span class="token class-name">int</span> <span class="token operator">*</span> name<span class="token punctuation">:</span> <span class="token class-name">string</span>
</span><span class="code-line">          <span class="token keyword">type</span> <span class="token class-name">Bouncer</span> <span class="token operator">=</span> Gaurding <span class="token keyword">of</span> <span class="token class-name">GuardingBouncer</span> <span class="token operator">|</span> HavingABreak <span class="token keyword">of</span> <span class="token class-name">BouncerHavingABreak</span>
</span><span class="code-line">
</span><span class="code-line">          <span class="token keyword">type</span> <span class="token class-name">private</span> StartGuarding <span class="token operator">=</span> BouncerHavingABreak <span class="token operator">-&gt;</span> GuardingBouncer
</span><span class="code-line">          <span class="token keyword">type</span> <span class="token class-name">private</span> HaveABreak <span class="token operator">=</span> GuardingBouncer <span class="token operator">-&gt;</span> BouncerHavingABreak
</span><span class="code-line">          <span class="token keyword">type</span> <span class="token class-name">private</span> ReportNewPeople <span class="token operator">=</span> int <span class="token operator">-&gt;</span> GuardingBouncer <span class="token operator">-&gt;</span> GuardingBouncer
</span></code></pre></div></div><p>This time we decided to model a bouncer with a two possible states.</p><p>We do not have the implementation yet, but we delegated the rules to the compiler.</p><p>Let the types guide us.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token comment">// still within internal Bouncers module</span>
</span><span class="code-line"><span class="token keyword">let</span> startGuarding<span class="token punctuation">:</span> <span class="token class-name">StartGuarding</span> <span class="token operator">=</span> <span class="token comment">// BouncerHavingABreak -&gt; GuardingBouncer</span>
</span><span class="code-line">    <span class="token keyword">fun</span> <span class="token punctuation">(</span>BouncerHavingABreak <span class="token punctuation">(</span>count<span class="token punctuation">,</span> name<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">-&gt;</span>
</span><span class="code-line">        GuardingBouncer <span class="token punctuation">(</span>count<span class="token punctuation">,</span> name<span class="token punctuation">)</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">let</span> haveABreak<span class="token punctuation">:</span> <span class="token class-name">HaveABreak</span> <span class="token operator">=</span> <span class="token comment">// GuardingBouncer -&gt; BouncerHavingABreak</span>
</span><span class="code-line">    <span class="token keyword">fun</span> <span class="token punctuation">(</span>GuardingBouncer <span class="token punctuation">(</span>count<span class="token punctuation">,</span> name<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">-&gt;</span>
</span><span class="code-line">        BouncerHavingABreak <span class="token punctuation">(</span>count<span class="token punctuation">,</span> name<span class="token punctuation">)</span>
</span><span class="code-line">        
</span><span class="code-line"><span class="token keyword">let</span> reportNewPeople<span class="token punctuation">:</span> <span class="token class-name">ReportNewPeople</span> <span class="token operator">=</span> <span class="token comment">// int -&gt; GuardingBouncer -&gt; GuardingBouncer</span>
</span><span class="code-line">    <span class="token keyword">fun</span> newPeople <span class="token punctuation">(</span>GuardingBouncer <span class="token punctuation">(</span>count<span class="token punctuation">,</span> name<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">-&gt;</span>
</span><span class="code-line">        GuardingBouncer <span class="token punctuation">(</span>count <span class="token operator">+</span> newPeople<span class="token punctuation">,</span> name<span class="token punctuation">)</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">let</span> countPeople <span class="token punctuation">(</span>bouncer<span class="token punctuation">:</span> <span class="token class-name">Bouncer</span><span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token comment">// Bouncer -&gt; int</span>
</span><span class="code-line">    <span class="token keyword">match</span> bouncer <span class="token keyword">with</span>
</span><span class="code-line">    <span class="token operator">|</span> Guarding <span class="token punctuation">(</span>GuardingBouncer <span class="token punctuation">(</span>count<span class="token punctuation">,</span> _<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">-&gt;</span> count
</span><span class="code-line">    <span class="token operator">|</span> HavingABreak <span class="token punctuation">(</span>BouncerHavingABreak <span class="token punctuation">(</span>count<span class="token punctuation">,</span> _<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">-&gt;</span> count
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">let</span> startShift <span class="token punctuation">(</span>name<span class="token punctuation">:</span> <span class="token class-name">string</span><span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token punctuation">(</span>BouncerHavingABreak <span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> name<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// string -&gt; BouncerHavingABreak</span>
</span></code></pre></div></div><p>The most intersting part here is <code>reportNewPeople</code> function that works only with <code>GuardingBouncer</code>. Also, we added a helper function <code>countPeople</code> so that we are able to provide this number outside of the module.</p><p>Yet again, a <code>Bouncer</code> starts with a break.</p><p>Now, a <code>BouncersShift</code>. This time we will try to encode problems within a shift (previously we used exceptions).</p><p>T Y P E S first!</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token comment">// within public BouncersShift module</span>
</span><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">BouncersShift</span> <span class="token operator">=</span> <span class="token keyword">private</span> BouncersShift <span class="token keyword">of</span> <span class="token punctuation">(</span>Map<span class="token operator">&lt;</span>string<span class="token punctuation">,</span> Bouncers<span class="token punctuation">.</span>Bouncer<span class="token operator">&gt;</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token comment">//            __________ we are representing problems explicitly</span>
</span><span class="code-line"><span class="token comment">//          /</span>
</span><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">BouncersShiftProblem</span> <span class="token operator">=</span> 
</span><span class="code-line">    <span class="token keyword">private</span>
</span><span class="code-line">    <span class="token operator">|</span> CountingRefused <span class="token keyword">of</span> name<span class="token punctuation">:</span> <span class="token class-name">string</span> <span class="token operator">*</span> reason<span class="token punctuation">:</span> <span class="token class-name">string</span>
</span><span class="code-line">    <span class="token operator">|</span> PartyingPeopleLimitReached
</span><span class="code-line">    <span class="token operator">|</span> SchedulingABreakRejected <span class="token keyword">of</span> reason<span class="token punctuation">:</span> <span class="token class-name">string</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token comment">//                                 ______ we are encoding problems in type signature                           </span>
</span><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">StartGuarding</span> <span class="token operator">=</span>  <span class="token comment">//         /</span>
</span><span class="code-line">    string <span class="token operator">-&gt;</span> BouncersShift <span class="token operator">-&gt;</span> Result<span class="token operator">&lt;</span>BouncersShift<span class="token punctuation">,</span> BouncersShiftProblem <span class="token operator">*</span> BouncersShift<span class="token operator">&gt;</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">ScheduleBreakFor</span> <span class="token operator">=</span> 
</span><span class="code-line">    string <span class="token operator">-&gt;</span> BouncersShift <span class="token operator">-&gt;</span> Result<span class="token operator">&lt;</span>BouncersShift<span class="token punctuation">,</span> BouncersShiftProblem <span class="token operator">*</span> BouncersShift<span class="token operator">&gt;</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">ReportNewPeopleComing</span> <span class="token operator">=</span> 
</span><span class="code-line">    string <span class="token operator">-&gt;</span> int <span class="token operator">-&gt;</span> BouncersShift <span class="token operator">-&gt;</span> Result<span class="token operator">&lt;</span>BouncersShift<span class="token punctuation">,</span> BouncersShiftProblem <span class="token operator">*</span> BouncersShift<span class="token operator">&gt;</span>
</span></code></pre></div></div><p>I hope you are wondering why such a strange result of those three operations? Let&#x27;s wait to see the example.</p><p>To be truly functional (and maybe a bit slow?), we are using <code>Map</code> to represent a bouncers within a given shift. We need to adjust our invariants, but this should be pretty simple.</p><span class="mb-8">Rule: <span class="italic">when scheduling a break, at least two bouncers needs to be guarding</span></span><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> <span class="token keyword">private</span> atLeastTwoGuarding <span class="token punctuation">(</span>bouncers<span class="token punctuation">:</span> <span class="token class-name">Map</span><span class="token operator">&lt;</span>string<span class="token punctuation">,</span> Bouncers<span class="token punctuation">.</span>Bouncer<span class="token operator">&gt;</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">  <span class="token keyword">let</span> guardingBouncersCount <span class="token operator">=</span>
</span><span class="code-line">    bouncers<span class="token punctuation">.</span>Values
</span><span class="code-line">    <span class="token operator">|&gt;</span> <span class="token punctuation">(</span>Seq<span class="token punctuation">.</span>cast <span class="token operator">&gt;&gt;</span> List<span class="token punctuation">.</span>ofSeq<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token operator">|&gt;</span> List<span class="token punctuation">.</span>sumBy <span class="token punctuation">(</span><span class="token keyword">fun</span> bouncer <span class="token operator">-&gt;</span>
</span><span class="code-line">        <span class="token keyword">match</span> bouncer <span class="token keyword">with</span>
</span><span class="code-line">        <span class="token operator">|</span> Bouncers<span class="token punctuation">.</span>Guarding _ <span class="token operator">-&gt;</span> <span class="token number">1</span>
</span><span class="code-line">        <span class="token operator">|</span> _ <span class="token operator">-&gt;</span> <span class="token number">0</span>
</span><span class="code-line">    <span class="token punctuation">)</span>
</span><span class="code-line">
</span><span class="code-line">  guardingBouncersCount <span class="token operator">&gt;</span> <span class="token number">2</span>
</span><span class="code-line">
</span></code></pre></div></div><p>I told ya, nothing fancy.</p><span class="mb-8">Rule: <span class="italic">no more than 100 people partying</span></span><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> <span class="token keyword">private</span> reportedLessThan100PeopleWith <span class="token punctuation">(</span>newPeopleComing<span class="token punctuation">:</span> <span class="token class-name">int</span><span class="token punctuation">)</span> <span class="token punctuation">(</span>bouncers<span class="token punctuation">:</span> <span class="token class-name">Map</span><span class="token operator">&lt;</span>string<span class="token punctuation">,</span> Bouncers<span class="token punctuation">.</span>Bouncer<span class="token operator">&gt;</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">  <span class="token keyword">let</span> currentlyPartyingPeople <span class="token operator">=</span> 
</span><span class="code-line">          bouncers<span class="token punctuation">.</span>Values
</span><span class="code-line">          <span class="token operator">|&gt;</span> <span class="token punctuation">(</span>Seq<span class="token punctuation">.</span>cast <span class="token operator">&gt;&gt;</span> List<span class="token punctuation">.</span>ofSeq<span class="token punctuation">)</span>
</span><span class="code-line">          <span class="token operator">|&gt;</span> List<span class="token punctuation">.</span>sumBy Bouncers<span class="token punctuation">.</span>countPeople
</span><span class="code-line">
</span><span class="code-line">  currentlyPartyingPeople <span class="token operator">+</span> newPeopleComing <span class="token operator">&lt;=</span> <span class="token number">100</span>
</span></code></pre></div></div><p>Let&#x27;s assume we&#x27;re going to leave the last rule with the same implementation. Exception will work as a &quot;fail fast&quot;.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> start <span class="token punctuation">(</span>bouncerNames<span class="token punctuation">:</span> <span class="token class-name">string</span> list<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token comment">// string list -&gt; BouncersShift</span>
</span><span class="code-line">  ensureAtLeastThreeBouncers bouncerNames
</span><span class="code-line">  <span class="token keyword">let</span> bouncers <span class="token operator">=</span> 
</span><span class="code-line">      bouncerNames 
</span><span class="code-line">      <span class="token operator">|&gt;</span> List<span class="token punctuation">.</span>map <span class="token punctuation">(</span><span class="token keyword">fun</span> name <span class="token operator">-&gt;</span> <span class="token punctuation">(</span>name<span class="token punctuation">,</span> Bouncers<span class="token punctuation">.</span>HavingABreak <span class="token punctuation">(</span>Bouncers<span class="token punctuation">.</span>startShift name<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class="code-line">      <span class="token operator">|&gt;</span> Map<span class="token punctuation">.</span>ofList
</span><span class="code-line">      
</span><span class="code-line">  BouncersShift <span class="token punctuation">(</span>bouncers<span class="token punctuation">)</span>
</span></code></pre></div></div><p>Neat. We have all building blocks to start implementing three functions: <code>startGuarding</code>, <code>haveABreak</code> and <code>reportNewPeopleComing</code>.</p><p>First, let a <code>Bouncer</code> start guarding:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> startGuarding<span class="token punctuation">:</span> <span class="token class-name">StartGuarding</span> <span class="token operator">=</span> 
</span><span class="code-line">  <span class="token comment">// string -&gt; BouncersShift -&gt; Result&lt;BouncersShift, BouncersShiftProblem * BouncersShift&gt;</span>
</span><span class="code-line">  <span class="token keyword">fun</span> <span class="token punctuation">(</span>name<span class="token punctuation">:</span> <span class="token class-name">string</span><span class="token punctuation">)</span> <span class="token punctuation">(</span>BouncersShift bouncers<span class="token punctuation">)</span> <span class="token operator">-&gt;</span>
</span><span class="code-line">      <span class="token keyword">let</span> bouncer <span class="token operator">=</span> bouncers <span class="token operator">|&gt;</span> Map<span class="token punctuation">.</span>find name
</span><span class="code-line">      <span class="token keyword">match</span> bouncer <span class="token keyword">with</span>
</span><span class="code-line">      <span class="token operator">|</span> Bouncers<span class="token punctuation">.</span>HavingABreak bouncerHavingABreak <span class="token operator">-&gt;</span> 
</span><span class="code-line">        <span class="token keyword">let</span> guardingBouncer <span class="token operator">=</span>
</span><span class="code-line">            bouncerHavingABreak 
</span><span class="code-line">                <span class="token operator">|&gt;</span> Bouncers<span class="token punctuation">.</span>startGuarding
</span><span class="code-line">                <span class="token operator">|&gt;</span> Bouncers<span class="token punctuation">.</span>Guarding
</span><span class="code-line">        Ok <span class="token punctuation">(</span>BouncersShift <span class="token punctuation">(</span>bouncers <span class="token operator">|&gt;</span> Map<span class="token punctuation">.</span>update name guardingBouncer<span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class="code-line">      <span class="token operator">|</span> _ <span class="token operator">-&gt;</span> Ok <span class="token punctuation">(</span>BouncersShift bouncers<span class="token punctuation">)</span>
</span></code></pre></div></div><p>No problems here as a <code>Bouncer</code> can always start guarding. As this is within the <code>BouncersShift</code> module, we can match on the particular state and then wrap the given bouncer again.</p><p>This might be a bit tiresome, but hey, we wanted the &quot;type-safety&quot;, right?</p><p>Next? Scheduling a break for a given <code>Bouncer</code>.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> scheduleBreakFor<span class="token punctuation">:</span> <span class="token class-name">ScheduleBreakFor</span> <span class="token operator">=</span>
</span><span class="code-line">  <span class="token comment">// string -&gt; BouncersShift -&gt; Result&lt;BouncersShift, BouncersShiftProblem * BouncersShift&gt;</span>
</span><span class="code-line">  <span class="token keyword">fun</span> <span class="token punctuation">(</span>name<span class="token punctuation">:</span> <span class="token class-name">string</span><span class="token punctuation">)</span> <span class="token punctuation">(</span>BouncersShift <span class="token punctuation">(</span>bouncers<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">-&gt;</span>
</span><span class="code-line">      <span class="token keyword">if</span> atLeastTwoGuarding bouncers <span class="token comment">// 👈 consistency rule</span>
</span><span class="code-line">        <span class="token keyword">then</span>
</span><span class="code-line">            <span class="token keyword">let</span> bouncer <span class="token operator">=</span> bouncers <span class="token operator">|&gt;</span> Map<span class="token punctuation">.</span>find name
</span><span class="code-line">            <span class="token keyword">match</span> bouncer <span class="token keyword">with</span>
</span><span class="code-line">            <span class="token operator">|</span> Bouncers<span class="token punctuation">.</span>Guarding guardingBouncer <span class="token operator">-&gt;</span> 
</span><span class="code-line">                <span class="token keyword">let</span> bouncerHavingABreak <span class="token operator">=</span>
</span><span class="code-line">                    guardingBouncer
</span><span class="code-line">                        <span class="token operator">|&gt;</span> Bouncers<span class="token punctuation">.</span>haveABreak <span class="token comment">// 👈 consistency rule guided by a compiler</span>
</span><span class="code-line">                        <span class="token operator">|&gt;</span> Bouncers<span class="token punctuation">.</span>HavingABreak
</span><span class="code-line">                Ok <span class="token punctuation">(</span>BouncersShift <span class="token punctuation">(</span>bouncers <span class="token operator">|&gt;</span> Map<span class="token punctuation">.</span>update name bouncerHavingABreak<span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token operator">|</span> Bouncers<span class="token punctuation">.</span>HavingABreak _ <span class="token operator">-&gt;</span> Ok <span class="token punctuation">(</span>BouncersShift bouncers<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token keyword">else</span> <span class="token function">Error</span><span class="token punctuation">(</span>SchedulingABreakRejected <span class="token string">&quot;at least two bounces need to be guarding&quot;</span><span class="token punctuation">,</span> BouncersShift bouncers<span class="token punctuation">)</span> <span class="token comment">// ⛔ consistency violation</span>
</span></code></pre></div></div><p>As this function is scoped to the <code>BouncersShift</code> module, we are able to reach <code>Bouncer</code> type and match on it.</p><p>Ok, without further ado, we are missing the last operation, <code>reportNewPeopleComing</code>, here it comes!</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> reportNewPeopleComing<span class="token punctuation">:</span> <span class="token class-name">ReportNewPeopleComing</span> <span class="token operator">=</span>
</span><span class="code-line">  <span class="token comment">// string -&gt; int -&gt; BouncersShift -&gt; Result&lt;BouncersShift, BouncersShiftProblem * BouncersShift&gt;</span>
</span><span class="code-line">  <span class="token keyword">fun</span> <span class="token punctuation">(</span>name<span class="token punctuation">:</span> <span class="token class-name">string</span><span class="token punctuation">)</span> <span class="token punctuation">(</span>newPeopleComing<span class="token punctuation">:</span> <span class="token class-name">int</span><span class="token punctuation">)</span> <span class="token punctuation">(</span>BouncersShift <span class="token punctuation">(</span>bouncers<span class="token punctuation">)</span><span class="token punctuation">:</span> BouncersShift<span class="token punctuation">)</span> <span class="token operator">-&gt;</span>
</span><span class="code-line">    <span class="token keyword">if</span> bouncers <span class="token operator">|&gt;</span> reportedLessThan100PeopleWith newPeopleComing <span class="token comment">// 👈 consistency rule</span>
</span><span class="code-line">      <span class="token keyword">then</span>
</span><span class="code-line">          <span class="token keyword">let</span> bouncer <span class="token operator">=</span> bouncers <span class="token operator">|&gt;</span> Map<span class="token punctuation">.</span>find name
</span><span class="code-line">          <span class="token keyword">match</span> bouncer <span class="token keyword">with</span>
</span><span class="code-line">          <span class="token operator">|</span> Bouncers<span class="token punctuation">.</span>Guarding guardingBouncer <span class="token operator">-&gt;</span> 
</span><span class="code-line">            <span class="token keyword">let</span> guardingBouncer <span class="token operator">=</span>
</span><span class="code-line">                guardingBouncer 
</span><span class="code-line">                    <span class="token operator">|&gt;</span> Bouncers<span class="token punctuation">.</span>reportNewPeople newPeopleComing <span class="token comment">// 👈 consistency rule guided by a compiler</span>
</span><span class="code-line">                    <span class="token operator">|&gt;</span> Bouncers<span class="token punctuation">.</span>Guarding
</span><span class="code-line">            Ok <span class="token punctuation">(</span>BouncersShift <span class="token punctuation">(</span>bouncers <span class="token operator">|&gt;</span> Map<span class="token punctuation">.</span>update name guardingBouncer<span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class="code-line">          <span class="token operator">|</span> Bouncers<span class="token punctuation">.</span>HavingABreak _ <span class="token operator">-&gt;</span> <span class="token function">Error</span><span class="token punctuation">(</span>CountingRefused <span class="token punctuation">(</span>name<span class="token punctuation">,</span> <span class="token string">&quot;having a break&quot;</span><span class="token punctuation">)</span><span class="token punctuation">,</span> BouncersShift bouncers<span class="token punctuation">)</span> <span class="token comment">// ⛔ consistency violation</span>
</span><span class="code-line">      <span class="token keyword">else</span> <span class="token function">Error</span><span class="token punctuation">(</span>PartyingPeopleLimitReached<span class="token punctuation">,</span> BouncersShift bouncers<span class="token punctuation">)</span> <span class="token comment">// ⛔ consistency violation</span>
</span></code></pre></div></div><p>This is probably the most interesting function so far! Runtime checks didn&#x27;t disappear, so still we need to match on cases.</p><p>But yet again, we are guided by the compiler on &quot;what is possible&quot; within the domain we defined.</p><p>What is not possible and should result with a problem, gets encoded in types properly.</p><p>As we are dealing with problems explicitly in types, we need to have some helper function:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> handleProblems handleProblem bouncersShift <span class="token operator">=</span>
</span><span class="code-line"><span class="token comment">// (BouncersShiftProblem -&gt; unit) -&gt; Result&lt;BouncersShift, BouncersShiftProblem * BouncersShift&gt; -&gt; BouncersShift</span>
</span><span class="code-line">    <span class="token keyword">match</span> bouncersShift <span class="token keyword">with</span>
</span><span class="code-line">    <span class="token operator">|</span> Ok bouncersShift <span class="token operator">-&gt;</span> bouncersShift
</span><span class="code-line">    <span class="token operator">|</span> Error <span class="token punctuation">(</span>error<span class="token punctuation">,</span> bouncersShift<span class="token punctuation">)</span> <span class="token operator">-&gt;</span> 
</span><span class="code-line">        handleProblem error
</span><span class="code-line">        bouncersShift
</span><span class="code-line">
</span><span class="code-line"><span class="token comment">//                                       ____ built-in function!</span>
</span><span class="code-line"><span class="token comment">//                                     /</span>
</span><span class="code-line"><span class="token keyword">let</span> ignoreProblems <span class="token operator">=</span> handleProblems ignore
</span></code></pre></div></div><p>It&#x27;s not a brave attitude to ignore problems (in one&#x27;s life), but this time we are going to do so.</p><p>Finally, we arrived at the point when we can use our model. Note that the same sequence of operations were used in the OOP solution.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> shift <span class="token operator">=</span> BouncersShift<span class="token punctuation">.</span>start <span class="token punctuation">[</span><span class="token string">&quot;mike&quot;</span><span class="token punctuation">;</span><span class="token string">&quot;john&quot;</span><span class="token punctuation">;</span><span class="token string">&quot;derek&quot;</span><span class="token punctuation">]</span>
</span><span class="code-line">
</span><span class="code-line">shift
</span><span class="code-line"><span class="token operator">|&gt;</span> BouncersShift<span class="token punctuation">.</span>startGuarding <span class="token string">&quot;mike&quot;</span>
</span><span class="code-line"><span class="token operator">|&gt;</span> <span class="token punctuation">(</span>ignoreProblems <span class="token operator">&gt;&gt;</span> BouncersShift<span class="token punctuation">.</span>startGuarding <span class="token string">&quot;derek&quot;</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token operator">|&gt;</span> <span class="token punctuation">(</span>ignoreProblems <span class="token operator">&gt;&gt;</span> BouncersShift<span class="token punctuation">.</span>startGuarding <span class="token string">&quot;john&quot;</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token operator">|&gt;</span> <span class="token punctuation">(</span>ignoreProblems <span class="token operator">&gt;&gt;</span> BouncersShift<span class="token punctuation">.</span>reportNewPeopleComing <span class="token string">&quot;mike&quot;</span> <span class="token number">20</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token operator">|&gt;</span> <span class="token punctuation">(</span>ignoreProblems <span class="token operator">&gt;&gt;</span> BouncersShift<span class="token punctuation">.</span>scheduleBreakFor <span class="token string">&quot;mike&quot;</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token operator">|&gt;</span> <span class="token punctuation">(</span>ignoreProblems <span class="token operator">&gt;&gt;</span> BouncersShift<span class="token punctuation">.</span>reportNewPeopleComing <span class="token string">&quot;mike&quot;</span> <span class="token number">20</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token comment">//                                        \_______ we could throw an exception here!</span>
</span><span class="code-line"><span class="token operator">|&gt;</span> <span class="token punctuation">(</span>ignoreProblems <span class="token operator">&gt;&gt;</span> BouncersShift<span class="token punctuation">.</span>reportNewPeopleComing <span class="token string">&quot;derek&quot;</span> <span class="token number">40</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token operator">|&gt;</span> <span class="token punctuation">(</span>ignoreProblems <span class="token operator">&gt;&gt;</span> BouncersShift<span class="token punctuation">.</span>reportNewPeopleComing <span class="token string">&quot;derek&quot;</span> <span class="token number">40</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token operator">|&gt;</span> <span class="token punctuation">(</span>ignoreProblems <span class="token operator">&gt;&gt;</span> BouncersShift<span class="token punctuation">.</span>reportNewPeopleComing <span class="token string">&quot;derek&quot;</span> <span class="token number">40</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token comment">//                                        \_______ we could throw an exception here!</span>
</span><span class="code-line"><span class="token operator">|&gt;</span> <span class="token punctuation">(</span>ignoreProblems <span class="token operator">&gt;&gt;</span> BouncersShift<span class="token punctuation">.</span>scheduleBreakFor <span class="token string">&quot;derek&quot;</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token comment">//                                        \_______ we could throw an exception here!</span>
</span><span class="code-line"><span class="token operator">|&gt;</span> <span class="token punctuation">(</span>ignoreProblems <span class="token operator">&gt;&gt;</span> BouncersShift<span class="token punctuation">.</span>startGuarding <span class="token string">&quot;mike&quot;</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token operator">|&gt;</span> <span class="token punctuation">(</span>ignoreProblems <span class="token operator">&gt;&gt;</span> BouncersShift<span class="token punctuation">.</span>scheduleBreakFor <span class="token string">&quot;derek&quot;</span><span class="token punctuation">)</span>
</span><span class="code-line">
</span></code></pre></div></div><p>It might be hard to grasp the output of such pipeline so let me help you with visualizing it:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="code-highlight language-sh"><span class="code-line">Ok
</span><span class="code-line">    BouncersShift
</span><span class="code-line">  <span class="token punctuation">(</span>map
</span><span class="code-line">     <span class="token punctuation">[</span><span class="token punctuation">(</span><span class="token string">&quot;derek&quot;</span>, HavingABreak <span class="token punctuation">(</span>BouncerHavingABreak <span class="token punctuation">(</span><span class="token number">80</span>, <span class="token string">&quot;derek&quot;</span><span class="token punctuation">))</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">      <span class="token punctuation">(</span><span class="token string">&quot;john&quot;</span>, Guarding <span class="token punctuation">(</span>GuardingBouncer <span class="token punctuation">(</span><span class="token number">0</span>, <span class="token string">&quot;john&quot;</span><span class="token punctuation">))</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">      <span class="token punctuation">(</span><span class="token string">&quot;mike&quot;</span>, Guarding <span class="token punctuation">(</span>GuardingBouncer <span class="token punctuation">(</span><span class="token number">20</span>, <span class="token string">&quot;mike&quot;</span><span class="token punctuation">))</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
</span><span class="code-line">
</span></code></pre></div></div><p>As mentioned at the beginning, in this solution we wanted to let our friend, the compiler, help us, mere mortals, leading to the pits of success in &quot;a lightweight fashion&quot;.</p><p>But wait a minute. As we encoded some possible states of a single <code>Bouncer</code> in types, this means that some states are possible for some operations, whereas other combinations should never happen 🤔</p><p>I bet there is a good model for tackling such problem in which some transitions between states are possible and others do not affect state changes.</p><h3 id="solution-3-functional-state-machine-like-approach"><a href="#solution-3-functional-state-machine-like-approach" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Solution #3: Functional, State Machine-like approach</h3><p>What would you say if a <code>Bouncer</code> was represented by a state machine?</p><p>We&#x27;ve already seen that there are three behaviors of a bouncer: start guarding, have a break and report new people coming.</p><p>It turns out those are commands we are sending to the machine. And in the <a href="#solution-2-functional-oriented-approach">&quot;Solution #2: Functional-oriented approach&quot;</a>, we know that there are two possible states: <code>GuardingBouncer</code> and <code>HavingABreakBouncer</code>.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/bouncer-fsm.png" class="max-h-[30rem]"/></div><div class="italic mx-24">A bouncer as a state machine.</div></div><p>To work with lightweight state machines, we need to define a new module: <code>StateMachines</code>.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">module</span> StateMachines <span class="token operator">=</span>
</span><span class="code-line">    <span class="token keyword">type</span> <span class="token class-name">FSM</span><span class="token operator">&lt;</span>&#x27;Input<span class="token punctuation">,</span> &#x27;Output<span class="token operator">&gt;</span> <span class="token operator">=</span> FSM <span class="token keyword">of</span> &#x27;Output
</span><span class="code-line">    <span class="token comment">//          \______ used  mostly for documentation - what input is possible</span>
</span><span class="code-line">    <span class="token keyword">type</span> <span class="token class-name">Evolve</span><span class="token operator">&lt;</span>&#x27;Input<span class="token punctuation">,</span> &#x27;Output<span class="token punctuation">,</span> &#x27;FSM<span class="token operator">&gt;</span> <span class="token operator">=</span> &#x27;Input <span class="token operator">-&gt;</span> &#x27;FSM <span class="token operator">-&gt;</span> &#x27;Output <span class="token operator">*</span> &#x27;FSM
</span><span class="code-line">    <span class="token keyword">type</span> <span class="token class-name">Aggregate</span><span class="token operator">&lt;</span>&#x27;Command<span class="token punctuation">,</span> &#x27;Event<span class="token punctuation">,</span> &#x27;State<span class="token operator">&gt;</span> <span class="token operator">=</span> FSM<span class="token operator">&lt;</span>&#x27;Command<span class="token punctuation">,</span> &#x27;Event list <span class="token operator">*</span> &#x27;State<span class="token operator">&gt;</span>
</span><span class="code-line">    <span class="token comment">//                           &#x27;Input   ____________/                \________ &#x27;Output with implicit state</span>
</span></code></pre></div></div><p><code>FSM</code> stands for <code>Finite State Machine</code>.</p><p>Note that <code>Evolve</code> function and <code>FSM</code> type are handled separately. There is a way to handle them both together, but this will come in the future tale (is it a clickbait? Well, maybe).</p><p>What is really interesting, an <code>Aggregate</code> works with commands, events and state. As we implicitly encoded state, when we will evolve our finite state machine, we are going to emit the current state <strong>and</strong> some facts that happened during the evolution.</p><p>As it is still functional approach, let us start with types firstly.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token annotation"><span class="token punctuation">[&lt;</span><span class="token class-name">RequireQualifiedAccess</span><span class="token punctuation">&gt;]</span></span>
</span><span class="code-line">  <span class="token keyword">module</span> <span class="token keyword">internal</span> Bouncers <span class="token operator">=</span>
</span><span class="code-line">    <span class="token keyword">open</span> StateMachines
</span><span class="code-line">    <span class="token comment">//      \_________ we use types from new module</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">type</span> <span class="token class-name">BouncerCommand</span> <span class="token operator">=</span> <span class="token keyword">private</span> StartGuarding <span class="token operator">|</span> HaveABreak <span class="token operator">|</span> ReportNewPeopleComing <span class="token keyword">of</span> count<span class="token punctuation">:</span> <span class="token class-name">int</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">type</span> <span class="token class-name">BouncerDetails</span> <span class="token operator">=</span> <span class="token keyword">private</span> <span class="token punctuation">{</span> name<span class="token punctuation">:</span> <span class="token class-name">string</span><span class="token punctuation">;</span> count<span class="token punctuation">:</span> <span class="token class-name">int</span> <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">type</span> <span class="token class-name">BouncerState</span> <span class="token operator">=</span> Guarding <span class="token keyword">of</span> bouncer<span class="token punctuation">:</span> <span class="token class-name">BouncerDetails</span> <span class="token operator">|</span> HavingABreak <span class="token keyword">of</span> bouncer<span class="token punctuation">:</span> <span class="token class-name">BouncerDetails</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">//       ______ we are introducing facts happening inside of the state machine</span>
</span><span class="code-line">    <span class="token comment">//      /</span>
</span><span class="code-line">    <span class="token keyword">type</span> <span class="token class-name">BouncerEvent</span> <span class="token operator">=</span>
</span><span class="code-line">      <span class="token operator">|</span> StartedGuarding <span class="token operator">|</span> StartedABreak <span class="token operator">|</span> CountingRefused <span class="token keyword">of</span> reason<span class="token punctuation">:</span> <span class="token class-name">string</span> <span class="token operator">|</span> ReportedCount <span class="token keyword">of</span> count<span class="token punctuation">:</span> <span class="token class-name">int</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">type</span> <span class="token class-name">Bouncer</span> <span class="token operator">=</span> Bouncer <span class="token keyword">of</span> <span class="token class-name">Aggregate</span><span class="token operator">&lt;</span>BouncerCommand<span class="token punctuation">,</span> BouncerEvent<span class="token punctuation">,</span> BouncerState<span class="token operator">&gt;</span>
</span><span class="code-line">    <span class="token keyword">type</span> <span class="token class-name">private</span> EvolveBouncer <span class="token operator">=</span> Evolve<span class="token operator">&lt;</span>BouncerCommand<span class="token punctuation">,</span> BouncerEvent list <span class="token operator">*</span> BouncerState<span class="token punctuation">,</span> Bouncer<span class="token operator">&gt;</span>
</span></code></pre></div></div><p>So now we defined all our operations as commands. Instead of &quot;problems&quot;, that we used in <a href="#solution-2-functional-oriented-approach">&quot;Solution #2: Functional-oriented approach&quot;</a>, we are naming those as &quot;facts&quot; or &quot;events&quot;.</p><p>We need to bring evolution of a <code>Bouncer</code> state machine into life!</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> <span class="token keyword">private</span> NoEvents <span class="token operator">=</span> List<span class="token punctuation">.</span>empty
</span><span class="code-line"><span class="token keyword">let</span> <span class="token keyword">private</span> evolve<span class="token punctuation">:</span> <span class="token class-name">EvolveBouncer</span> <span class="token operator">=</span> <span class="token comment">// BouncerCommand -&gt; Bouncer -&gt; (BouncerEvent list * BouncerState) * Bouncer</span>
</span><span class="code-line">    <span class="token keyword">fun</span> <span class="token punctuation">(</span>cmd<span class="token punctuation">:</span> <span class="token class-name">BouncerCommand</span><span class="token punctuation">)</span> <span class="token punctuation">(</span>bouncer<span class="token punctuation">:</span> <span class="token class-name">Bouncer</span><span class="token punctuation">)</span> <span class="token operator">-&gt;</span>
</span><span class="code-line">        <span class="token keyword">let</span> <span class="token punctuation">(</span><span class="token function">Bouncer</span><span class="token punctuation">(</span>FSM <span class="token punctuation">(</span>events<span class="token punctuation">,</span> bouncer&#x27;<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">=</span> bouncer
</span><span class="code-line">
</span><span class="code-line">        <span class="token keyword">let</span> output <span class="token operator">=</span> <span class="token comment">// (BouncerEvent list * BouncerState) * Bouncer</span>
</span><span class="code-line">            <span class="token keyword">match</span> cmd<span class="token punctuation">,</span> bouncer&#x27; <span class="token keyword">with</span>
</span><span class="code-line">            <span class="token operator">|</span> StartGuarding<span class="token punctuation">,</span> Guarding _ <span class="token operator">-&gt;</span> NoEvents<span class="token punctuation">,</span> bouncer&#x27;
</span><span class="code-line">            <span class="token operator">|</span> HaveABreak<span class="token punctuation">,</span> Guarding bouncer&#x27;&#x27; <span class="token operator">-&gt;</span> <span class="token punctuation">[</span>StartedABreak<span class="token punctuation">]</span><span class="token punctuation">,</span> HavingABreak bouncer&#x27;&#x27;
</span><span class="code-line">            <span class="token operator">|</span> StartGuarding<span class="token punctuation">,</span> HavingABreak bouncer&#x27;&#x27; <span class="token operator">-&gt;</span> <span class="token punctuation">[</span>StartedGuarding<span class="token punctuation">]</span><span class="token punctuation">,</span> Guarding bouncer&#x27;&#x27;
</span><span class="code-line">            <span class="token operator">|</span> HaveABreak<span class="token punctuation">,</span> HavingABreak _ <span class="token operator">-&gt;</span> NoEvents<span class="token punctuation">,</span> bouncer&#x27;
</span><span class="code-line">            <span class="token operator">|</span> ReportNewPeopleComing count<span class="token punctuation">,</span> Guarding bouncer&#x27;&#x27; <span class="token operator">-&gt;</span> <span class="token comment">// 👈 consistency rule</span>
</span><span class="code-line">                <span class="token punctuation">[</span>ReportedCount count<span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token keyword computation-expression">Guarding</span> <span class="token punctuation">{</span> bouncer&#x27;&#x27; <span class="token keyword">with</span> count <span class="token operator">=</span> bouncer&#x27;&#x27;<span class="token punctuation">.</span>count <span class="token operator">+</span> count <span class="token punctuation">}</span>
</span><span class="code-line">            <span class="token operator">|</span> ReportNewPeopleComing _<span class="token punctuation">,</span> HavingABreak _ <span class="token operator">-&gt;</span> <span class="token punctuation">[</span>CountingRefused <span class="token string">&quot;I am having a break&quot;</span><span class="token punctuation">]</span><span class="token punctuation">,</span> bouncer&#x27; <span class="token comment">// ⛔ consistency violation</span>
</span><span class="code-line">
</span><span class="code-line">        <span class="token keyword">let</span> <span class="token punctuation">(</span>newEvents<span class="token punctuation">,</span> newBouncerState<span class="token punctuation">)</span> <span class="token operator">=</span> output
</span><span class="code-line">
</span><span class="code-line">        output<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token function">Bouncer</span><span class="token punctuation">(</span><span class="token function">FSM</span><span class="token punctuation">(</span>events <span class="token operator">|&gt;</span> <span class="token keyword">with</span>&#x27; newEvents<span class="token punctuation">,</span> newBouncerState<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
</span></code></pre></div></div><p>Everything is in this single function. All possible transitions between the states.</p><p>As this function is private, which is a good thing, we need to give some public API.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> startShift name <span class="token operator">=</span> <span class="token function">Bouncer</span><span class="token punctuation">(</span><span class="token function">FSM</span><span class="token punctuation">(</span>NoEvents<span class="token punctuation">,</span> <span class="token keyword computation-expression">HavingABreak</span> <span class="token punctuation">{</span> name <span class="token operator">=</span> name<span class="token punctuation">;</span> count <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">let</span> haveABreak <span class="token operator">=</span> evolve HaveABreak
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">let</span> startGuarding <span class="token operator">=</span> evolve StartGuarding
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">let</span> reportNewPeopleComing count <span class="token operator">=</span> evolve <span class="token punctuation">(</span>ReportNewPeopleComing count<span class="token punctuation">)</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">let</span> countPeople <span class="token punctuation">(</span><span class="token punctuation">(</span>Bouncer <span class="token punctuation">(</span><span class="token function">FSM</span><span class="token punctuation">(</span><span class="token punctuation">(</span>_<span class="token punctuation">,</span> bouncer&#x27;<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">:</span> Bouncer<span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">    <span class="token keyword">match</span> bouncer&#x27; <span class="token keyword">with</span>
</span><span class="code-line">    <span class="token operator">|</span> Guarding guardingBouncerDetails <span class="token operator">-&gt;</span> guardingBouncerDetails<span class="token punctuation">.</span>count
</span><span class="code-line">    <span class="token operator">|</span> HavingABreak havingABreakBouncerDetails <span class="token operator">-&gt;</span> havingABreakBouncerDetails<span class="token punctuation">.</span>count
</span></code></pre></div></div><p>Yet again, we need to expose <code>countPeople</code> helper function and we already know it will be used by the <code>BouncersShift</code>.</p><p>Can we represent a <code>BouncersShift</code> as a state machine too?</p><p>Tom clearly stated that we need to maintain the &quot;luxury&quot; level of their clubs. So keeping people outside of the club when limits are reached sounds like a good indicator for having the state when there are no more people allowed and people are allowed to enter.</p><div class="flex justify-center items-center flex-col"><div class="flex justify-between items-center"><img src="https://talesfrom.dev/static/images/bouncers-shift-fsm.png" class="max-h-[40rem]"/></div><div class="italic mx-24">A shift as a state machine.</div></div><p>You know with what we are going to start firstly, right?</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">BouncersShiftCommand</span> <span class="token operator">=</span> 
</span><span class="code-line">  <span class="token keyword">private</span> StartGuarding <span class="token keyword">of</span> name<span class="token punctuation">:</span> <span class="token class-name">string</span> <span class="token operator">|</span> ScheduleBreakFor <span class="token keyword">of</span> name<span class="token punctuation">:</span> <span class="token class-name">string</span> <span class="token operator">|</span> ReportNewPeopleComing <span class="token keyword">of</span> name<span class="token punctuation">:</span> <span class="token class-name">string</span> <span class="token operator">*</span> count<span class="token punctuation">:</span> <span class="token class-name">int</span>
</span><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">BouncersShiftDetails</span> <span class="token operator">=</span> <span class="token keyword">private</span> <span class="token punctuation">{</span> bouncers<span class="token punctuation">:</span> <span class="token class-name">Map</span><span class="token operator">&lt;</span>string<span class="token punctuation">,</span> Bouncers<span class="token punctuation">.</span>Bouncer<span class="token operator">&gt;</span> <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token comment">//       ______ we are introducing facts happening inside of the state machine</span>
</span><span class="code-line">    <span class="token comment">//      /</span>
</span><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">BouncersShiftEvent</span> <span class="token operator">=</span> 
</span><span class="code-line">  <span class="token operator">|</span> StartedGuarding <span class="token keyword">of</span> name<span class="token punctuation">:</span> <span class="token class-name">string</span> <span class="token operator">|</span> ScheduledBreakFor <span class="token keyword">of</span> name<span class="token punctuation">:</span> <span class="token class-name">string</span>
</span><span class="code-line">  <span class="token operator">|</span> CountReported <span class="token keyword">of</span> name<span class="token punctuation">:</span> <span class="token class-name">string</span> <span class="token operator">*</span> count<span class="token punctuation">:</span> <span class="token class-name">int</span> <span class="token operator">|</span> CountingRefused <span class="token keyword">of</span> name<span class="token punctuation">:</span> <span class="token class-name">string</span> <span class="token operator">*</span> reason<span class="token punctuation">:</span> <span class="token class-name">string</span>
</span><span class="code-line">  <span class="token operator">|</span> PartyingPeopleLimitReached <span class="token operator">|</span> SchedulingABreakRejected <span class="token keyword">of</span> reason<span class="token punctuation">:</span> <span class="token class-name">string</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">BouncersShiftState</span> <span class="token operator">=</span> 
</span><span class="code-line">  <span class="token keyword">private</span> NoMorePeopleAllowed <span class="token keyword">of</span> <span class="token class-name">BouncersShiftDetails</span> <span class="token operator">|</span> MorePeopleAllowed <span class="token keyword">of</span> <span class="token class-name">BouncersShiftDetails</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">BouncersShift</span> <span class="token operator">=</span> 
</span><span class="code-line">  <span class="token keyword">private</span> BouncersShift <span class="token keyword">of</span> <span class="token class-name">Aggregate</span><span class="token operator">&lt;</span>BouncersShiftCommand<span class="token punctuation">,</span> BouncersShiftEvent<span class="token punctuation">,</span> BouncersShiftState<span class="token operator">&gt;</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">private</span> EvolveBouncersShift <span class="token operator">=</span> 
</span><span class="code-line">  Evolve<span class="token operator">&lt;</span>BouncersShiftCommand<span class="token punctuation">,</span> BouncersShiftEvent list <span class="token operator">*</span> BouncersShiftState<span class="token punctuation">,</span> BouncersShift<span class="token operator">&gt;</span>
</span></code></pre></div></div><p>We modeled aforementioned <code>NoMorePeopleAllowed</code> and <code>MorePeopleAllowed</code> states explicitly. From the state machine transition diagram we can see that even though the club does not allow for more people, bouncers can go for breaks as usual.</p><p>Let&#x27;s see how could we evolve such machine.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> evolve<span class="token punctuation">:</span> <span class="token class-name">EvolveBouncersShift</span> <span class="token operator">=</span> <span class="token comment">// BouncersShiftCommand -&gt; BouncersShift -&gt; (BouncersShiftEvent list * BouncersShiftState) * BouncersShift</span>
</span><span class="code-line">  <span class="token keyword">fun</span> <span class="token punctuation">(</span>cmd<span class="token punctuation">:</span> <span class="token class-name">BouncersShiftCommand</span><span class="token punctuation">)</span> <span class="token punctuation">(</span>bouncersShift<span class="token punctuation">:</span> <span class="token class-name">BouncersShift</span><span class="token punctuation">)</span> <span class="token operator">-&gt;</span>
</span><span class="code-line">    <span class="token keyword">let</span> <span class="token punctuation">(</span><span class="token function">BouncersShift</span><span class="token punctuation">(</span><span class="token function">FSM</span><span class="token punctuation">(</span>events<span class="token punctuation">,</span> <span class="token punctuation">(</span>shiftDetails<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">=</span> bouncersShift
</span><span class="code-line">    
</span><span class="code-line">    <span class="token keyword">let</span> result <span class="token operator">=</span> <span class="token comment">// (BouncersShiftEvent list * BouncersShiftState) * BouncersShift</span>
</span><span class="code-line">        <span class="token keyword">match</span> shiftDetails <span class="token keyword">with</span>
</span><span class="code-line">        <span class="token operator">|</span> NoMorePeopleAllowed shiftDetails&#x27; <span class="token operator">-&gt;</span>
</span><span class="code-line">            handleShiftWhenNoMorePeopleAllowed cmd shiftDetails&#x27;
</span><span class="code-line">        <span class="token operator">|</span> MorePeopleAllowed shiftDetails&#x27; <span class="token operator">-&gt;</span>
</span><span class="code-line">            handleShiftWhenMorePeopleAllowed cmd shiftDetails&#x27;
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">let</span> <span class="token punctuation">(</span>newEvents&#x27;<span class="token punctuation">,</span> squadState<span class="token punctuation">)</span> <span class="token operator">=</span> result
</span><span class="code-line">
</span><span class="code-line">    result<span class="token punctuation">,</span> <span class="token function">BouncersShift</span><span class="token punctuation">(</span><span class="token function">FSM</span><span class="token punctuation">(</span>events <span class="token operator">|&gt;</span> List<span class="token punctuation">.</span>append newEvents&#x27;<span class="token punctuation">,</span> squadState<span class="token punctuation">)</span><span class="token punctuation">)</span>
</span></code></pre></div></div><p>It might be too intimidating to show all at once, so let&#x27;s assume we decided to abstract away some details. As <code>handleShiftWhenMorePeopleAllowed</code> function is much more interesting, because it contains the transition to a &quot;quasi-terminate&quot; state, let&#x27;s see how it could look like.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> handleShiftWhenMorePeopleAllowed <span class="token punctuation">(</span>cmd<span class="token punctuation">:</span> <span class="token class-name">BouncersShiftCommand</span><span class="token punctuation">)</span> <span class="token punctuation">(</span>shiftDetails&#x27;<span class="token punctuation">:</span> BouncersShiftDetails<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token comment">// BouncersShiftCommand -&gt; BouncersShiftDetails -&gt; (BouncersShiftEvent list * BouncersShiftState) * BouncersShift</span>
</span><span class="code-line">    <span class="token keyword">match</span> cmd <span class="token keyword">with</span>
</span><span class="code-line">    <span class="token operator">|</span> StartGuarding bouncerName <span class="token operator">-&gt;</span>
</span><span class="code-line">        handleBouncersWhenMorePeopleAllowed <span class="token punctuation">(</span>Bouncers<span class="token punctuation">.</span>startGuarding<span class="token punctuation">)</span> bouncerName shiftDetails&#x27;
</span><span class="code-line">
</span><span class="code-line">    <span class="token operator">|</span> ReportNewPeopleComing <span class="token punctuation">(</span>_<span class="token punctuation">,</span> newPeopleComingCount<span class="token punctuation">)</span> 
</span><span class="code-line">        <span class="token keyword">when</span> shiftDetails&#x27;<span class="token punctuation">.</span>bouncers <span class="token operator">|&gt;</span> <span class="token punctuation">(</span><span class="token keyword">not</span> <span class="token operator">&lt;&lt;</span> reportedLessThan100PeopleWith newPeopleComingCount<span class="token punctuation">)</span> <span class="token operator">-&gt;</span> <span class="token comment">// 👈 consistency rule</span>
</span><span class="code-line">        <span class="token punctuation">[</span>PartyingPeopleLimitReached<span class="token punctuation">]</span><span class="token punctuation">,</span> NoMorePeopleAllowed shiftDetails&#x27; <span class="token comment">// ⛔ consistency violation</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token operator">|</span> ReportNewPeopleComing <span class="token punctuation">(</span>bouncerName<span class="token punctuation">,</span> newPeopleComingCount<span class="token punctuation">)</span> <span class="token operator">-&gt;</span>
</span><span class="code-line">        handleBouncersWhenMorePeopleAllowed <span class="token punctuation">(</span>Bouncers<span class="token punctuation">.</span>reportNewPeopleComing newPeopleComingCount<span class="token punctuation">)</span> bouncerName shiftDetails&#x27;
</span><span class="code-line">
</span><span class="code-line">    <span class="token operator">|</span> ScheduleBreakFor _
</span><span class="code-line">        <span class="token keyword">when</span> <span class="token punctuation">(</span><span class="token keyword">not</span> <span class="token operator">&lt;&lt;</span> atLeastTwoGuarding<span class="token punctuation">)</span> shiftDetails&#x27;<span class="token punctuation">.</span>bouncers <span class="token operator">-&gt;</span> <span class="token comment">// 👈 consistency rule</span>
</span><span class="code-line">        <span class="token punctuation">[</span>SchedulingABreakRejected <span class="token string">&quot;Can&#x27;t schedule break because less than two bouncers are guarding&quot;</span><span class="token punctuation">]</span><span class="token punctuation">,</span> MorePeopleAllowed shiftDetails&#x27; <span class="token comment">// ⛔ consistency violation</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token operator">|</span> ScheduleBreakFor bouncerName <span class="token operator">-&gt;</span>
</span><span class="code-line">        handleBouncersWhenMorePeopleAllowed <span class="token punctuation">(</span>Bouncers<span class="token punctuation">.</span>haveABreak<span class="token punctuation">)</span> bouncerName shiftDetails&#x27;
</span></code></pre></div></div><p>Some cases use <code>handleBouncersWhenMorePeopleAllowed</code> function, it&#x27;s because we wanted to track all facts that happen during the shift.</p><p>Now we need to &quot;translate&quot; facts mentioned by each bouncer. Also, this is the place when are are actually delegating the work to a particular bouncer.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> <span class="token keyword">private</span> translateFacts bouncerName <span class="token punctuation">(</span>bouncerFacts<span class="token punctuation">:</span> <span class="token class-name">Bouncers<span class="token punctuation">.</span>BouncerEvent</span> list<span class="token punctuation">)</span><span class="token punctuation">:</span> BouncersShiftEvent list <span class="token operator">=</span>
</span><span class="code-line">    bouncerFacts
</span><span class="code-line">    <span class="token operator">|&gt;</span> List<span class="token punctuation">.</span>map <span class="token punctuation">(</span><span class="token keyword">fun</span> fact <span class="token operator">-&gt;</span>
</span><span class="code-line">        <span class="token keyword">match</span> fact <span class="token keyword">with</span>
</span><span class="code-line">        <span class="token operator">|</span> Bouncers<span class="token punctuation">.</span>StartedGuarding <span class="token operator">-&gt;</span> StartedGuarding bouncerName
</span><span class="code-line">        <span class="token operator">|</span> Bouncers<span class="token punctuation">.</span>StartedABreak <span class="token operator">-&gt;</span> ScheduledBreakFor bouncerName
</span><span class="code-line">        <span class="token operator">|</span> Bouncers<span class="token punctuation">.</span>ReportedCount count <span class="token operator">-&gt;</span> CountReported <span class="token punctuation">(</span>bouncerName<span class="token punctuation">,</span> count<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token operator">|</span> Bouncers<span class="token punctuation">.</span>CountingRefused reason <span class="token operator">-&gt;</span> CountingRefused <span class="token punctuation">(</span>bouncerName<span class="token punctuation">,</span> reason<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">)</span>
</span><span class="code-line"><span class="token keyword">let</span> <span class="token keyword">private</span> handle cmd bouncerName shift <span class="token operator">=</span>
</span><span class="code-line">    <span class="token keyword">let</span> bouncer <span class="token operator">=</span> shift<span class="token punctuation">.</span>bouncers<span class="token punctuation">[</span>bouncerName<span class="token punctuation">]</span>
</span><span class="code-line">    <span class="token keyword">let</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>bouncerFacts<span class="token punctuation">,</span> _<span class="token punctuation">)</span><span class="token punctuation">,</span> bouncer&#x27;<span class="token punctuation">)</span> <span class="token operator">=</span> bouncer <span class="token operator">|&gt;</span> cmd
</span><span class="code-line">    <span class="token keyword">let</span> bouncers <span class="token operator">=</span>
</span><span class="code-line">        shift<span class="token punctuation">.</span>bouncers <span class="token operator">|&gt;</span> Map<span class="token punctuation">.</span>update bouncerName bouncer&#x27;
</span><span class="code-line">    <span class="token punctuation">(</span>translateFacts bouncerName bouncerFacts<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> shift <span class="token keyword">with</span> bouncers <span class="token operator">=</span> bouncers <span class="token punctuation">}</span>  
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">let</span> <span class="token keyword">private</span> handleBouncersWhenMorePeopleAllowed cmd bouncerName shift <span class="token operator">=</span>
</span><span class="code-line">    handle cmd bouncerName shift
</span><span class="code-line">    <span class="token operator">|&gt;</span> <span class="token keyword">fun</span> <span class="token punctuation">(</span>events<span class="token punctuation">,</span> shiftState<span class="token punctuation">)</span> <span class="token operator">-&gt;</span> events<span class="token punctuation">,</span> MorePeopleAllowed shiftState
</span></code></pre></div></div><p>As with a <code>Bouncer</code> finite state machine, <code>evolve</code> function is a private function which we don&#x27;t want to show (it is the implenentation details).</p><p>So let&#x27;s bring a public API for a <code>BouncersShift</code>.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> startGuarding name <span class="token operator">=</span> evolve <span class="token punctuation">(</span>StartGuarding name<span class="token punctuation">)</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">let</span> scheduleBreakFor name <span class="token operator">=</span> evolve <span class="token punctuation">(</span>ScheduleBreakFor name<span class="token punctuation">)</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">let</span> reportNewPeopleComing name count <span class="token operator">=</span> evolve <span class="token punctuation">(</span>ReportNewPeopleComing <span class="token punctuation">(</span>name<span class="token punctuation">,</span> count<span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">let</span> <span class="token keyword">private</span> toBouncers bouncerNames <span class="token operator">=</span>
</span><span class="code-line">  bouncerNames
</span><span class="code-line">      <span class="token operator">|&gt;</span> List<span class="token punctuation">.</span>map <span class="token punctuation">(</span><span class="token keyword">fun</span> name <span class="token operator">-&gt;</span> name<span class="token punctuation">,</span> Bouncers<span class="token punctuation">.</span>startShift name<span class="token punctuation">)</span>
</span><span class="code-line">      <span class="token operator">|&gt;</span> Map<span class="token punctuation">.</span>ofList
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">let</span> <span class="token keyword">private</span> NoEventsWhenStarting <span class="token operator">=</span> List<span class="token punctuation">.</span>empty
</span><span class="code-line"><span class="token keyword">let</span> start bouncerNames <span class="token operator">=</span>
</span><span class="code-line">  ensureAtLeastThreeBouncers bouncerNames
</span><span class="code-line">  <span class="token keyword">let</span> bouncers <span class="token operator">=</span> bouncerNames <span class="token operator">|&gt;</span> toBouncers
</span><span class="code-line">  
</span><span class="code-line">  <span class="token function">BouncersShift</span><span class="token punctuation">(</span>FSM <span class="token punctuation">(</span>NoEventsWhenStarting<span class="token punctuation">,</span> <span class="token keyword computation-expression">MorePeopleAllowed</span> <span class="token punctuation">{</span> bouncers <span class="token operator">=</span> bouncers <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
</span></code></pre></div></div><p>It&#x27;s pretty straightforward, isn&#x27;t it? The interesting part is the verbosity of the last line - we are starting with no events and when more people are allowed.</p><p>How about the usage of such shift?</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-fsharp code-highlight"><span class="code-line"><span class="token keyword">let</span> ignoreFacts <span class="token operator">=</span> snd <span class="token comment">// built-in function!</span>
</span><span class="code-line"><span class="token keyword">let</span> shift <span class="token operator">=</span> BouncersShift<span class="token punctuation">.</span>start <span class="token punctuation">[</span><span class="token string">&quot;mike&quot;</span><span class="token punctuation">;</span><span class="token string">&quot;john&quot;</span><span class="token punctuation">;</span><span class="token string">&quot;derek&quot;</span><span class="token punctuation">]</span>
</span><span class="code-line">
</span><span class="code-line">shift 
</span><span class="code-line"><span class="token operator">|&gt;</span> BouncersShift<span class="token punctuation">.</span>startGuarding <span class="token string">&quot;mike&quot;</span>
</span><span class="code-line"><span class="token operator">|&gt;</span> <span class="token punctuation">(</span>ignoreFacts <span class="token operator">&gt;&gt;</span> BouncersShift<span class="token punctuation">.</span>startGuarding <span class="token string">&quot;derek&quot;</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token comment">//      \________________ each operation yields both facts that happened</span>
</span><span class="code-line"><span class="token comment">//                        during execution and current state machine</span>
</span><span class="code-line"><span class="token operator">|&gt;</span> <span class="token punctuation">(</span>ignoreFacts <span class="token operator">&gt;&gt;</span> BouncersShift<span class="token punctuation">.</span>startGuarding <span class="token string">&quot;john&quot;</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token operator">|&gt;</span> <span class="token punctuation">(</span>ignoreFacts <span class="token operator">&gt;&gt;</span> BouncersShift<span class="token punctuation">.</span>reportNewPeopleComing <span class="token string">&quot;mike&quot;</span> <span class="token number">20</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token operator">|&gt;</span> <span class="token punctuation">(</span>ignoreFacts <span class="token operator">&gt;&gt;</span> BouncersShift<span class="token punctuation">.</span>scheduleBreakFor <span class="token string">&quot;mike&quot;</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token operator">|&gt;</span> <span class="token punctuation">(</span>ignoreFacts <span class="token operator">&gt;&gt;</span> BouncersShift<span class="token punctuation">.</span>reportNewPeopleComing <span class="token string">&quot;mike&quot;</span> <span class="token number">20</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token comment">//                    \______ public API haven&#x27;t changed</span>
</span><span class="code-line"><span class="token operator">|&gt;</span> <span class="token punctuation">(</span>ignoreFacts <span class="token operator">&gt;&gt;</span> BouncersShift<span class="token punctuation">.</span>reportNewPeopleComing <span class="token string">&quot;derek&quot;</span> <span class="token number">40</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token operator">|&gt;</span> <span class="token punctuation">(</span>ignoreFacts <span class="token operator">&gt;&gt;</span> BouncersShift<span class="token punctuation">.</span>reportNewPeopleComing <span class="token string">&quot;derek&quot;</span> <span class="token number">40</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token operator">|&gt;</span> <span class="token punctuation">(</span>ignoreFacts <span class="token operator">&gt;&gt;</span> BouncersShift<span class="token punctuation">.</span>reportNewPeopleComing <span class="token string">&quot;derek&quot;</span> <span class="token number">40</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token operator">|&gt;</span> <span class="token punctuation">(</span>ignoreFacts <span class="token operator">&gt;&gt;</span> BouncersShift<span class="token punctuation">.</span>scheduleBreakFor <span class="token string">&quot;derek&quot;</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token operator">|&gt;</span> <span class="token punctuation">(</span>ignoreFacts <span class="token operator">&gt;&gt;</span> BouncersShift<span class="token punctuation">.</span>startGuarding <span class="token string">&quot;mike&quot;</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token operator">|&gt;</span> <span class="token punctuation">(</span>ignoreFacts <span class="token operator">&gt;&gt;</span> BouncersShift<span class="token punctuation">.</span>scheduleBreakFor <span class="token string">&quot;derek&quot;</span><span class="token punctuation">)</span>
</span></code></pre></div></div><p>Yet again, we are totally not interested what happened during the shift. It might be we could utilize such information for some interesting business metric.</p><p>In <a href="#solution-2-functional-oriented-approach">&quot;Solution #2: Functional-oriented approach&quot;</a> example, we haven&#x27;t tracked anything, since we were dealing with &quot;problems&quot;.</p><p>Now it is a different story - there are some facts happening and the interpretation of them is on a caller&#x27;s hands (&quot;the beauty is the observer&#x27;s eyes&quot;).</p><p>Nothing is lost, because in this example we are keeping entire history for a particular shift. Let us help ourselves with a simple output visualization.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="code-highlight language-sh"><span class="code-line">BouncersShift<span class="token punctuation">(</span>FSM
</span><span class="code-line">     <span class="token punctuation">(</span><span class="token punctuation">[</span>StartedGuarding <span class="token string">&quot;mike&quot;</span><span class="token punctuation">;</span> StartedGuarding <span class="token string">&quot;derek&quot;</span><span class="token punctuation">;</span> StartedGuarding <span class="token string">&quot;john&quot;</span><span class="token punctuation">;</span>
</span><span class="code-line">       CountReported <span class="token punctuation">(</span><span class="token string">&quot;mike&quot;</span>, <span class="token number">20</span><span class="token punctuation">)</span><span class="token punctuation">;</span> ScheduledBreakFor <span class="token string">&quot;mike&quot;</span><span class="token punctuation">;</span>
</span><span class="code-line">       CountingRefused <span class="token punctuation">(</span><span class="token string">&quot;mike&quot;</span>, <span class="token string">&quot;I am having a break&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">       CountReported <span class="token punctuation">(</span><span class="token string">&quot;derek&quot;</span>, <span class="token number">40</span><span class="token punctuation">)</span><span class="token punctuation">;</span> CountReported <span class="token punctuation">(</span><span class="token string">&quot;derek&quot;</span>, <span class="token number">40</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">       PartyingPeopleLimitReached<span class="token punctuation">;</span>
</span><span class="code-line">       SchedulingABreakRejected <span class="token string">&quot;Can&#x27;t schedule break because less than two bouncers are guarding&quot;</span><span class="token punctuation">;</span>
</span><span class="code-line">       StartedGuarding <span class="token string">&quot;mike&quot;</span><span class="token punctuation">;</span> ScheduledBreakFor <span class="token string">&quot;derek&quot;</span><span class="token punctuation">]</span>,
</span><span class="code-line">      NoMorePeopleAllowed
</span><span class="code-line">        <span class="token punctuation">{</span> bouncers <span class="token operator">=</span> map
</span><span class="code-line">             <span class="token punctuation">[</span><span class="token punctuation">(</span><span class="token string">&quot;derek&quot;</span>, Bouncer<span class="token punctuation">(</span>FSM
</span><span class="code-line">                    <span class="token punctuation">(</span><span class="token punctuation">[</span>StartedGuarding<span class="token punctuation">;</span> ReportedCount <span class="token number">40</span><span class="token punctuation">;</span> ReportedCount <span class="token number">40</span><span class="token punctuation">;</span>
</span><span class="code-line">                      StartedABreak<span class="token punctuation">]</span>, HavingABreak <span class="token punctuation">{</span> name <span class="token operator">=</span> <span class="token string">&quot;derek&quot;</span> count <span class="token operator">=</span> <span class="token number">80</span> <span class="token punctuation">}</span><span class="token punctuation">))</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">              <span class="token punctuation">(</span><span class="token string">&quot;john&quot;</span>, Bouncer <span class="token punctuation">(</span>FSM <span class="token punctuation">(</span><span class="token punctuation">[</span>StartedGuarding<span class="token punctuation">]</span>, Guarding <span class="token punctuation">{</span> name <span class="token operator">=</span> <span class="token string">&quot;john&quot;</span> count <span class="token operator">=</span> <span class="token number">0</span> <span class="token punctuation">}</span><span class="token punctuation">))</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">              <span class="token punctuation">(</span><span class="token string">&quot;mike&quot;</span>, Bouncer <span class="token punctuation">(</span>FSM
</span><span class="code-line">                    <span class="token punctuation">(</span><span class="token punctuation">[</span>StartedGuarding<span class="token punctuation">;</span> ReportedCount <span class="token number">20</span><span class="token punctuation">;</span> StartedABreak<span class="token punctuation">;</span>
</span><span class="code-line">                      CountingRefused <span class="token string">&quot;I am having a break&quot;</span><span class="token punctuation">;</span> StartedGuarding<span class="token punctuation">]</span>,
</span><span class="code-line">                     Guarding <span class="token punctuation">{</span> name <span class="token operator">=</span> <span class="token string">&quot;mike&quot;</span> count <span class="token operator">=</span> <span class="token number">20</span> <span class="token punctuation">}</span><span class="token punctuation">))</span><span class="token punctuation">)</span><span class="token punctuation">]</span> <span class="token punctuation">}</span><span class="token punctuation">))</span><span class="token punctuation">)</span>
</span></code></pre></div></div><p>What&#x27;s is more, each bouncer also remembers what he did during the shift!</p><p>Does it look familiar? How could we utilize such information? More in the next tales! (I know, I know, again clitbait-ish, but I couldn&#x27;t resist!)</p><h3 id="what-the-hell-just-happened"><a href="#what-the-hell-just-happened" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>WHAT THE HELL JUST HAPPENED?</h3><p>It was tough, bumpy, exhaustive, but enjoyable journey (at least for me).</p><p>We were working on a single business problem concerned around consistency.</p><p>Thanks to the analysis we did, using strategic DDD with language modeling, our problem became &quot;approachable&quot;.</p><p>We used Aggregate building block from tactical DDD.</p><p>We provided three solutions (models) for the problem that Tom challenged us with:</p><ul><li>Object-oriented approach</li><li>&quot;Lightweight&quot; Type-driven functional approach</li><li>&quot;Lightweight&quot; functional, State Machine-like approach</li></ul><p>This is also <strong>very</strong> important - we should always think of multiple models for solving a problem to &quot;promote&quot; the best one (at the current moment). Note that it does not mean all of them need to be perfectly implemented - the main purpose is to experiment and analyze!</p><p>Conclusions?</p><ul><li>OO achieves evolvability through mutability</li> <li>FP achieves evolvability through immutability</li> <li>F# is able to keep implementation details hidden, even though data and behavior are separated</li> <li>There are various ways for handling output from an operation on an aggregate: exception, Result or Event</li> <li>Domain language can be expressed on various levels</li> <li>Type correctness isn&#x27;t &quot;free&quot;</li> <li>Handling all cases might be tiresome, but might help with crafting. bug-free code</li></ul><p>There is also another observation - F# is a great language for domain modeling on variety of levels. Use its powers, let it empower you (I am looking at you F# Compiler!).</p><p>Because it is functional-first and <strong>not</strong> functional-only we use the most suitable approach. I always say that F# made me better Object-oriented programmer.</p><p>Ok, we arrived at the place when we can stop. I hope you enjoyed this little exercise my dear Reader.</p><p>Thank you for your patience and time!</p>]]></content:encoded>
    <pubDate>Thu, 15 Dec 2022 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>programming</category><category>domain-driven design</category><category>having fun</category><category>language</category><category>abstraction</category><category>modeling</category><category>encapsulation</category><category>model</category><category>code</category><category>representations</category><category>principles</category><category>tactical design</category><category>ddd</category><category>fsharp</category><category>advent of code</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/the-ambiguity-of-abstraction</guid>
    <title>The ambiguity of abstraction</title>
    <link>https://talesfrom.dev/blog/the-ambiguity-of-abstraction</link>
    <description>Why are we abstracting?</description>
    <content:encoded><![CDATA[<h3 id="groceries"><a href="#groceries" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Groceries</h3><p>Imagine you went on walking to do some small shopping because you needed edible goods.</p><p>It turned out that you got so many little things that you couldn&#x27;t hold them all in your hands.</p><p>Fortunately, there were some plastic/paper bags you could use to solve this problem.</p><p>The next day, you wanted to return some IT books to your friend, but it wasn&#x27;t safe to carry them outdoor. Snow and rain can easily damage precious knowledge available in the books.</p><p>To keep them away from moisture, you put them inside of the same bag you got your groceries earlier.</p><h3 id="driving"><a href="#driving" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Driving</h3><p>Next time, you needed to go to drive to a shop distant from your current place.</p><p>You went to your car, started the engine and the sound you have heard was far from the regular one.</p><p>You went out and lifted out the hood of the car - the hot steam was miserably unfriendly feedback from the reality that your car broke.</p><p>Everything was simple before this situation - use the key (or button depending if the car is &quot;keyless&quot;) and drive happily to destination at will.</p><p>Unintentionally, internals got exposed to you - there was no need to see them before (or at least you didn&#x27;t think of them).</p><h3 id="what-is-the-purpose"><a href="#what-is-the-purpose" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What is the purpose?</h3><p>I can hear your voice (at least I am simulating you were telling so): &quot;What the hell are you talking about? Bags? Broken car?&quot;</p><p>Two totally unrelated contexts, although both scenarios have something in common.</p><p>What?</p><p>Those examples were made purposefully so I know the answer: both subjects of our little sceneries took away the details.</p><p>Of course, there are other reasons why things are as they are, but either a bag or a car provides a specific contract, when satisfied, gives back a certain function.</p><p>&quot;(...) took away the details&quot;, but what are those &quot;details&quot;?</p><p>The details of the provided function.</p><h3 id="taking-away-the-items"><a href="#taking-away-the-items" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Taking away the items</h3><p>Coincidentally, we are talking about something which is really fundamental in the universe - abstraction.</p><p>Without abstraction, we are not able to operate, because of drowning in the ocean of details, nitty gritties and edge cases.</p><p>We want simplicity (and predictability, but that&#x27;s a different story we will tackle at some point in the future).</p><p>Even though our examples have something in common, they also differ in one particular perspective.</p><p>We can carry various things in a bag - books, groceries, rocks, clothes and whatever else you can pick.</p><p>A bag abstracts away the details of the specific fabric endurance, ergonomics of handlers, and so on, simultaneously providing a handy interface to work with (in most cases).</p><p>I can imagine (or at least that&#x27;s my reasoning) that a shopping carry bag was introduced to help customers taking back their goods.</p><p>The function provided by it is clearly orbiting around carrying, aggregating, holding together, etc. After putting of the stuff inside, we stop thinking of them as individual items, instead we refer to the &quot;interface&quot;.</p><p>This unified contract opens a possibility to keep various types of things inside. When designed, this contract was supposed to be &quot;generic&quot; or &quot;reusable&quot;.</p><p>On the other hand, the details kept under the hood of a car, were taken away for a &quot;slightly&quot; different purpose.</p><h3 id="taking-away-the-complexity"><a href="#taking-away-the-complexity" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Taking away the complexity</h3><p>We don&#x27;t want to deal with complexity of the car - at least until it doesn&#x27;t break down (here I can totally recommend a great <a href="https://www.youtube.com/watch?v=Lc13xKEJZTc">talk</a> given by <a href="https://twitter.com/KevlinHenney">Kevlin Henney</a>).</p><p>They are taken away from our sight so that we can refer to a simple interface - &quot;put a key, turn it over, go&quot;.</p><p>To fulfill this function a vast collaboration between sub-components need to happen. But we don&#x27;t want to think about it <em>all the time</em>.</p><p>In this scenario, the main purpose was to primarily hide internals, and reusability of reasoning about it might be called a side-effect of this interface, not a purpose itself.</p><p>Additionally, it wasn&#x27;t mentioned during the introduction of this tale, but each hidden part is an abstraction of other sub-parts. A consequence of such abstraction might be reusability, but yet again the details are hidden under a stable interface.</p><h3 id="manufacturing-the-understanding"><a href="#manufacturing-the-understanding" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Manufacturing the understanding&quot;</h3><p>We could build the conclusion that hiding complexity <strong>might</strong> lead to reusability, but no the other way around.</p><p>The reusable function might emerge when a given abstraction proves itself among various contexts.</p><p>So when the complexity, the internals, &quot;the guts&quot;, are kept away from our sight, we start reasoning on a totally different level.</p><p>Our cognition flies high to the upper planes of understanding. We no longer &quot;ignite the engine&quot;, but we do &quot;put a key, turn it over, go&quot;.</p><p>Concluding, the process of abstracting can be thought of as a function that takes the details (with the related words, the &quot;language&quot;) and outputs the intention-oriented, context-capturing concept.</p><p>It might be, coincidentally, that it can be reused in some other contexts, but then we need to check the language to prove its universality.</p><p>As we obtained the high-order concept, having a stable inteface, we can use its interface as a specification in building even higher-order functions (there is a great blog post called <a href="https://www.codurance.com/publications/2018/10/18/mocking-as-a-design-tool">&quot;Mocking as a design tool&quot;</a> written by <a href="https://twitter.com/sandromancuso">Sandro Mancuso</a>).</p><h3 id="you-aint-gonna-need-it-so-keep-it-simple-stupid"><a href="#you-aint-gonna-need-it-so-keep-it-simple-stupid" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>You ain&#x27;t gonna need it so keep it simple, stupid</h3><p>What about YAGNI? What about KISS? Isn&#x27;t the &quot;premature abstraction is the root of all evil&quot;?</p><p>The question is about the purpose, the intention, &quot;the why&quot; - why are we abstracting?</p><p>If we want to drive the understanding by it - it&#x27;s probably worth doing. Emphasizing the language, by keeping the details inside, was one of the topics of <a href="https://talesfrom.dev/blog/language-of-the-problem">&quot;Language of the problem&quot;</a> blog post.</p><p>Another trait, raising the probability of a decision for abstracting some details away, is &quot;replaceability&quot; - in order to have control over it when designing some other thing.</p><p>And &quot;replaceability&quot; leads to another interesting conclusion - we are able to grow, to evolve the structure, as we learn (check <a href="http://localhost:3000/blog/feature-toggling-as-a-design-tool">&quot;Feature toggling as a design tool&quot;</a>).</p><p>In fact, this is not anything new. It is the hallmark of modularity, testability and other properties of a well-designed (sub)system that the IT industry icons are speaking over and over.</p><p>At the same time, I&#x27;m thinking that YAGNI and KISS might be treated as really dangerous abbreviations (please note I don&#x27;t say they are bad or wrong, but dangerous).</p><p>They are highly context-dependent, intention-hiding, distilled forms of a thought process and experience.</p><p>Actually, what does it mean &quot;simple&quot;? What does &quot;the need&quot;, in YAGNI, refers to?</p><p>If working with all the low-level &quot;gizmos&quot;, providing the universal interface full of getters and setters, means simple then we have a problem.</p><p>This might be a good example of the inherent property of &quot;coding&quot;, which is totally opposite to &quot;modeling&quot;. However, the problem with modeling is that it doesn&#x27;t come without costs (you don&#x27;t know what I am talking about? Please check <a href="https://talesfrom.dev/blog/the-cost-of-modeling">&quot;The cost of modeling&quot;</a>).</p><h3 id="dont-repeat-yourself-stupid"><a href="#dont-repeat-yourself-stupid" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Don&#x27;t repeat yourself, stupid</h3><p>Contradictory to YAGNI and KISS, we have DRY.</p><p>&quot;Repeating&quot; sounds like an another form of &quot;reusability&quot;, and we already touched it a bit.</p><p>When the main goal is unification, in the form of a generic contract, we might be missing a point of abstraction and then we fall into &quot;premature&quot; or &quot;too early&quot; issue.</p><p>Wrapping a bunch of lines, that initially look as if they are building up a bigger responsibility, in a function might be a good idea unless the main intention is not reusability.</p><p>This needs to be proven, battle-tested.</p><p>Slow down.</p><h3 id="one-question-to-rule-them-all"><a href="#one-question-to-rule-them-all" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>One question to rule them all</h3><p>There is one particular question that might reveal weaknesses of the design.</p><p>But it needs reflection and proper effort put into the process.</p><p>This question is: &quot;how am I going to test it?&quot; (please note that it doesn&#x27;t exclude other questions and tools of analysis).</p><p>Uncontrollable dependencies, relatively high (what does it mean? 🤔) probability of changes, various cases and scenarios are some of the heuristics we can have.</p><p>Another interesting point is grouping the manifold of parts, according to a responsibility they need to jointly provide. Putting them &quot;inside a box&quot; opens a possibility to work only on this responsibility as a whole.</p><p>How do we know how many parts we need to have? We can <em>assume</em>, but it&#x27;s probably better to discover them, hence the Outside-In TDD might be helpful here.</p><h3 id="the-ambiguity"><a href="#the-ambiguity" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The ambiguity?</h3><p>We have enormously powerful techniques in our tool belt - and one of them is abstracting away the details (of function, or implementation).</p><p>As I wrote in <a href="https://talesfrom.dev/blog/the-value-of-value-objects">&quot;The value of Value Objects&quot;</a>, the value might be visible in building higher-levels of reasoning by using context-specific language. The value might not be directly in reusability (which might come as a side-effect).</p><p>We have discriminated unions, classes, modules, namespaces, functions, methods, REST APIs and other &quot;programming&quot; constructs to represent higher ways of reasoning so let&#x27;s use them to express the meaning of our thought process and a snapshot of the state of mind.</p>]]></content:encoded>
    <pubDate>Mon, 12 Dec 2022 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>programming</category><category>paradigms</category><category>domain-driven design</category><category>problem-solving</category><category>language</category><category>abstraction</category><category>modeling</category><category>encapsulation</category><category>model</category><category>code</category><category>representations</category><category>principles</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/the-cost-of-modeling</guid>
    <title>The cost of modeling</title>
    <link>https://talesfrom.dev/blog/the-cost-of-modeling</link>
    <description>Is modeling more expensive than coding?</description>
    <content:encoded><![CDATA[<h3 id="language-of-the-problem"><a href="#language-of-the-problem" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Language of the problem</h3><p>In one of previous <a href="https://talesfrom.dev/blog/language-of-the-problem">tales</a>, we were discussing the language of the problem.</p><p>Essentially, that is what Domain-Driven Design is about - carefully listening to another human being and capturing the concepts (along with related activities) in the form of the model.</p><p>What comes first is the understanding, so the mental model we built inside of our mind so that we are able to communicate effectively (or at least we should).</p><p>Another representation might be a model specified using our favorite programming language. Then we refer to it as &quot;code&quot;.</p><p>I mentioned one observation in <a href="https://talesfrom.dev/blog/essentially-bounded-accidentally-unlimited">&quot;Essentially bounded, accidentally unlimited&quot;</a>:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>There is no single solution, but there is a single problem.</p></div></div></div><p>Based on this premise, we are able to create various models so that we tackle the essential complexity. The one that never disappears (provided that we are solving the right problem!).</p><h3 id="listen-to-the-expert"><a href="#listen-to-the-expert" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Listen to the expert</h3><p>The last part of <a href="https://talesfrom.dev/blog/language-of-the-problem">&quot;Language of the problem&quot;</a> contains a brain teaser, or better, modeling teaser.</p><p>Given the model:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Emails</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">  <span class="token keyword">private</span> <span class="token class-name">List<span class="token punctuation">&lt;</span>Email<span class="token punctuation">&gt;</span></span> _emails<span class="token punctuation">;</span> <span class="token comment">// details</span>
</span><span class="code-line">
</span><span class="code-line">  <span class="token keyword">public</span> <span class="token function">Emails</span><span class="token punctuation">(</span><span class="token class-name">List<span class="token punctuation">&lt;</span>Email<span class="token punctuation">&gt;</span></span> emails<span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
</span><span class="code-line">    _emails <span class="token operator">=</span> emails<span class="token punctuation">;</span> <span class="token comment">// ctor</span>
</span><span class="code-line">
</span><span class="code-line">  <span class="token keyword">public</span> <span class="token class-name return-type">List<span class="token punctuation">&lt;</span>Email<span class="token punctuation">&gt;</span></span> <span class="token function">GetInvalidEmails</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token comment">// is it ANY email?</span>
</span><span class="code-line">    _emails
</span><span class="code-line">    <span class="token punctuation">.</span><span class="token function">Where</span><span class="token punctuation">(</span>email <span class="token operator">=&gt;</span> <span class="token operator">!</span>email<span class="token punctuation">.</span>IsValid<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">.</span><span class="token function">ToList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Is the method <code>GetInvalidEmails</code> saying all truth? Its name clearly states we can expect only invalid emails, but the result doesn&#x27;t indicate that.</p><p>Without any problems, one can easily notice that <code>Email</code> contains a <code>IsValid</code> property. This might tell us the story that all the <code>Email</code>s returned would have <code>IsValid</code> set to <code>false</code>.</p><p>But wait, given a collection of invalid emails, one could do with them?</p><p>Let&#x27;s assume that our expert says that in this marathon, oops, I was about to say sprint, we need only to &quot;print&quot; them.</p><p>That&#x27;s not fancy.</p><p>Unfortunately, a collection of invalid emails, represented by compile-time model <code>List&lt;Email&gt;</code> with runtime <code>IsValid</code> indication set to <code>false</code>, gives a lot more, e.g. using a very cryptic (to our expert) <code>Aggregate</code> operation.</p><p>Can we do better?</p><h3 id="domain-out-of-balance"><a href="#domain-out-of-balance" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Domain out of balance</h3><p>In my observation, people tend to watch shorter and shorter videos. If a content creator publishes a video longer than 20 min, there might be a high probability it won&#x27;t get that many views as 8 min video (common sense, isn&#x27;t it?).</p><p>We are all busy. We need to be fast, efficient, productive.</p><p>Even by having support of the greatest IDEs in the market, it&#x27;s &quot;still&quot; quicker to leave <code>List&lt;Email&gt;</code> as a representation of invalid emails.</p><p>Physical typing is just a top of an iceberg. There&#x27;s even bigger cost - mental, or psychological one.</p><p>By clearly listening to our imaginary expert, we know what should be expressed in the &quot;code&quot; and it is not a list of emails with <code>IsValid</code> boolean flag.</p><p>To me it looks as if we got out of balance with our domain. We no longer align with the mental model presented by the expert.</p><p>And what is worse, it&#x27;s easy to get used to such approach.</p><h3 id="constraints-liberate"><a href="#constraints-liberate" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Constraints liberate</h3><p>What if, just for a mental expertiment, we would create a new concept called, wait for it, <code>InvalidEmails</code>?</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">InvalidEmails</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Let&#x27;s think of it in terms of <a href="https://talesfrom.dev/blog/organization-driven-design">&quot;Organization-Driven Design&quot;</a> - and imagine that <code>InvalidEmails</code> is a local expert in working with invalid emails.</p><p>What would he be responsible for?</p><p>For now, it&#x27;s just printing the invalid emails in the form of text.</p><p>We could probably use well-known <code>ToString</code> method, right? Technically speaking yes, but as an expert, he doesn&#x27;t know what &quot;ToString&quot; means.</p><p>But when you ask him to print the invalid emails, we would eagerily do so.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">InvalidEmails</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">   <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> <span class="token function">Print</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">   <span class="token punctuation">{</span> <span class="token comment">/* implementation goes here... */</span><span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>What to print if there&#x27;s nothing available?</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">InvalidEmails</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">   <span class="token keyword">private</span> List<span class="token operator">&lt;</span>InvalidEmail<span class="token operator">&gt;</span> _invalidEmails <span class="token comment">// received from ctor</span>
</span><span class="code-line">   <span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">string</span></span> <span class="token function">Print</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">   <span class="token punctuation">{</span> <span class="token comment">/* implementation goes here... */</span><span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>We introduced another &quot;concept&quot; - <code>InvalidEmail</code>. There is no longer ANY <code>Email</code> with runtime <code>IsValid</code> property set to <code>false</code>, but a very precise specification.</p><p>Both for the responsibility and for the related contract details.</p><h3 id="hold-on-cowboy"><a href="#hold-on-cowboy" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Hold on cowboy!</h3><p>I hear it (currently in my head only) - you are complicating so much, keep it simple, you ain&#x27;t gonna need it, etc.</p><p>Well, undoubtedly we introduced &quot;more&quot; code. &quot;More&quot; readable code.</p><p>Things got segregated which by definition implies it might require a bit more &quot;infrastructure&quot; - characters in the given file (or separate files).</p><p>Are we really optimizing for a number of characters? Nope, we all know it&#x27;s not the case.</p><p>Should we be afraid that such code soon will come unmaintanable piece of mud? Who knows.</p><p>Are we communicating the intentions? Yup, that&#x27;s one of the points.</p><p>Just having <code>List&lt;Email&gt;</code> with runtime property <code>IsValid</code> set to <code>false</code> as a representation of invalid emails is not enough.</p><p>Same stands just for <code>IsValid</code> boolean flag - it is so-called status property. You could easily imagine an enum property called, you won&#x27;t guess it, <code>Status</code> with two possible values: <code>Valid</code> and <code>Invalid</code>.</p><h3 id="mixed-language-mixed-worlds"><a href="#mixed-language-mixed-worlds" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Mixed language, mixed worlds</h3><p>I dare to say that most of the primtive obsession examples are there because of mixing up two aspects: data and model.</p><p>Either a boolean flag or an enum are suitable for working with infrastructure components:</p><ul><li>serializing them to JSON so that we can return them to from the controller</li><li>putting them inside of a message so that we are able to send them to a queue</li><li>inserting them to a database</li></ul><div class="flex flex-col justify-center items-center mt-6"><img class="m-0" src="https://talesfrom.dev/static/images/data-structure-and-model.png" style="width:80%;height:80%"/><span>what does your model resemble - a data structure?</span></div><p>Shouldn&#x27;t we use right &quot;abstractions&quot; on various levels?</p><p>When talking to an expert, a model is clearly communicating what is possible.</p><p>When talking to a database, a data structure has its own benefits.</p><p>Aren&#x27;t we introducing the model-to-data (impedance) mismatch? Surely we do.</p><p>How much does it hurt?</p><h3 id="language-cost"><a href="#language-cost" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Language cost</h3><p>There&#x27;s also another point on &quot;proper&quot; modeling - what your tools allow you to do.</p><p>Representing two cases for an email: valid email and invalid email, might be troublesome in some languages.</p><p>It would be even undesirable to model them separately as such usage won&#x27;t get magical label &quot;idiomatic&quot;, in terms of the given language.</p><p>Given the need for expressing the model as close as experts are telling us, I would say that some languages <em>encourage</em> modeling , whereas other rather <em>discourage</em> it.</p><p>I am not stating that C# is &quot;worse&quot; (or something) than F#, but it would be really uncommon to see two classes for representing two separate cases of an email.</p><p>Then it would &quot;break&quot; one of the <a href="https://dannorth.net/2022/02/10/cupid-for-joyful-coding/">CUPID</a> properties - I - idiomatic.</p><p>On the other hand, in F# it is a quite common to have:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="code-highlight language-fsharp"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">Email</span> <span class="token operator">=</span>
</span><span class="code-line"><span class="token operator">|</span> Invalid <span class="token keyword">of</span> <span class="token class-name">InvalidEmail</span>
</span><span class="code-line"><span class="token operator">|</span> Valid <span class="token keyword">of</span> <span class="token class-name">ValidEmail</span>
</span></code></pre></div></div><p>The cost (I am not talking about a runtime, performance-wise cost) of using such construct is simply nothing, no additional effort required.</p><h3 id="model-states-not-statuses"><a href="#model-states-not-statuses" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Model states, not statuses</h3><p>In our particular example, statuses are reserved for infrastructure side - one might say they are &quot;optimized&quot; for it.</p><p>What about states? States are for the essential complexity, for representing the concepts available in the domain you are designing the software for.</p><p>A question is how easily your language allows you to model.</p><p>Modeling states also gives very nice property - we are reasoning with the types we see on the screen. This means we don&#x27;t need to &quot;load&quot; the model into our brain. We keep it externalized.</p><p>That&#x27;s what I tried to convey in <a href="https://talesfrom.dev/blog/the-value-of-value-objects">&quot;The value of Value Objects&quot;</a> blog post.</p><p>Additionally, you are able to restrict some of the operations/responsibilities to work only with a <strong>specific</strong> state.</p><p>This is what we mean by &quot;embedding the invariants/rules in the type&quot;.</p><h3 id="are-you-capable-of-paying-the-cost"><a href="#are-you-capable-of-paying-the-cost" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Are you capable of paying the cost?</h3><p>What is really crucial here that it is not only applicable for the domain/business concepts.</p><p>We are solving problems all the time, some of them are technical in nature which is a domain itself.</p><p>Then the language of the domain is highly technical. Still we are able to express it in the decent way and the good part is that we are the experts.</p><p>Materializing the domain in the code costs - sometimes you need to put some additional key strokes to reveal the intention. But again, are we suppose to minimize the key strokes?</p><p>Scattering pure data structures along the entire codebase costs too - it might seem &quot;simpler&quot;, but isn&#x27;t it deceiving that less &quot;code&quot; simply expresses the same intentions as expressive language?</p><p>It might be that you are afraid that soon such modeling approach will turn your code into a piece of turdpile because it will leak toward undesirable places of your codebase? Watch your &quot;layers&quot; and pay attention to the local architecture - maybe some layers see too much? If you would like to see a metaphor for working with such state please check <a href="https://talesfrom.dev/blog/organization-driven-design">&quot;Organization-Driven Design&quot;</a>.</p><h3 id="the-biggest-cost"><a href="#the-biggest-cost" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The biggest cost?</h3><p>Nothing is so limiting to us as ourselves. Even if you think that such reasoning is utter nuts, give it a try.</p><p>Might it be that there are some interesting assumptions you made long time ago so that they got a bit...Stiff?</p><p>Challenge your mental representation (hence mental model) of how the model looks like.</p><p>Slow down, start from specifying through tests what the model should do (you don&#x27;t know what I am talking about? Please check <a href="https://talesfrom.dev/blog/the-ambiguity-of-tdd">&quot;The ambiguity of TDD&quot;</a>).</p><p>Listen to your problem experts, if you don&#x27;t have such, listen to the language, pay attention to the words and be free with your tempo. Be free to yourself.</p><p>And the last thing.</p><p>Should you always design rich, well-encapsulated models? Yes, my zealot, always (I hope you see the irony here!).</p><h3 id="a-bonus-modeling-teaser"><a href="#a-bonus-modeling-teaser" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>A bonus: modeling teaser</h3><p>Imagine that one expert says that the patient can be either healthy or sick.</p><p>When he or she is sick, we need to send a text message with drug prescription.</p><p>How would you model that in your favorite language?</p>]]></content:encoded>
    <pubDate>Mon, 28 Nov 2022 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>programming</category><category>paradigms</category><category>domain-driven design</category><category>problem-solving</category><category>language</category><category>learning</category><category>encapsulation</category><category>model</category><category>code</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/fragile</guid>
    <title>(Fr)Agile</title>
    <link>https://talesfrom.dev/blog/fragile</link>
    <description>Are you agile or fragile?</description>
    <content:encoded><![CDATA[<h3 id="what-is-the-response"><a href="#what-is-the-response" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What is the response?</h3><p>Imagine the following situation: you are walking down the street and an unknown man stands in front of you.</p><p>He pushes you once.</p><p>Seconds pass.</p><p>He pushes you again, but this time more aggressively.</p><p>Milliseconds pass.</p><p>You fall down, hitting the ground.</p><h3 id="what-is-the-decision"><a href="#what-is-the-decision" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What is the decision?</h3><p>Imagine the next situation: a friend of yours offers you a great deal - going to a tech workshop you always wanted to attend, but it was too expensive - for free!</p><p>He texts you with a question.</p><p>Hours pass.</p><p>He contacts you again, but this time by calling you directly.</p><p>Minutes pass.</p><p>The next message states that the ticket was given to someone else eventually.</p><h3 id="answer"><a href="#answer" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Answer?</h3><p>Imagine yet another situation: you are waiting in the overpopulated queue to get an autograph from your beloved (tech) author.</p><p>Suddenly a person behind you steps in and stands before you.</p><p>Minutes pass.</p><p>Author announces that soon he&#x27;s going to end the event.</p><p>Seconds pass.</p><p>The guy that took your place previously was the last one.</p><h3 id="similar"><a href="#similar" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Similar?</h3><p>The world is a system of interconnected subsystems, as some might say.</p><p>Some events are happening and we are not &quot;operating&quot; in the vacuum. We need to decide. To take an action.</p><p>Or not.</p><p>Not taking any action is also an action.</p><p>Not making a decision is also a decision.</p><p>Our action, or decision, influences the world outside, as we are a subpart of it.</p><p>You have probably wondered (or to put it straight - I hope you wondered) about all those scenarios, I brought to you, at the beginning.</p><p>Can you say what they have in common?</p><p>Probably you can guess - it&#x27;s related to agility.</p><p>But wait, what is &quot;agility&quot;?</p><p>The simplest definition (and the laziest, I googled it) could be:</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">&quot;agility&quot; - definition</div><div class="pb-2 px-3"><div class="break-words"><p>ability to <strong>move</strong> quickly and easily.</p></div></div></div><p>Nice, but now it&#x27;s pretty coupled to a single behavior. Let&#x27;s generalize, so it is not tight only to &quot;movement&quot;. What could we get?</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">&quot;agility&quot; - definition evolution</div><div class="pb-2 px-3"><div class="break-words"><p>ability to <strong>act</strong> quickly and easily.</p></div></div></div><p>I assume that such activity is not purposeless, there is some intention behind.</p><p>Plausibly, we are acting as a response to a fact that we faced.</p><p>We can say we are responding, reacting, with a proper action.</p><p>Let&#x27;s move on (or should I say &quot;act on&quot;?)!</p><p>We have &quot;quickly and easily&quot; to think through.</p><h3 id="what-does-it-mean-quickly"><a href="#what-does-it-mean-quickly" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What does it mean &quot;quickly&quot;?</h3><p>Lazy searching tells me that it means:</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">&quot;quickly&quot; - first definition</div><div class="pb-2 px-3"><div class="break-words"><p>with little or no delay; promptly.</p></div></div></div><p>and second definition is:</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">&quot;quickly&quot; - second definition</div><div class="pb-2 px-3"><div class="break-words"><p>at a fast speed; rapidly.</p></div></div></div><p>&quot;Delay&quot;, &quot;speed&quot; - both of these words relate to time. They are functions of time (meaning, they vary based on the time).</p><p>Just to recap, bear with me:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>&quot;agility&quot; is an ability to act (or respond with an action) with little or no delay, at a fast speed.</p></div></div></div><p>Things are getting really interesting.</p><p>Could we say that one can measure his or her agility based on how fast is able to respond with an action?</p><p>Minimizing the delays in communicating the reactions to the world.</p><p>In the communication, between systems that exchange information, there is a very precise word, describing similar operation. A synonym to &quot;response&quot;, &quot;react&quot;.</p><p>Repeat after me: <strong>feedback</strong>.</p><h3 id="cursed-word"><a href="#cursed-word" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Cursed word</h3><p><em>Agile</em>, written with the capital &quot;A&quot;, became both a blessing and curse in the IT industry.</p><p>Holy Grail and dreaded sin.</p><p>I think we can draw the analogy between Nietzsche&#x27;s &quot;God is dead&quot; and Agile.</p><p>The meaning is quite subtle when one adds the missing piece of the sentence: &quot;God is dead (because you people killed him)&quot;.</p><p>Let&#x27;s apply it to &quot;Agile&quot;: &quot;Agile is dead (because you people killed it)&quot;.</p><h3 id="we-are-agile-we-do-daily-stand-ups"><a href="#we-are-agile-we-do-daily-stand-ups" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;We are Agile, we do daily stand-ups&quot;</h3><p>The mental journey we did, through definitions, mentioned nothing about: daily stand-ups, retros, technical user stories, etc.</p><p>Fast feedback.</p><p>As in the first tale, how fast can you react to some stranger pushing you? I think you won&#x27;t wait much.</p><p>Fast feedback.</p><p>When a new feature is required to be developed, how fast are you able to introduce it? Hours? Weeks? Months?</p><p>Of course, it&#x27;s very contextual, because you might need to understand the problem (I hugely advise doing so!), design proper architecture, etc.</p><p>What about experimenting? Verifying if the idea behind the new cool feature is correct? It will be blazingly fast feedback from the external world - your users.</p><p>Can&#x27;t we isolate it, behind a stable interface, so that it is easy to be removed later? Just in case if it didn&#x27;t make any sense?</p><h3 id="but-i-dont-need-to-experiment"><a href="#but-i-dont-need-to-experiment" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;But I don&#x27;t need to experiment!&quot;</h3><p>I hear you - it is not only about experimenting per se.</p><p>Experiments, fast feedback, rapid delivery - those are just side-effects. They happen, because something else happened before them.</p><p>One could ask - what happened before? What worked as a catalyst to obtain those effects?</p><p>Stand-ups? Retrospectives? Planning poker? Giving estimates on a non-repetitive tasks?</p><h3 id="what-was-the-first-fast-feedback-or-backlog-grooming"><a href="#what-was-the-first-fast-feedback-or-backlog-grooming" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What was the first: fast feedback or backlog grooming?</h3><p>As we already discussed (let&#x27;s pretend, I know I am the only one talking here), it&#x27;s not about any kind of ceremony, because it wasn&#x27;t mentioned in our final definition (simple reasoning, isn&#x27;t it?).</p><p>I also assume none of us wants to perform ritualistic actions to satisfy demigods of time-wasting.</p><p>But let&#x27;s get not out of focus here.</p><p>One could call it too simplistic reasoning, but let&#x27;s do a thought experiment.</p><p>We are going to reverse engineer how to get to &quot;fast feedback&quot; state through questions.</p><p>Have you noticed? I deliberately left one word without a definition.</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">&quot;agility&quot; - definition</div><div class="pb-2 px-3"><div class="break-words"><p>ability to act quickly and <strong>easily</strong>.</p></div></div></div><p>Yes, I am talking about &quot;easily&quot;. Fast feedback (pun intended) from Google results in two definitions:</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">&quot;easily&quot; - first definition</div><div class="pb-2 px-3"><div class="break-words"><p>without difficulty or effort.</p></div></div></div><p>and</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">&quot;easily&quot; - second definition</div><div class="pb-2 px-3"><div class="break-words"><p>without doubt; by far.</p></div></div></div><p>Using those definitions, we can formulate inital questions.</p><p>How can we effortlessly get fast feedback? By introducing a small change.</p><p>How can we know it&#x27;s small enough? By specifying it in isolation.</p><p>How can we fearlessly introduce a small change? By integrating it with the rest without any problems.</p><p>How can we verify that it integrates with the rest without any problems? By verifying the value is delivered without interruptions.</p><p>Stop. Retrospection time.</p><p>A small change?</p><p>A Specification?</p><p>An Integration?</p><p>A Verification?</p><p>If we compose them altogether, we can get the answer to our question: how to get to &quot;fast feedback&quot;?</p><h3 id="are-you-agile"><a href="#are-you-agile" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Are you Agile?</h3><p>Repeat after me:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Fast feedback can be achieved by specifying a small change in isolation, integrating it with the rest of the system, and simultaneously maintaining the value delivered by it.</p></div></div></div><p>We can now replace &quot;fast feedback&quot; with &quot;agility&quot; and here you go.</p><p>But this is nothing new. There are people in our industry telling all of those truths. And we do not listen to them.</p><p>So there are four components: a small change, a specification, an integration and a verification. For now, they are only plain words.</p><p>Then, what is their technical manifestation?</p><p>A small change? Minimum viable capability.</p><p>A Specification? Tests.</p><p>An Integration? CI/CD.</p><p>A Verification? Tests.</p><p>What&#x27;s more:</p><ul><li>don&#x27;t get misleaded by &quot;Tests&quot; - there is a huge difference between specification and verification (check <a href="https://talesfrom.dev/blog/the-ambiguity-of-tdd">&quot;The ambiguity of TDD&quot;</a>)</li><li>to provide proper isolation one can start with &quot;Feature Toggling&quot; and treat it as a design tool (see my take on <a href="https://talesfrom.dev/blog/feature-toggling-as-a-design-tool">&quot;Feature toggling as a design tool?&quot;</a>)</li></ul><h3 id="are-you-fragile"><a href="#are-you-fragile" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Are you Fragile?</h3><p>Starting from the ceremonial side won&#x27;t get you far. Ritualistic approach might create illusion of progress and work, but it won&#x27;t solve problems with agility.</p><p>It might make you fragile. Fragility isn&#x27;t only reserved for all the frameworks that are supposed to help managing the project or delivery.</p><p>It starts from the software, from the technical aspect. Why?</p><p>Without understanding the problem, we can&#x27;t assign responsibilities.</p><p>Without assigning responsibilities, we can&#x27;t isolate things.</p><p>Without isolating things, we can&#x27;t get right boundaries.</p><p>Without getting right boundaries, we can&#x27;t get scoped, small changes.</p><p>So repeat after me:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Agility can be achieved by specifying a small change in isolation, integrating it with the rest of the system, and simultaneously maintaining the value delivered by it.</p></div></div></div>]]></content:encoded>
    <pubDate>Mon, 14 Nov 2022 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>programming</category><category>paradigms</category><category>problem-solving</category><category>learning</category><category>agile</category><category>feedback</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/language-of-the-problem</guid>
    <title>Language of the problem</title>
    <link>https://talesfrom.dev/blog/language-of-the-problem</link>
    <description>Why should we stop coding?</description>
    <content:encoded><![CDATA[<h3 id="what-happens-when-superman-does-not-use-his-powers"><a href="#what-happens-when-superman-does-not-use-his-powers" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What happens when superman does not use his powers?</h3><p>We are living in the world of constant changes and new tech emerging every minute (I know, I am exaggerating. Did it purposefully!).</p><p>Our software should evolve even faster. Today&#x27;s architecture might be obsolete in weeks, if we want to support new shiny use case.</p><p>Code must follow landscape that shapes itself. Code - a basic building block of the software systems.</p><p>We, developers and architects, can create things out of thin air. It fells almost unnatural!</p><p>Then, is the code our secret superpower?</p><h3 id="what-is-the-problem-with-a-language-of-the-problem"><a href="#what-is-the-problem-with-a-language-of-the-problem" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What is the problem with a language of the problem?</h3><p>Imagine a simple scenario: we are working with a collection of e-mails (valid and invalid ones) and we would like to get only invalid ones.</p><p>The example will be in C# and should be pretty straightforward.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="code-highlight language-cs"><span class="code-line"><span class="token comment">// somewhere in a method of the service...</span>
</span><span class="code-line"><span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">void</span></span> <span class="token function">DoCoolStuffWithEmails</span><span class="token punctuation">(</span><span class="token class-name">List<span class="token punctuation">&lt;</span>Email<span class="token punctuation">&gt;</span></span> emails<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> invalidEmails <span class="token operator">=</span> 
</span><span class="code-line">        emails
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">Where</span><span class="token punctuation">(</span>email <span class="token operator">=&gt;</span> <span class="token operator">!</span>email<span class="token punctuation">.</span>IsValid<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">ToList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token comment">//...consume it somehow</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Looks unharmful, right?</p><p>It is so typical that it looks innocently.</p><h3 id="what-is-your-problem"><a href="#what-is-your-problem" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;What is your problem?&quot;</h3><p>What problem can I see?</p><p>I don&#x27;t like the language used.</p><p>One could ask this question - why I am so nitpicky?</p><p>Why using computational power of the brain to even think about such a naive scenario?</p><p>Initially, we were challenged to solve the problem of getting invalid emails.</p><p>Above we can see a suggested solution (a model). In <a href="https://talesfrom.dev/blog/essentially-bounded-accidentally-unlimited">&quot;Essentially bounded, Accidentally unlimited&quot;</a>, I shared this observation:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>There is no single solution, but there is a single problem.</p></div></div></div><p>Avid peer developer could say: &quot;oh, you want to be more expressive?&quot;</p><h3 id="new-hope"><a href="#new-hope" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>New hope</h3><p>Here&#x27;s the next version that typically appears in the wild:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="code-highlight language-cs"><span class="code-line">
</span><span class="code-line"><span class="token keyword">private</span> <span class="token class-name return-type">List<span class="token punctuation">&lt;</span>Email<span class="token punctuation">&gt;</span></span> <span class="token function">GetInvalidEmailsFrom</span><span class="token punctuation">(</span><span class="token class-name">List<span class="token punctuation">&lt;</span>Email<span class="token punctuation">&gt;</span></span> emails<span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
</span><span class="code-line">    emails
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">Where</span><span class="token punctuation">(</span>email <span class="token operator">=&gt;</span> <span class="token operator">!</span>email<span class="token punctuation">.</span>IsValid<span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token punctuation">.</span><span class="token function">ToList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">        
</span><span class="code-line"><span class="token comment">// somewhere in a method of the service...</span>
</span><span class="code-line"><span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">void</span></span> <span class="token function">DoCoolStuffWithEmails</span><span class="token punctuation">(</span><span class="token class-name">List<span class="token punctuation">&lt;</span>Email<span class="token punctuation">&gt;</span></span> emails<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> invalidEmails <span class="token operator">=</span> <span class="token function">GetInvalidEmailsFrom</span><span class="token punctuation">(</span>emails<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token comment">//...consume it somehow</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Great, readability increased. Intention is explicit now.</p><p>Still, I don&#x27;t like it.</p><h3 id="the-dot-will-tell-you"><a href="#the-dot-will-tell-you" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;The dot&quot; will tell you</h3><p>Bear with me, for a while (I know you will, because you are already spending your energy to read this!).</p><p>We already agreed (or at least I enforced it, my speachless reader) that our approach is one of the possible models.</p><p>I like to think that a model is materializing a certain capability, or responsibility.</p><p>Let pause for a while and ask a question:</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>What responsibility do we want to get from our model?</p></div></div></div><p>It should be responsible for giving us only invalid e-mails.</p><p>How could we check what it can do?</p><p>We can just hit &quot;the dot&quot; (<code>.</code>) on our keyboard and we will get, of course, all of the available operations (i.e. methods).</p><p>What methods do we get in return, after hitting &quot;the dot&quot;?</p><p>Here are just some of them:</p><ul><li><code>Any</code></li><li><code>Add</code></li><li><code>Where</code></li><li><code>Select</code></li><li><code>GroupBy</code></li><li>etc.</li></ul><p>Let&#x27;s be honest - are we getting the desired responsibility?</p><h3 id="paying-attention-to-the-language"><a href="#paying-attention-to-the-language" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Paying attention to the language</h3><p>We were pretty clear with our &quot;question&quot; to the model - we stated <strong>WHAT</strong> we want to get, but instead we got <strong>HOW</strong>.</p><p>Still, the language, a breakpoint that triggered entire &quot;discussion&quot; (in fact it is a monologue, because I am the only one talking, but let&#x27;s pretend it is a discussion!), isn&#x27;t right.</p><p>We didn&#x27;t mention all those technical operations.</p><p>A remedy?</p><h3 id="stop-coding-start-modelling"><a href="#stop-coding-start-modelling" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Stop coding, start modelling</h3><p>Let&#x27;s suggest another model.</p><p>A model where the concept of e-mails is really visible, and real.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Emails</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">  <span class="token comment">// I am empty :-(</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Here it is. Our new, powerful model.</p><p>Of course, when we use &quot;the dot&quot;, we are not getting any capabilities.</p><p>It&#x27;s pretty useless, isn&#x27;t it?</p><p>Ok, let&#x27;s &quot;teach&quot; it some cool skillz. The first one of course will be giving us a list of invalid emails.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Emails</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">  <span class="token keyword">public</span> <span class="token class-name return-type">List<span class="token punctuation">&lt;</span>Email<span class="token punctuation">&gt;</span></span> <span class="token function">GetInvalidEmails</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">  <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">return</span> <span class="token keyword">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// look how cool I am, I know new syntax</span>
</span><span class="code-line">  <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Impressive, but it&#x27;s not working. We could ask ourselves: to satisfy this responsibility, what does <code>Emails</code> need to know?</p><p>Easy.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Emails</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">  <span class="token keyword">private</span> <span class="token class-name">List<span class="token punctuation">&lt;</span>Email<span class="token punctuation">&gt;</span></span> _emails<span class="token punctuation">;</span> <span class="token comment">// details</span>
</span><span class="code-line">
</span><span class="code-line">  <span class="token keyword">public</span> <span class="token function">Emails</span><span class="token punctuation">(</span><span class="token class-name">List<span class="token punctuation">&lt;</span>Email<span class="token punctuation">&gt;</span></span> emails<span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
</span><span class="code-line">    _emails <span class="token operator">=</span> emails<span class="token punctuation">;</span> <span class="token comment">// ctor</span>
</span><span class="code-line">
</span><span class="code-line">  <span class="token keyword">public</span> <span class="token class-name return-type">List<span class="token punctuation">&lt;</span>Email<span class="token punctuation">&gt;</span></span> <span class="token function">GetInvalidEmails</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
</span><span class="code-line">    _emails
</span><span class="code-line">    <span class="token punctuation">.</span><span class="token function">Where</span><span class="token punctuation">(</span>email <span class="token operator">=&gt;</span> <span class="token operator">!</span>email<span class="token punctuation">.</span>IsValid<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">.</span><span class="token function">ToList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Woah, outstanding. Who did expect such evolution? Nevertheless, our work isn&#x27;t finished.</p><p>We need to utilize our new friend. I got rid of unused method from previous attempt.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="code-highlight language-cs"><span class="code-line"><span class="token comment">// somewhere in a method of the service...</span>
</span><span class="code-line"><span class="token keyword">public</span> <span class="token class-name return-type"><span class="token keyword">void</span></span> <span class="token function">DoCoolStuffWithEmails</span><span class="token punctuation">(</span><span class="token class-name">List<span class="token punctuation">&lt;</span>Email<span class="token punctuation">&gt;</span></span> emails<span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> emailz <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name constructor-invocation">Emails</span><span class="token punctuation">(</span>emails<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token class-name"><span class="token keyword">var</span></span> invalidEmails <span class="token operator">=</span> emailz<span class="token punctuation">.</span><span class="token function">GetInvalidEmails</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token comment">//...consume it somehow</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>How cool is that?!</p><h3 id="what-the-hell-have-just-happened-"><a href="#what-the-hell-have-just-happened-" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What the hell have just happened? 😲</h3><p>You might wonder: &quot;Is this dude crazy? Why freaking with a simple class?&quot;</p><p>Well, it might sound strange, but I don&#x27;t see only a simple class.</p><p>I see a materialized concept, not just &quot;a class&quot;.</p><p>It carries the context with it, binding a language, which is valid only within this context. (isn&#x27;t it one of the definitions of <em>Bounded Context</em>? 🤔)</p><p>It satisfies the responsibility, we wanted it to get. When &quot;dotting&quot; it, we see what is possible. Nothing more, nothing less.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>A concept carries the context with it, binding a language, which is valid only within this context.</p></div></div></div><p>We taught it what it needs to know.</p><h3 id="nihil-novi"><a href="#nihil-novi" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Nihil novi</h3><p>This, of course, isn&#x27;t something new. Encapsulation, single responsibility, object-orientation, etc.</p><p>Name it as you want.</p><p>Mentioned heuristics, are yet again &quot;technical&quot; terms. And they are highly useful.</p><p>Thinking in terms of &quot;concepts&quot;, about <strong>what</strong>, deferring <strong>how</strong>, expresses the right language.</p><p>It (the language), gives the meaning, determining the rules how one can use a given concept.</p><p>Such a modelling approach is very friendly, because of making it easier, for other programming folks, to get the intention faster. Documenting and capturing the context, so that it can evolve within its boundaries.</p><h3 id="what-about-flexibility"><a href="#what-about-flexibility" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What about flexibility?</h3><p>But actually, is it all flowers and butterflies?</p><p>Nope, one could argue we &quot;lost&quot; the flexibility of underlying data structure (a list).</p><p>We can&#x27;t just rush to extract other details, use some interesting transformations. There&#x27;s an additional effort to achieve so.</p><p>And that&#x27;s fine.</p><p>Now it requires <strong>discipline</strong>, thus thought process, to pause and analyze, is it the right direction.</p><p>When new requirements are in place, we would be &quot;encouraged&quot; to stop and start asking (examplary) questions:</p><ul><li>What other responsibilities it needs to know?</li><li>When it is too much?</li><li>Does it need help from external collaborators?</li><li>etc.</li></ul><p>Our job is not to &quot;code&quot;, but to solve problems, preferably by providing models. Modelling.</p><h3 id="why-limiting-yourself"><a href="#why-limiting-yourself" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Why limiting yourself?</h3><p>I like what <a href="https://grugbrain.dev/">grug</a> &quot;said&quot;:</p><blockquote><p>Apex predator of grug is complexity.</p></blockquote><p>I want to keep the apex predator in the single place. The best place for apex predator is in the cage. Or in a small box.</p><p>I want to exchange this box with something else, when necessary.</p><p>Yes, we are putting limits on ourselves. That&#x27;s deliberate. Such discipline gives us some interesting properties.</p><p>Ease of reasoning (I already tried to discuss <a href="https://talesfrom.dev/blog/the-value-of-value-objects">&quot;The value of Value Objects&quot;</a>).</p><p>Ease of giving the meaning to a technical data structures.</p><p>Ease of communication.</p><p>Every limit is a possibility, every possibility is a limit.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Stop coding, start modelling.</p></div></div></div><p>What&#x27;s more, I think it&#x27;s wise to stop lying to ourselves that things are simpler than they really are.</p><p>One could easily call such an approach, which I am trying to present, &quot;unnecessarily complex&quot;.</p><p>What if such &quot;complexity&quot;, of the concept we try to model (with its context), is hidden in the author&#x27;s head?</p><p>Aren&#x27;t we trying to turn our heads around, when unintentionally hiding in our heads the context and intentions, and stating &quot;nothing to see here&quot;?</p><h3 id="a-bonus-are-we-dealing-with-any-email"><a href="#a-bonus-are-we-dealing-with-any-email" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>A bonus: are we dealing with any email?</h3><p>Let&#x27;s recall our suggested model:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-csharp code-highlight"><span class="code-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Emails</span>
</span><span class="code-line"><span class="token punctuation">{</span>
</span><span class="code-line">  <span class="token keyword">private</span> <span class="token class-name">List<span class="token punctuation">&lt;</span>Email<span class="token punctuation">&gt;</span></span> _emails<span class="token punctuation">;</span> <span class="token comment">// details</span>
</span><span class="code-line">
</span><span class="code-line">  <span class="token keyword">public</span> <span class="token function">Emails</span><span class="token punctuation">(</span><span class="token class-name">List<span class="token punctuation">&lt;</span>Email<span class="token punctuation">&gt;</span></span> emails<span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
</span><span class="code-line">    _emails <span class="token operator">=</span> emails<span class="token punctuation">;</span> <span class="token comment">// ctor</span>
</span><span class="code-line">
</span><span class="code-line">  <span class="token keyword">public</span> <span class="token class-name return-type">List<span class="token punctuation">&lt;</span>Email<span class="token punctuation">&gt;</span></span> <span class="token function">GetInvalidEmails</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token comment">// is it ANY email?</span>
</span><span class="code-line">    _emails
</span><span class="code-line">    <span class="token punctuation">.</span><span class="token function">Where</span><span class="token punctuation">(</span>email <span class="token operator">=&gt;</span> <span class="token operator">!</span>email<span class="token punctuation">.</span>IsValid<span class="token punctuation">)</span>
</span><span class="code-line">    <span class="token punctuation">.</span><span class="token function">ToList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Avid reader might notice that <code>GetInvalidEmails</code> returns a list of <code>Email</code>s. Method itself says it is giving out only <strong>invalid</strong> emails.</p><p>Are we missing something? What do you think?</p>]]></content:encoded>
    <pubDate>Wed, 02 Nov 2022 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>programming</category><category>paradigms</category><category>domain-driven design</category><category>problem-solving</category><category>language</category><category>learning</category><category>encapsulation</category><category>value objects</category><category>code</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/microoffices-vs-officeolith</guid>
    <title>&quot;Microoffices&quot; vs &quot;Officeolith&quot;</title>
    <link>https://talesfrom.dev/blog/microoffices-vs-officeolith</link>
    <description>What we can learn from the evolution of a small business?</description>
    <content:encoded><![CDATA[<h3 id="the-oracle"><a href="#the-oracle" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The Oracle</h3><p>We, developers and architects, tend to think about modularity. Scale. Evolvability. Flexibility.</p><p>Predicting the future so that our design is robust. Anti-fragile.</p><p>Those are the traits we seek when facing the problem.</p><p>While business people are dreaming of neverending stream of value, being delivered through product that effortlessly and costlessly could react and adapt to the market changes, we, technologists, try to provide tools supporting such dystopian vision.</p><p>We all know that, right?</p><h3 id="no-tech-around-us"><a href="#no-tech-around-us" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>No tech around us</h3><p>Taking into account that we could think of our system as an <a href="https://talesfrom.dev/blog/organization-driven-design">Organization</a>, I wonder what would happen if we could imagine an evolution of a new business. Wouldn&#x27;t observing all the decisions made on each step be thrilling? What we could learn?</p><p>Let&#x27;s spin up creativity cluster and jump into the wilderness of completely making up a business tale! Here we go!</p><div class="bg-slate-600 rounded-xl "><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Attention!</span></div><div class="pb-2 px-3"><div class="break-words"><p>Bear in mind I have never, ever, experienced business development myself.</p>
<p>No company was harmed during writing this tale.</p></div></div></div><h3 id="meet-jack-cleaner"><a href="#meet-jack-cleaner" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Meet Jack, &quot;CLeaner&quot;</h3><p>Warm applause for Jack, the founder of a tiny, single person company called &quot;CLean Inc.&quot;.</p><div class="flex flex-col justify-center items-center"><img class="m-0" src="https://talesfrom.dev/static/images/company-single-jack.png" style="width:80%;height:80%"/></div><p>As you see, he has a tiny, bit empty office, because he just started his entrepreneurship.</p><p>He wants to conquer the world with his cleaning skills and lean attitude to the business.</p><p>Jack works alone, trying to serve his customers in the most competent manner.</p><h3 id="too-much-on-the-plate"><a href="#too-much-on-the-plate" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Too much on the plate</h3><p>Turns out, Jack knows how to work in the cleaning market. He has some experience with talking to cleaning products companies so soon he sees opportunities with starting the partnership with some of them.</p><p>Customer base grows, Jack can&#x27;t clone himself. The decision is made - he needs to hire another person.</p><div class="flex flex-col justify-center items-center"><img class="m-0" src="https://talesfrom.dev/static/images/company-jack-and-new-guy.png" style="width:80%;height:80%"/></div><p>Say hi to Jim, the worker. He knows cleaning business quite well and he&#x27;s not afraid of working hard to achieve the best quality of the service.</p><p>This is something that Jack, the founder, really liked in Jim - the spark in the eye when vacuuming the floor.</p><p>Jack was thinking if Jim should have his own office, but it didn&#x27;t add up - this costs and still they work closely together.</p><p>There is no point of putting a wall between them.</p><h3 id="three-is-more-than-two"><a href="#three-is-more-than-two" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Three is more than two</h3><p>Months were passing rapidly and both Jack and Jim couldn&#x27;t keep up with growing demands from the market.</p><p>New cleaning products, new methods of vacuuming, new approaches to window polishing - each customer has its own wishes.</p><p>Jack, the founder, decided again - &quot;CLean Inc.&quot; needs a new cleaning talent.</p><div class="flex flex-col justify-center items-center"><img class="m-0" src="https://talesfrom.dev/static/images/company-jack-jim-dan.png" style="width:80%;height:80%"/></div><p>That&#x27;s how Dan got the job. Jack saw how Dan is wholeheartedly servicing the customer on his trial day. That made the difference.</p><p>Well, Jack had this thought again - three people in the single office. How unprofessional. Probably other cleaning companies are having luxurious and spacious rooms for each of the individual.</p><p>But Jack made a tough decision - what&#x27;s the point of putting each of them in the &quot;box&quot; as they need to communicate efficiently about what are the plans.</p><h3 id="the-cleaning-squad"><a href="#the-cleaning-squad" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The CLeaning Squad</h3><p>Is there something better than success? MASSIVE success.</p><p>Soon, &quot;CLean Inc.&quot; started becoming a benchmark company for how cleaning quality should be provided.</p><p>When people started sharing contact to the Jack, the founder, the requests skyrocketed. He was so busy with answering the questions, taking the calls, he needed to stop cleaning at all.</p><p>This required growing the company. This is exactly what Jack did.</p><p>Meet &quot;The Squad&quot;.</p><div class="flex flex-col justify-center items-center"><img class="m-0" src="https://talesfrom.dev/static/images/company-jack-and-cleaning-squad.png" style="width:80%;height:80%"/></div><p>Jack and his &quot;commandos&quot; were widely recognized for the level of service they provided.</p><p>But things changed - &quot;The CLeaners&quot; were chatting about new formulas of cleaning products, recent news claiming that cleaning robots are better for doing room service than humans, and so on.</p><p>Jack, the founder, didn&#x27;t have time for such activities. He realized he needs to focus on providing the correct plans and vision for the company, as they received more time in the spotlight.</p><p>Jack also observed that he no longer used &quot;cleaning&quot; language - he spoke about plans, mission, economy, budgeting.</p><p>Totally different realms.</p><p>He made the decision - it&#x27;s time to get the new office for him. And as he wasn&#x27;t into cleaning topics that much, he needed someone who will take care of the squad.</p><h3 id="the-wall"><a href="#the-wall" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The Wall</h3><p>This felt really good. Jack finally had calm time talking to customers, planning strategy for expansion.</p><p>He hired Tom, the cleaning squad manager. His main job was to organize the work for the workers.</p><p>He thought of moving the squad to another building, just to make sure they won&#x27;t interrupt him too often.</p><p>It didn&#x27;t add up - there was no point for renting new office space.</p><div class="flex flex-col justify-center items-center"><img class="m-0" src="https://talesfrom.dev/static/images/company-manager.png" style="width:80%;height:80%"/></div><p>Everything was going so smoothly - Jack started marketing campaings that made his people even more busy.</p><p>He was really proud of the squad, the work that Tom did to make the cleaning service the best gift people could ever imagine.</p><p>But Jack started receiving feedback from the customers that sometimes a cleaner needs to go back and forth between the premise, where the cleaning service is given, and one of the shops having cleaning products. Such events made entire service taking longer than expected, impacting schedule of other customers.</p><p>Simply unacceptable.</p><p>This made Jack wondering.</p><h3 id="no-more-delays"><a href="#no-more-delays" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>No more delays</h3><p>&quot;How can we prevent delays caused by the need to refill cleaning product?&quot; - that question was constantly in Jack&#x27;s head for couple of days.</p><p>The founder was playing with the idea that one of the cleaners will get new responsibility to ensure that other cleaners have all the means for providing the service, before they drive to the place.</p><p>There were doubts about if a single person manages all the complexity. &quot;Maybe I should get three more people into this responsibility?&quot;, he wondered.</p><p>It was a pure reasoning without evidence from the reality so Jack chose a single volunteer and started probing the solution.</p><p>He was very good observer - he noticed that this cleaner didn&#x27;t have time for cleaning responsibilities and the majority of his time was consumed by thinking about stocking up products, optimizing space on the shelves in the cleaners room.</p><p>What&#x27;s more, other &quot;CLeaners&quot; were a bit annoyed that he&#x27;s constantly interrupting their discussions by carrying boxes with cleaning products.</p><p>That was a clear (pun intended!) signal for Jack - the cleaning guy not doing cleaning work needs to have his own room.</p><p>The good part was that all people were in the same building. It was easy to move things here and there.</p><div class="flex flex-col justify-center items-center"><img class="m-0" src="https://talesfrom.dev/static/images/company-warehouse-single-worker.png" style="width:80%;height:80%"/></div><p>From now on, Wim was responsible for keeping cleaning products available for cleaners so that they can be prepared before the actual work.</p><h3 id="lean-approach"><a href="#lean-approach" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Lean approach</h3><p>Turned out that Jack&#x27;s idea was brilliant. Customers stopped complaining about delayed time for getting the service done.</p><p>What&#x27;s more, they glorified &quot;CLean Inc.&quot; for quickly responding to feedback. That made this little growing company really recognized.</p><p>&quot;Lean approach for cleaning&quot; - it became a known phrase used by the customers.</p><p>One day Jack, the founder, got a call from one of the delighted customers regarding floor conditioning product that was used by one of the cleaning commandos. The customer wanted to take chance and do some of the cleaning work by themselves.</p><p>Well, it didn&#x27;t sound good. Jack thought that the customer wants to stop getting the service. However, this made a huge opportunity for reselling the products from his partners.</p><p>Single customer asked for such service, but what happens if Jack starts asking directly &quot;do you need some cleaning products from our catalogue?&quot;.</p><p>He made couple of calls himself and turned out that there some potential there.</p><p>But Wim was very clear in his message - he can&#x27;t keep up with the cleaning squad right now so there&#x27;s no chance he manages to supply external parties.</p><p>Jack was also terrified with accounting of such endeavour. Up to now, he was able to do everything by his own, but putting more attention into supplying responsibility will devour even more of his precious time.</p><h3 id="the-next-level-of-service"><a href="#the-next-level-of-service" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The next level of service</h3><p>Jack, the founder, didn&#x27;t wait. He hired bunch of new warehousing people, along with Winston, their manager. Additionally, to mitigate accouting issues, he hired Paul, the accountant.</p><p>Jack knew that Paul&#x27;s work is totally different than cleaning work and supplying cleaning products - Paul got separate room. No one except Paul needed to know about the books, end of month, etc.</p><div class="flex flex-col justify-center items-center"><img class="m-0" src="https://talesfrom.dev/static/images/company-warehouse.png"/></div><p>Did it work? Hell yeah.</p><p>Customers didn&#x27;t stop getting cleaning services, but even wanted to get &quot;all those great products&quot; directly from the &quot;CLean Inc.&quot;.</p><p>Soon, Jack, the founder, wasn&#x27;t able to respond to all the shopping requests. He tried pretending he is able to handle everything - company strategy planning, thinking how to grow and do the selling part.</p><p>He got pretty tired. The decision was made - Jack won&#x27;t be responsible for sales. This responsibility is going to be in hands of new team - THE Sales.</p><div class="flex flex-col justify-center items-center"><img class="m-0" src="https://talesfrom.dev/static/images/company-sales.png"/></div><p>Sales people were very energetic, motivated and a bit too loud for Paul, there were speaking about KPIs, targets and so on. This was strong signal towards giving them their own office.</p><h3 id="cleaner-winner"><a href="#cleaner-winner" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;CLeaner Winner&quot;</h3><p>Reaching sales goals were so surprising for Jack that he couldn&#x27;t believe what&#x27;s was happening.</p><p>&quot;CLean Inc.&quot; was able to get another revenue stream. Everything looked like in the dream.</p><p>The cleaning squad was doing great, the sales were able to increase customer base even more, the supplies warehousing people got really busy.</p><p>&quot;Some products we&#x27;re getting from you are good, but not best&quot; - the opinion that changed everything.</p><p>Jack read one of the e-mails from their customers. One could be sad that the customer wasn&#x27;t happy, but Jack clearly saw the opportunity - &quot;CLean Inc.&quot; will make new product that will be the number one in terms of cleaning.</p><p>Unfortunately, he didn&#x27;t know anything about creating such products. Nothing.</p><p>Jack, the founder, started reading, searching the internet, asking people, but he wasn&#x27;t expert in that. Such responsibility wasn&#x27;t clearly his the highest competence.</p><div class="flex flex-col justify-center items-center"><img class="m-0" src="https://talesfrom.dev/static/images/company-rnd.png"/></div><p>Exactly due to this reason the R&amp;D crew was founded. Chemistry engineers, cleaning passionates were involved in this journey.</p><p>Jack was really happy. He had means to invest tons of money to be recognized not only by their perfection in servicing customers, but also for high-tech cleaning products.</p><p>He immediately knew that R&amp;D people need to have calm workplace, far from the noise coming from the cleaning commandos, suppliers or always happy the sales team.</p><p>So they got their small lab to be creative and invent new products that will dominate the market.</p><p>That&#x27;s how &quot;CLeaner Winner&quot; was made. Secret formula, full of strange names, was supposed to conquer establishment of the cleaning industry.</p><h3 id="321production"><a href="#321production" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>3...2...1...Production!</h3><p>The manager of R&amp;D was very clear - they know how to invent new formulas and think of products, but they can&#x27;t bring them alive for huge scale.</p><p>Jack, the founder, was adviced that if he wants to make a real difference, they need to invest money in manufacturing. Tons of money. A simple reason was the effect of scale - they will be able to lower the costs by having their own production lines.</p><div class="flex flex-col justify-center items-center"><img class="m-0" src="https://talesfrom.dev/static/images/company-manufacturing.png"/></div><p>The founder didn&#x27;t wait for more opinions. He felt he needs to go All in.</p><p>That&#x27;s how product manufacturing and internal product warehousing teams were established.</p><p>After making the decision, it was known they both need to have their own space. The sounds of the machines, optimizing of the production, replanning the production lines - totally different world than the rest of the company.</p><p>Boom. &quot;CLeaner Winner&quot; started becoming the number one of the cleaning products. The response from the market was clear - it was the right decision.</p><p>Unfortunately, new problems started emerging. Due to the power consumption, enormously loud noise and sounds, other departments couldn&#x27;t do their job efficiently.</p><p>Jack couldn&#x27;t take more complains from the rest of the organization, so he decided that the manufacturing and its warehousing need to be in another building. Having two, distributed offices will alleviate some of the problems and this should make other parts of organization highly focused.</p><p>Additionally, accounting team get some new people on the board, because of the number of invoices piling up on Paul&#x27;s desk.</p><div class="flex flex-col justify-center items-center"><img class="m-0" src="https://talesfrom.dev/static/images/company-distribute-manufacturing.png"/></div><h3 id="send-me-an-e-mail"><a href="#send-me-an-e-mail" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Send me an e-mail&quot;</h3><p>It became quite and calm, as before founding manufacturing and its warehousing. Distributing these responsibilities looked like a good decision.</p><p>Even though the problem of a loud neighbor disappeared, another issue arouse. R&amp;D team was complaining about communication with manufacturers. Previously they could just go to their place and see how they are making things and ensure the right quality.</p><p>Now it&#x27;s totally different. They are scheduling meetings, having calls and exchanging e-mails.</p><p>When the new batch is finally released, it takes time for the delivery guys to bring it for assessment. Suddenly, the distance between the sides became the problem.</p><h3 id="plagiarism"><a href="#plagiarism" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Plagiarism</h3><p>Other manufacturers were envy of the formula and started copying the ingridients. This made Jack furious. He immediately called other manufacturers threatening going to the court, but they just laughed.</p><p>There was a problem - Jack knew almost nothing about the legal part of manufacturing, plagiarism and so on.</p><div class="flex flex-col justify-center items-center"><img class="m-0" src="https://talesfrom.dev/static/images/company-legal.png"/></div><p>He didn&#x27;t wait and hired the new team, responsible for legal activities. For sure this shouldn&#x27;t be the responsibility of the founder to know such things. In order to have constant and quick communication line, they were placed closely to his office.</p><h3 id="research-company"><a href="#research-company" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Research company</h3><p>The legal people made Jack confident. He sensed they could become the leader of nanotechnology, when it comes to cleaning business.</p><p>Being reinforced by the legal, knowing that their intellectual property is properly secured, &quot;CLean Inc.&quot; heavily invested in this branch of the industry.</p><p>This made things clear - R&amp;D team needed to grow. High-end lab, full of expensive, advanced appliances was the clear goal.</p><p>The legal advised that industrial espionage is very typical, especially in the cleaning industry.</p><p>The decision was made - the lab needs to be secret and hidden from the world.</p><div class="flex flex-col justify-center items-center"><img class="m-0" src="https://talesfrom.dev/static/images/company-distributed-rnd.png"/></div><p>Soon, the lab was founded. Only chosen ones knew where it is located, but it was doing great.</p><p>Cleaning services, cleaning products got a new friend - cleaning research. In a few months, &quot;CLean Inc.&quot; started giving advanced consulting for other companies, e.g. where tough conditions made cleaning very difficult.</p><p>Of course, communication suffered. Jack, the founder, observed that distributing the R&amp;D team made him unaware of multiple topics.</p><p>Having separate office, &quot;the lab&quot;, made them flexible in terms of space, power consumption.</p><p>But about cleaning services.</p><h3 id="autonomous-bubble"><a href="#autonomous-bubble" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Autonomous bubble</h3><p>Turned out that &quot;The CLeaning Squad&quot; was pretty isolated from the new areas of the company. They were providing services with the highest possible quality.</p><p>Keeping them in the single building was really wasteful, because cleaning services department could be easily scaled out or scaled up.</p><p>It was tough decision for Jack, because he started as a &quot;cLeaner&quot;. Even though he no longer did cleaning work, he felt a bit attached.</p><p>Still, he tried to balance pros and cons, finally deciding that cleaning services will get their own office, in another building.</p><p>Distributing this responsibility felt good, because cleaning research and their advanced cleaning products might soon required highly specialized &quot;cLeaners&quot;.</p><div class="flex flex-col justify-center items-center"><img class="m-0" src="https://talesfrom.dev/static/images/company-four-premises.png"/></div><p>Jack, the founder, was right - customers soon required pioneering cleaning services and that was the responsibility of the cleaning squad. They got their training facilities, full of the equipment to develop their skills.</p><h3 id="the-journey"><a href="#the-journey" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The journey</h3><p>Phew, that was pretty long, isn&#x27;t it?</p><p>Yes, I also got tired. I hope it was worth it to stand next to Jack and his decisions, along the way.</p><p>I know it was completely made up and some of the events won&#x27;t be that easy.</p><p>Nevertheless, our minds are great in pretending that things are happening in real, isn&#x27;t it?</p><h3 id="lessons-learned"><a href="#lessons-learned" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Lessons learned</h3><p>For sure Jack didn&#x27;t keep architecture decision records in his office. But he was deciding all the time. As we do. Sometimes decisions were hard, sometimes full of courage and trust.</p><p>In the most cases he probed the reality to find if his ideas made sense.</p><p>How it could look like in the software world?</p><p>Let&#x27;s look from &quot;the software&quot; perspective on some of the areas:</p><ul><li>Was Jack &quot;agile&quot;?</li><li>Jack didn&#x27;t distribute the capabilities of his company early. He waited until there will be intense signals for doing so. Should he distribute the company earlier?</li><li>He also didn&#x27;t prepare for massive scale, from the day one. Waiting, observing, analyzing - all of those made him confident to hire more people. Was that a right decision?</li><li>Did Jack establish the legal team when he scaled cleaning services crew? Why not?</li><li>Why Jack didn&#x27;t move R&amp;D team to a separate building sooner?</li><li>What was the downside of keeping cleaning services and external products warehousing in the same building?</li></ul><h3 id="the-metaphor"><a href="#the-metaphor" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The metaphor</h3><p>I love metaphors, I hope you see it.</p><p>Each part of the tale has its counterpart in software world.</p><p>Jack didn&#x27;t start with &quot;microoffices&quot;. He begun with &quot;modular officeolith&quot;.</p><p>Along the steps, he refactored the organization toward better structure, based on the responsiblities of each department.</p><p>The opportunities arouse and Jack was responding accordingly, without going to full-blown distributed architecture.</p><p>&quot;CLean Inc.&quot; evolved organically, mitigating unnecessary complexity.</p><p>At the same time, Jack didn&#x27;t wait until the entropy creeped into the organization.</p><p>He did housekeeping (orgkeeping?) gradually, leading toward protected boundaries that made entire organization modular.</p><h3 id="organization-driven-design"><a href="#organization-driven-design" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Organization-Driven Design</h3><p>This was an extension to the metaphor I played with here: <a href="https://talesfrom.dev/blog/organization-driven-design">&quot;Organization-Driven-Design&quot;</a>.</p><p>Imagining how &quot;organization&quot; could develop might bring interesting insights to the decision process, when it comes to the architecture of our systems.</p><p>We could think of a system as: classes, functions, projects, APIs, React components, etc.</p><p>Such model opens the world full of various, more business-oriented perspectives and questions.</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>What happens when you treat evolution of your system as an organization evolution?</p></div></div></div>]]></content:encoded>
    <pubDate>Sat, 15 Oct 2022 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>modularity</category><category>paradigms</category><category>domain-driven design</category><category>problem-solving</category><category>organization</category><category>boundaries</category><category>principles</category><category>fundamentals</category><category>context</category><category>metaphores</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/software-engineering-for-busy-parents</guid>
    <title>Software Engineering for busy parents</title>
    <link>https://talesfrom.dev/blog/software-engineering-for-busy-parents</link>
    <description>How to keep up with tech when babies are crying?</description>
    <content:encoded><![CDATA[<h3 id="being-lost"><a href="#being-lost" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Being lost</h3><p>Is there a new framework or a library that draws attention of entire community, but the only thing you made is reading a tweet about it?</p><p>Did you, during the conversation, hear <a href="https://htmx.org">htmx</a>, but you thought someone made mistake and should say <code>html</code>?</p><p>Have you been late with using new C#11 &quot;double bang&quot; operator, because it got rejected before you even learned about it?</p><p>Welcome to the club of busy people!</p><h3 id="what-is-the-meaning-of-life"><a href="#what-is-the-meaning-of-life" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What is the meaning of life?</h3><p>Of course, I don&#x27;t mean life life - I am talking about your, mine, professional life.</p><p>Are we dopamine-driven, technology-fueled creatures, enchanted in a human body?</p><p>There&#x27;s also &quot;after life&quot;. Life after professional life, where babies are crying, you are tired and your back hurts.</p><p>Still, as software engineering professionals, we would like to be up to date with the coolest and the newest stuff.</p><p>Is there a lighthouse of knowledge, showing the direction for ships having various stops during the day?</p><h3 id="it-is-not-about-k8s-or-microservices"><a href="#it-is-not-about-k8s-or-microservices" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>It is not about k8s or microservices</h3><p>I don&#x27;t want to look as if I am demonizing or devaluating either k8s or microservices. They are applicable to set of problems, but in other scenarios might be pretty cumbersome.</p><p>Technologies get outdated.</p><p>Ideas, concepts and fundamentals preserve.</p><p>It&#x27;s nothing new, or even fancy.</p><p>Might be that some of the new, sexy toys materialize some &quot;old&quot;, well-explored concepts, because finally we arrived at the moment of time when it is technologically possible to bring them to live.</p><p>On the other hand, innovation happens not in the vacuum, but rather by mixing up experience, incubated ideas, stories and patterns. Such amalgamation produce a graph of things connected in the new, creative way.</p><p>Nevertheless, coming up with so-called &quot;Maxwell equations&quot;, discovering &quot;Foucault&#x27;s current&quot; or imagining &quot;Theory of relativity&quot;, were not invented in the single night.</p><p>They might appear as an final, read-model state, but actually it was a process full of consequitive events, leading to the final event of breakthrough.</p><h3 id="programming-is-fun"><a href="#programming-is-fun" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Programming is fun</h3><p>You might call me naive, but recently I am getting more and more aware that &quot;coding&quot; is a teeny-tiny droplet of entire endeavour.</p><p>Maybe it is because of not having that much spare time for it as I would wish for.</p><p>It is fun to build, to make, to create, to feel &quot;the zone&quot; and get lost of one&#x27;s ego in a pure bliss of creation.</p><p>But is it the only thing that constitutes &quot;Software Engineering&quot;?</p><p>I really love the first sentence of the book <a href="https://www.amazon.com/Applying-UML-Patterns-Introduction-Object-Oriented/dp/0131489062">Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development</a>:</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Programming is fun, but developing high quality software is hard.</p></div></div></div><p>We can&#x27;t just develop, we need to embrace what is known for so long time - it should be &quot;doable&quot; by standing on the shoulders&#x27; of giants.</p><h3 id="software-engineering-for-busy-parents"><a href="#software-engineering-for-busy-parents" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Software Engineering for busy parents</h3><p>Of course, you might not be a busy parent and still benefit from battle-tested, &quot;old&quot; observations about Software Engineering.</p><p>There are various concepts, patterns or approaches I find particurarly interesting. Most of them I learned either from courses, books, articles, videos or from production experience.</p><p>What is great about them? It is the fact that one can use it agnostic to the technology. They are not subjects of changes, at least not so frequently.</p><p>The stability of their wisdom is the key here.</p><p>They might be considered as &quot;general problem solving skills&quot;.</p><p>Let me channel them in the form of text, for you, my dear Reader!</p><h3 id="1-focus-on-the-problem-forget-the-programming-part"><a href="#1-focus-on-the-problem-forget-the-programming-part" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>1. Focus on the problem, forget the programming part</h3><p>We, developers, tend to jump to sketching or prototyping the solution almost immediately.</p><p>It is so easy to open editor and draft couple of classes (which turn out to have no responsibility and be simple POCOs - there will be separate blog post about it soon!).</p><p>I learned two fundamental, analytical questions that I am trying to use on every problem I try to solve:</p><ul><li>What is the problem I am currently solving?</li><li>What is the problem I am not currently solving?</li></ul><p>They both try to help on finding the true nature of the case we are working on, counteracting on so-called <a href="https://xyproblem.info/">The XY Problem</a>.</p><p>For example, when you try to fix a bug, don&#x27;t refactor code at the same time. It is well-known from TDD approach, especially when doing verification through tests (Would you like to get mine perspective on it? Please check <a href="https://talesfrom.dev/blog/the-ambiguity-of-tdd">&quot;The ambiguity&quot; of TDD</a>).</p><p>But both questions apply well to such scenario, namely:</p><ul><li>&quot;What is the problem I am currently solving?&quot; - fixing a bug</li><li>&quot;What is the problem I am not currently solving?&quot; - refactoring ugly code.</li></ul><p>How can you utilize those questions in scenario, you are/were/will be working on?</p><h3 id="2-two-weeks-of-development-can-save-you-15-minutes-of-analysis"><a href="#2-two-weeks-of-development-can-save-you-15-minutes-of-analysis" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>2. &quot;Two weeks of development can save you 15 minutes of analysis&quot;</h3><p>The first time I&#x27;ve heard this phrase from <a href="https://twitter.com/SlawekSobotka">Sławek Sobótka</a> in one of his talks.</p><p>It&#x27;s self-describing - in most of the cases spending time on understanding the problem might bring enormous benefits.</p><p>You either save time (meaning money) by modelling correct solution OR by not spending time on corrupted/broken/wrong model.</p><p>Next time, even when working on a feature that &quot;seems simple&quot;, try to think of it a bit more deeply, setting aside a 15 minutes.</p><h3 id="3-validating-usefulness-of-your-modelsolution"><a href="#3-validating-usefulness-of-your-modelsolution" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>3. Validating usefulness of your model/solution</h3><p>Imagine we did a short analysis and it seems we understand the problem quite well.</p><p>After a brief thinking we have the solution. We start implementing it and soon it we are drowning in complexity. Do you know that feeling?</p><p>Seems like we are missing critical thinking about our solution.</p><p>I find a set of two questions working perfectly to achieve so:</p><ul><li>For the given context, what problem <code>X</code> solves?</li><li>For the given context, what problem <code>X</code> brings?</li></ul><p>Where <code>X</code> is your approach/model/solution/idea.</p><p>They appear as so stupidly obvious that I believe we often do not use them consciously. I learned about them in <a href="https://legacyfighter.pl/">Legacy Fighter</a> (only in Polish 😔) training.</p><p>I adore them so much!</p><p>We can use them for new method, responsibilities assignment, finding trade-offs, assessing new tool or thinking if a given architecture fits our needs.</p><p>They might be known as &quot;apply the right tool for the right job&quot;.</p><p>For instance, we need to have two bigger capabilities, A and B. We consider using either modular monolith or seperately deployable services (I am avoiding talking about microservices, because previously I said it is not about them so I need to keep my opinion, right?) to support them. Just to add more details, we are small team and capability B might require integration with legacy (mhm, I should say core product?).</p><p>And now:</p><ul><li>For the given context, what problem(s) modular monolith solves?</li><li>For the given context, what problem(s) modular monolith brings?</li><li>For the given context, what problem(s) seperately deployable services solve?</li><li>For the given context, what problem(s) seperately deployable services bring?</li></ul><p>Nice, isn&#x27;t it?</p><h3 id="4-watch-your-boundaries-capture-concepts"><a href="#4-watch-your-boundaries-capture-concepts" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>4. Watch your boundaries, capture concepts</h3><p>I couldn&#x27;t forget mentioning <a href="https://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215">Domain-Driven Design</a>.</p><p>I am not talking only about &quot;tactical&quot; parts of it, but also about &quot;soft&quot;-ish parts, which might be considered &quot;strategic&quot;.</p><p>Thinking contextually, carefully observing the language used, and finally looking for a model bounding domain language (which relates to a contextual world, a perspective) - true fundamentals, keeping their validity in most of the times.</p><p>It is also about reasonably capturing the concepts your domain consists of.</p><p>Not using only strings, collections or doubles, but building meaningful stories that live inside of your problem space. (What I am talking about? Please see <a href="https://talesfrom.dev/blog/the-value-of-value-objects">The value of Value Objects</a>).</p><h3 id="5-separate-the-core-from-external-world"><a href="#5-separate-the-core-from-external-world" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>5. Separate the core from external world</h3><p>Hexagonal Architecture, Onion Architecture, Ports &amp; Adapters Architecture, Clean Architecture, The Functional Core and Imperative Shell - you name it.</p><p>I firmly believe that all mentioned constitute the same principle - isolate your logic from effects.</p><p>On the bigger level we can think of architecture, but in the smaller scale you can think of a simple class or a function.</p><p>Yes, it might be related to &quot;Single Responsibility Principle&quot;, because it is all about responsibilities assignment.</p><p>To achieve such thinking, I like to visualize how people would collaborate within an <a href="https://talesfrom.dev/blog/organization-driven-design">organization</a>.</p><p>Then it becomes clear who knows what should be the decision and who knows how to react upon such information.</p><h3 id="6-do-not-start-with-the-persistence---three-aspects-of-modeling"><a href="#6-do-not-start-with-the-persistence---three-aspects-of-modeling" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>6. Do not start with the persistence - three aspects of modeling</h3><p>Again, heard about it in <a href="https://legacyfighter.pl/">Legacy Fighter</a> and <a href="https://bettersoftwaredesign.pl/">Better Software Design podcast</a>.</p><p>Originally, it is presented in the book <a href="https://www.amazon.com/Rethinking-Systems-Analysis-General-Thinking-ebook/dp/B0054DW3KS">Rethinking Systems Analysis and General Thinking</a> by Gerald Weinberg.</p><p>I am talking about so-called three aspects of modeling:</p><ul><li>Being</li><li>Behaving</li><li>Becoming</li></ul><p>Each of those aspects is related to a specific set of questions that might be used to bring deeper undestanding and clarity.</p><p>Whereas we typically start thinking about &quot;Being&quot; aspect - the structure, the data, the properties, it might be beneficial to find proper usages, behaviors and responsiblities.</p><p>Then looking for a specific set of details, that are required to satisfy such operations, completes the entire design.</p><p>This approach totally shifts one&#x27;s mind for modeling - from data-first (producing bag of properties) to behavior-first (promoting collaborators with proper responsibilities).</p><h3 id="7-the-ying-yang-of-software-engineering"><a href="#7-the-ying-yang-of-software-engineering" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>7. The Ying-Yang of Software Engineering</h3><p>Cohesion and coupling.</p><p>Coupling and cohesion.</p><p>There were a lot of tweetscussions regarding this pair recently.</p><p>Again, they are applicable to variety of problems, levels nad environments.</p><p>Either looking at the boundaries of your services or designing a proper structure of React components - consciously or subsconsciously we make a decisions about amount of coupling and how cohesive our constructs will be.</p><p>At the moment of writing, I think that both of them give birth to responsibilities assignments, contextual thinking and many more of the patterns that were discovered/invtented during the history of Software Engineering.</p><h3 id="never-ending-story"><a href="#never-ending-story" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Never ending story</h3><p>I think I could mention more books, approaches and observations, but I hope you see the point.</p><p>There are topics and areas, while being technology agnostic, open a new world of understanding and self-development.</p><p>We don&#x27;t need to foolishly pursue never ending stream of new shiny things, because there are stable concepts, tools and fundamentals we can bet on.</p><p>I know that it is not a &quot;complete&quot; list, but still it brings the conclusion that it makes sense to revisit the basics, because they are the most difficult part of our job.</p>]]></content:encoded>
    <pubDate>Tue, 04 Oct 2022 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>programming</category><category>paradigms</category><category>domain-driven design</category><category>problem-solving</category><category>language</category><category>learning</category><category>principles</category><category>fundamentals</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/the-value-of-value-objects</guid>
    <title>The value of Value Objects</title>
    <link>https://talesfrom.dev/blog/the-value-of-value-objects</link>
    <description>Is it only about the primitive obsession?</description>
    <content:encoded><![CDATA[<h3 id="value"><a href="#value" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Value?</h3><p>When we face a need to pick a new tool, library or framework, we evaluate it, in the most cases, using software technical perspective. We are technical people, aren&#x27;t we?</p><p>Is it fast?</p><p>Is it boilerplate-free?</p><p>Does it reduce time from the idea to production?</p><p>The same is with Value Objects, a tactical DDD &quot;pattern&quot;. Typically, we use &quot;immutability&quot; and &quot;identity-less&quot; arguments.</p><p>Immutability gives safer, clearer reasoning.</p><p>Identity-less gives comparison advantages.</p><p>But in my opinion, the true value of Value Objects lies somewhere else. I briefly mentioned in already in <a href="https://talesfrom.dev/blog/modeling-value-objects-in-typescript">Modeling Value Objects in TypeScript</a> post.</p><p>Still, I think it&#x27;s worth emphasizing this impressive, valuable perspective.</p><h3 id="can-you-add-floor-numbers"><a href="#can-you-add-floor-numbers" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Can you add floor numbers?</h3><p>One of the well-known properties of Value Objects is taming complexity of <a href="https://refactoring.guru/pl/smells/primitive-obsession">Primitive Obsession</a>.</p><p>Just as a reminder, this obsession is oriented toward treating, so-called &quot;primitives&quot;, as <strong>something more than they actually represent</strong>.</p><p>Imagine that we are in the elevator and we want to go to the third floor. Being &quot;noun&quot;-trained software engineer, we spot &quot;third floor&quot;.</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">Primitive obsession</div><div class="pb-2 px-3"><div class="break-words"><p>Primitive obsession is about treating <code>int</code>s, <code>string</code>s, <code>bool</code>s as something more than they actually represent.</p></div></div></div><p>&quot;Third&quot; means number so it&#x27;s highly probable we would represent it by <code>int</code>-like type (e.g. <code>number</code> in TypeScript). Because it&#x27;s a number, right?</p><p>What can we do with <code>int</code>? For example, we can add two <code>int</code>s or we can multiply them. They are subjects of some operations, behavior.</p><p>Can we add floor numbers? Third floor plus fifth floor gives eighth floor, isn&#x27;t it?</p><p>No, of course not. It is silly. But with <code>int</code> representation, it is possible.</p><h3 id="the-king-of-all-primitives"><a href="#the-king-of-all-primitives" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The King of All Primitives</h3><p>Do you know who is it? Beloved, dreaded, unmerciful <code>string</code>. The type that has vast amount of capacity.</p><p>It can represent names, addresses, e-mails, bank account numbers, money, age, serial numbers, phone numbers, words, and so on, and on.</p><p>There are certain behaviors that are related to <code>string</code> - for instance getting a substring.</p><p>Can we take a substring of, for instance, e-mail? No. We can look for <em>domain</em>.</p><p>It&#x27;s a different language. Another level of reasoning.</p><p>I really like a thought exercise - asking myself, each time I see <code>string</code>, either required by a method, function or as a variable - &quot;is it any string?&quot;</p><p>There&#x27;s one meme, I believe that <a href="https://twitter.com/jusrin00">Justin</a> was the author of it, and it expresses exactly what is the primitive obsession:</p><div class="flex flex-col justify-center items-center"><img class="m-0" src="https://talesfrom.dev/static/images/types-are-lie.jpg"/></div><p>For those not knowing this notation, <code>String -&gt; String -&gt; String -&gt; String</code>, means this is a function accepting a three arguments of type <code>String</code> and returning type <code>String</code>.</p><p>What does the <code>String</code> mean in this context?</p><p>Age?</p><p>Email?</p><p>Your bank account number?</p><h3 id="in-the-pursuit-of-meaning"><a href="#in-the-pursuit-of-meaning" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>In the pursuit of meaning</h3><p>The biggest value of Value Objects is that they build the language of your problem domain, giving the meaning to primitives.</p><p>They elevate the code into higher levels of reasoning, humbly taking away the details (isn&#x27;t it called <em>abstraction</em>?).</p><p>They open the world of thinking about concepts, instead of primitives, by making them &quot;materialized&quot; in front of our eyes.</p><div class="flex flex-col justify-center items-center"><img class="m-0" src="https://talesfrom.dev/static/images/invisible-value-objects.png" style="width:80%;height:80%"/></div><p>Words have meaning and with the meaning behavior and rules come.</p><p>Even though we have <code>string</code>s, <code>int</code>s, <code>bool</code>s - the concepts are there. If not in the code, then in the writer&#x27;s/reader&#x27;s head.</p><p>It is the programmer who keeps running the entire simulation that makes primitive types <strong>representing</strong> underlying concepts.</p><p>Then (poor) reader needs to understand the rules, &quot;the physics&quot; of the simulation, so that it can be safely run in the mind.</p><div class="flex flex-col justify-center items-center"><img class="m-0" src="https://talesfrom.dev/static/images/visible-value-objects.png" style="width:80%;height:80%"/></div><p>Creating a concept, out of the code, put constraints on thinking.</p><p>In DDD, we think a lot of boundaries. Value Objects do the same - they set up boundaries, in which a certain behaviors and rules are applicable.</p><p>For example, we are no longer working with e-mail concept implicitly, constantly transferring the constraints from our minds to the code.</p><p>We materialize the concept in the code, deploying the model from the head. And now we don&#x27;t need to continouosly simulate the rules and behavior. Then we can ask our friends to help us: compiler, runtime and specifications/verifications (what&#x27;s the difference? Please check <a href="https://talesfrom.dev/blog/the-ambiguity-of-tdd">&quot;The ambiguity&quot; of TDD</a>)</p><h3 id="contraints-liberate"><a href="#contraints-liberate" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Contraints liberate</h3><p>What if we &quot;invert&quot; the primitive obsession? What would we get?</p><p>Is it an obsession of concepts? Concepts obsession?</p><p>One of the strengths of DDD approach is putting enormous attention on the language, hence Value Objects are something more than what tactical patterns show.</p><p>They are effective weapon against the complexity, complexity of reasoning.</p><p>Next time, when you spot a string, ask yourself</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>Is it any <code>string</code>?</p></div></div></div>]]></content:encoded>
    <pubDate>Mon, 12 Sep 2022 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>programming</category><category>paradigms</category><category>domain-driven design</category><category>problem-solving</category><category>language</category><category>learning</category><category>encapsulation</category><category>value objects</category><category>code</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/feature-toggling-as-a-design-tool</guid>
    <title>Feature toggling as a design tool?</title>
    <link>https://talesfrom.dev/blog/feature-toggling-as-a-design-tool</link>
    <description>What are the properties of hideability?</description>
    <content:encoded><![CDATA[<div class="bg-slate-600 rounded-xl "><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Attention!</span></div><div class="pb-2 px-3"><div class="break-words"><p>Prepare for blasphemy and heresis!</p></div></div></div><h3 id="a-tale-from-dev-life"><a href="#a-tale-from-dev-life" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>A tale from dev life</h3><p>Not so long time ago, I was implementing conceptually simple, but integration-wise challenging piece of functionality.</p><p>It was technical capability, cross-cutting concern one, meaning that it might have had big impact on some initialization code for each module.</p><p>But back to the point.</p><p>I was happily developing it locally, everything was working fine according to the verification done by manual tests (why &quot;verification&quot;? Please check <a href="https://talesfrom.dev/blog/the-ambiguity-of-tdd">The &quot;ambiguity&quot; of TDD</a> blog post).</p><p>In a sense it looked promising, so the next step was actually to verify the functionality in the dev environment.</p><p>It was pretty calm, stable time of this component so no need to worry - PR merged, got deployed to dev environment.</p><h3 id="how-to-get-free-stress-points"><a href="#how-to-get-free-stress-points" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>How to get free stress points</h3><p>Ooops, it wasn&#x27;t working there. Unexpected (or rather unnoticed) issue of <code>Newtonsoft.Json</code>&#x27;s multiple versions appeared.</p><p>&quot;Soon to be fixed&quot;, I thought.</p><p>I continued working, thinking how to beat that well-known problem.</p><p>Suddenly, a support ticket came - one of the customers started facing some issues with a new functionality released some time ago. Initially, it looked like a unexplored case.</p><p>&quot;Soon to be fixed&quot;, I thought again, but now with different subject in mind.</p><p>But, but - wait?! My unfinished, broken functionality is merged, meaning that according to our process, it would be released too.</p><p>A glitch in the Matrix. Impossible state became possible?</p><h3 id="is-a-broken-hidden-code-a-bug-or-not"><a href="#is-a-broken-hidden-code-a-bug-or-not" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Is a broken, hidden code a bug or not?</h3><p>Quite high prio investigation with possible fix to be delivered as soon as possible - that puts some frame around thinking and constrains work in a surprisingly creative way.</p><p>There were multiple models for fixing it (a solution to the given problem): reverting my work, working directly with <code>master</code> branch, creating a copy of existing branch, etc.</p><p>One of the options was to hide broken code. Literally, make it unavailable.</p><div class="flex flex-col justify-center items-center"><img class="m-0" src="https://talesfrom.dev/static/images/hidden-bug.jpg"/></div><p>Best of both worlds: being able to continue working on new functionality and fixing a bug. Isn&#x27;t that neat?</p><p>You probably recognize this as a feature toggle, when one, in the runtime, can change the behavior of the system. But, is it that easy?</p><h3 id="is-my-design-ready-to-be-toggled"><a href="#is-my-design-ready-to-be-toggled" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Is my design ready to be toggled?</h3><p>Turned out that I had multiple places to touch so that the broken functionality gets entirely hidden. Can you feel it? It is a bit smelly.</p><p>I was missing a proper abstraction (I can hear you - where&#x27;s my specification? &quot;With TDD you won&#x27;t reach such state!&quot;, but that&#x27;s another tale).</p><p>In the reasonable amount of time the proper abstraction was provided and suddenly I had only two guys (why &quot;guys&quot;? Please check <a href="https://talesfrom.dev/blog/organization-driven-design">Organization-Driven Design</a>), responsible for acting upon a toggling this feature. Now we are talking!</p><p>Soon I fixed the issue, it got delivered and, almost like a state machine, I returned to the initial state, working on the new functionality.</p><p>Could this short, but still, stressful situation, be mitigated? Of course!</p><p>Possibly, there were various measures I could have taken into account, but actually <strong>NOT</strong> designing it in the proper way highlighted some interesting properties of this codebase (and other, similar ones?).</p><p>As Kevlin Henney said in one of his talks (I believe it was during <a href="https://www.youtube.com/watch?v=Lc13xKEJZTc">#FAIL</a>):</p><blockquote><p>(...) we are forced to learn how things are working when they fail.</p></blockquote><h3 id="how-easy-it-is-to-hide-your-code"><a href="#how-easy-it-is-to-hide-your-code" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>How easy it is to hide your code?</h3><p>What would you do in a similar situation? Would it be easy for you to apply the similar approach?</p><p>I know, typically we don&#x27;t need to make some parts of our codebase hideable, because they are either too small or it would require additional effort to make them gaining this trait (e.g. no feature toggling infrastructure, convincing others, etc.).</p><p>There are certain actions that probably won&#x27;t benefit from making them hideable, e.g. adding a property/field to a DTO, working on new method in a class.</p><p>My introductory, short tale revealed some weaknesses of the codebases that are difficult for making them &quot;feature toggleable&quot;. In the mentioned case, it was a lack of proper abstraction.</p><p>What does it mean that a feature is &quot;difficult to hide&quot;?</p><p>What properties are missing so that, when &quot;added&quot;, code becomes easy to be hideable?</p><h3 id="hideability-opens-next-level"><a href="#hideability-opens-next-level" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Hideability&quot; opens next level</h3><p>A piece of functionality, easy to be hidden, brings another interesting perspective. When we can easily hide it, we should be able to easily replace it, isn&#x27;t it?</p><p>The first thing that comes to my mind is versionability, meaning that we are able to use either one version or another, for respective capability.</p><p>We know how to version our APIs. There are various stategies for achieving so. Consumers are not interested how we are arriving at this solution, they need to know the contract.</p><p>What happens under the hood? Is our code really able to be versionable?</p><h3 id="example-time-say-hi-to-usersbackend"><a href="#example-time-say-hi-to-usersbackend" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Example time: say hi to <code>Users.Backend</code>!</h3><p>Let&#x27;s imagine we have a very simple backend that gets more and more attention from various customers around the globe.</p><div class="flex flex-col justify-center items-center"><img class="m-0" src="https://talesfrom.dev/static/images/api-overview.png"/></div><p>I bet you know this style of architecture quite well. I would even say it&#x27;s quite common.</p><p>Going to the details of each layer, one can see:</p><div class="flex flex-col justify-center items-center"><img class="m-0" src="https://talesfrom.dev/static/images/api-details.png"/></div><p>Impressive, isn&#x27;t it? But again, back to the point.</p><p>Imagine that we were asked to introduce a novel change for assigning groups to the users.</p><p>As this is our core and critical capability, we need to make sure it&#x27;s always stable, always working.</p><p>Let&#x27;s highlight everything related to <code>Group</code> concept:</p><div class="flex flex-col justify-center items-center"><img class="m-0" src="https://talesfrom.dev/static/images/api-versioning.png"/></div><h3 id="the-birth-of-versioning"><a href="#the-birth-of-versioning" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The birth of versioning</h3><p>That seems easy. We should use a standard way to version the API. Our consumers will get a chance to decide either to use old way or a novel way.</p><p>What happens under the hood though?</p><p>We simply add a next controller action (at least in ASP.NET Core world) with a proper version number.</p><p>We could also introduce a separation between <code>V1</code> and <code>V2</code> controllers to retain even more granular control.</p><p>Let&#x27;s add another constraint.</p><p>Imagine that this change (because of being novel) requires touching every other related collaborator: <code>GroupsService</code>, <code>GroupsRepository</code>, <code>Group</code> (and maybe something from <code>Users.Backend.Common</code>). By touching I mean either extending something which is already working or modifying it in some sense.</p><p>It starts to be a bit shaky. Playing with the core functionality might sound a bit scary.</p><p>There are abundance of options how to approach such scenario, but it looks a bit smelly again - even though we are &quot;doing&quot; versioning of the &quot;API&quot;, seems like it&#x27;s just versioning the surface, because our current architecture does not provide a way of easily versioning everything.</p><p>Do we have a feature toggle here? In a sense, yes. The decision is on the consumer side which &quot;feature&quot; should be used. Does this design supports easy &quot;versionability&quot;?</p><p>It depends on the range of change, but because we constrainted ourselves with risky work, affecting every single collaborator, seems like we are in a trouble.</p><h3 id="what-is-missing"><a href="#what-is-missing" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What is missing?</h3><p>This is just a toy example and I intentionally used a typical N-tier architecture, in which every layer contains related components: controllers are together, services too, etc.</p><p>But it seems that this example is missing similar properties as my introductory one. Distributed, hard to manage in terms of complete hideability/versionability.</p><p>There is no easy way to make entire functionality (by entire I mean all related components) truly versionable, except going to an every single guy and doing some work there to ensure versioning.</p><p>Traits like hideability, versionability, provided by feature toggles, might highlight weak design, inability to have safe, risky-limiting changes.</p><h3 id="feature-toggle-as-a-design-tool"><a href="#feature-toggle-as-a-design-tool" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Feature toggle as a design tool</h3><p>A need for toggling some functionality on and off might suggest keeping things together if they fulfill a given capability.</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><ul>
<li>How easy it would be to hide/version entire feature? (&quot;entire&quot; meaning all code related to this feature)</li>
<li>How easy it would be to hide/version a single class/type/component/function/module?</li>
</ul></div></div></div><p>&quot;Keeping related things together&quot; might be also known as cohesion. Then, cohesive functionality seem to have hideability and versionability by default.</p><p>A conclusion might be that a design/code that is easy to be changed, should be easy to be hidden or versioned.</p><p>How can we check if our design adhears to such conclusion?</p><h3 id="the-fairy-of-immutable-code"><a href="#the-fairy-of-immutable-code" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The fairy of immutable code</h3><p>Let&#x27;s have a small mental experiment.</p><p>Imagine that the evil fairy came and turned all of our code into an immutable code. You know what immutability is, right?</p><p>Existing immutable code cannot be modified. But actually there&#x27;s a way to solve it - the only actions you can do is:</p><ul><li>copying a file/an entire directory</li><li>deleting a file/an entire directory</li><li>modyfing a new file</li><li>renaming a file/an entire directory</li></ul><p>In other words, one cannot go to the file, add a single &quot;if&quot; and check it in.</p><p>Instead of that, one would need to:</p><ol><li>Copy entire file and name it properly, e.g. with <code>*New</code> suffix.</li><li>Add this single &quot;if&quot; in the new file.</li><li>Delete the &quot;old&quot; file.</li><li>Rename the new file by removing <code>*New</code> suffix.</li></ol><p>Phew, that&#x27;s exhaustive, isn&#x27;t it?</p><p>But let&#x27;s go back to the second point of such sequence, before deleting the &quot;old&quot; file. At some point in time, in our project, there are <strong>two</strong> versions of the same file (hence namespace/class/function/type, you choose) available.</p><p>Isn&#x27;t it almost like a versioning? If we ensured unique naming of classes/functions/types/modules/namespaces/packages then we would be able to toggle between them (this would require another change on the higher level, somewhere else, of course!).</p><p>This teeny tiny example involved single &quot;if&quot;, but what if there will be more classes/functions/types (meaning, files) required to be extended/altered to be accepted as a solution?</p><p>I can imagine traversing entire project, all those directories and then applying actions only available on immutable code.</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>Provided that your code was turned to immutable code,</p>
<p>how easy it would be to introduce a change in our code?</p></div></div></div><h3 id="a-litmus-test-for-high-cohesion"><a href="#a-litmus-test-for-high-cohesion" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>A litmus test for high cohesion</h3><p>Thinking in terms of immutable code, it seems to me that capabilities provided by set of highly cohesive parts should be easily versionable/replaceable/hideable just by copying entire directory and ensuring uniqueness of its subparts (files/classes/functions/namespaces/modules).</p><p>I believe that &quot;vertical slices&quot; are another name for highly cohesive subparts, supporting versionability/replaceability/removability.</p><p>If the code from <a href="example-time-say-hi-to-users-backend">Example time: say hi to <code>Users.Backend</code>!</a> section became &quot;immutable&quot;, there will be multiple rounds of &quot;copy-modify-delete&quot; steps.</p><p>With proper vertical structuring, we should be able to copy entire directory, do proper extensions/modifications and ensure we are able to either delete &quot;old&quot; or provide a way to toggle different versions.</p><p>A very cheap verification of having highly cohesive code would be to delete a single file, an entire directory (or entire project, in .NET world).</p><p>Number of errors and their nature should suggest and highlight weakpoints.</p><ul><li>Single class got affected?</li><li>Multiple classes in a single directory, in the same project?</li><li>Multiple classes across multiple directories, still in the same project?</li><li>Multiple classes across multiple directories, across multiple projects?</li></ul><p>Answer to the first question might indicate high cohesion of a given subsystem. Going further might underline losing the cohesion points (there&#x27;s no such thing, I made this up, but I believe you got my point).</p><h3 id="sometimes-if-is-just-enough"><a href="#sometimes-if-is-just-enough" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Sometimes &quot;if&quot; is just enough</h3><p>Immutable code might sound a bit scary. The black, fairy magic looks dreadfully and would make our day to day job a nightmare.</p><p>With high probability, if you do not change <strong>almost everything</strong> related to a given capability you are working with, just an &quot;if&quot; will be enough to version your code or to hide it.</p><p>&quot;Teaching&quot; some higher level components/classes/modules how to decide which version to pick (or whether something should be hidden) should be simply doable. Pragmatism is the key here.</p><p>We could, of course, apply advanced strategies, e.g. by using strategy design pattern (yes, pun intended), but we won&#x27;t get away from &quot;if&quot; statement/expression. At some point, you would need to place it somewhere.</p><p>Branching with &quot;if&quot; (or with pattern matching, if your language supports it), in the code, can open a door of hideability or versionability too.</p><h3 id="what-about-branching-in-git"><a href="#what-about-branching-in-git" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What about branching in git?</h3><p>I am glad that you asked (in fact I asked that, but let&#x27;s pretend you did so).</p><p>With git branching you can have versioning, for free, not doing some magic stuff with immutable code or other tricks.</p><p>And that&#x27;s true. However, git branches do not compose. You cannot have your lovely API running two branches of the same codebase on the single instance.</p><p>With branching done in the code (because this is in fact what versionability means - branching in the code), you can have it.</p><p>We cannot escape branching, but the question is where we do it. In the code you have massive amount of control. But there are various caveats.</p><p>Your code needs to be modular, cohesive and properly coupled. Without those properties it might be really challenging to get, e.g. proper versionability.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>We cannot escape branching, but the question is where we do it.</p></div></div></div><p>Having that in mind, it&#x27;s easier to version things using git branches.</p><p>But what you are losing is feedback received from trying to obtain versionability/removability/hideability/replaceability traits.</p><p>Feedback about your design.</p><h3 id="feature-branches"><a href="#feature-branches" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Feature branches</h3><p>We are used to feature branches so that they can get reviewed and quality assurred.</p><p>But they delay feedback. Not only in terms of the integration, but in terms of the design too.</p><p>The assumption is they are short-lived, but I believe that we all experienced Pull-Requests, touching 50+ files, spreading across multiple directories, multiple projects (in .NET world).</p><p>They were approved with some low-impact improvements, getting &quot;LGTM&quot; eventually.</p><p>Let&#x27;s come back to one of questions we posed in this article:</p><blockquote><p>How easy it would be to hide/version entire feature (entire = everything related to it)?</p></blockquote><p>In this particular context, hiding entire feature, especially when we think of our code in terms of immutable code, seems like a drudgery full of torment.</p><p>Imagine going to every single place of those 50+ files and doing copy, modify, rename, delete. Torture.</p><h3 id="wait-wont-we-duplicate-the-code"><a href="#wait-wont-we-duplicate-the-code" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Wait, won&#x27;t we duplicate the code?</h3><p>Oh yes, we will!</p><p>I mean kind of. We will have <strong>TWO</strong> versions of the same functionality, <strong>available at the same time</strong>, but only some parts will be duplicated. But is it actually bad?</p><p>As with everything, there are trade-offs. You gain vast amount of control (e.g. you can apply fixes independently), but it requires discipline.</p><p>What discipline?</p><p>Again, keeping your code modular, cohesive and well-thought requires time, analysis, proper specification through tests, proper verification through tests (What I am talking about? See <a href="https://talesfrom.dev/blog/the-ambiguity-of-tdd">The &quot;ambiguity&quot; of TDD</a>).</p><p>Such implicit branching via feature toggling demands a totally different mindset. Are you ready to use it?</p><p>From the first seconds of a new code, we would need to make sure everything is ready for the evil fairy of immutable code.</p><p>Below is visual comparison of different ways of doing branching.</p><div class="flex flex-col justify-center items-center"><img class="m-0" src="https://talesfrom.dev/static/images/branching.png" style="width:60%;height:60%"/><span class="text-lg mt-0.5">With implicit branching, a higher level collaborator decides whether to use <code>AThing.cs</code> or <code>AThingV2.cs</code></span></div><p>With feature toggling (implicit branching done in the code), you choose when it is an appropriate moment for deleting the &quot;old&quot; code.</p><p>No rush, let is sink. You have control.</p><p>You can leave two versions as long as it is needed.</p><p>You can easily revert back to the &quot;old&quot; version. Apply fixes to it.</p><p>Experiment. Play.</p><p>Suddenly, branching via feature toggling opened another door - being able to use <a href="https://trunkbaseddevelopment.com/">Trunk Based Bevelopment</a>.</p><h3 id="there-is-no-free-lunch"><a href="#there-is-no-free-lunch" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>There is no free lunch.</h3><p>To gain this kind of control and shortening the feedback loop, we need to make our code ready for such approach.</p><p>All the software design heuristics and rules help achieving so, but we need to apply from the first seconds of our work.</p><p>In <a href="https://vimeo.com/108441214">&quot;The art of destroying software&quot;</a>, Greg Young recommends writing small, modular code that makes itself easy to be deleted and replaced.</p><p>With such mindset, we can &quot;hack and break things&quot;, because we are able to cancel our experiment.</p><p>&quot;Just coding&quot; won&#x27;t give us such properties. All well-recognized traits like Encapsulation, Modularity, etc., increase the probability of achieving such state - making our code versionable/hideable/replaceable.</p><h3 id="changing-through-copying"><a href="#changing-through-copying" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Changing through copying</h3><p>Recently, I had a pleasure to perform a refactoring of some other component.</p><p>One of the bringing value goals was achieving better maintainability and higher quality.</p><p>Such vague and abstract words were supposed to be materialized through making it more testable, by pulling all dependencies to the most outer layer.</p><p>Simple as that.</p><p>In fact, we didn&#x27;t start with feature toggling, but thanks to having isolated, pretty independent piece of code, we made it versionable by <strong>copying</strong> entire project.</p><p>Duplication? Yes.</p><p>Control? YES!</p><p>Fast Feedback? Yes.</p><p>Discipline? Yes!</p><p>Duplication isn&#x27;t bad, as long as you can delete the duplicated parts at any time, without being stressed that things will be broken.</p><div class="flex flex-col justify-center items-center"><img class="m-0" src="https://talesfrom.dev/static/images/toggling-versioning.png"/><span class="text-lg">The &quot;old&quot; code gets deleted, the &quot;new&quot; code becomes the only version available.</span></div><h3 id="are-you-ready-to-delete-your-code"><a href="#are-you-ready-to-delete-your-code" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Are you ready to delete your code?</h3><p>Have fun - go and try deleting parts of your codebase: entire directories, single files, single classes/functions and observe what happens.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Duplication isn&#x27;t bad as long as you can delete the duplicated parts at any time, without being stressed that things will be broken.</p></div></div></div><p>How many other parts of your system got affected?</p><p>This is really instant feedback. I don&#x27;t think you will get quicker than that.</p><p>There are other approaches and tools opening a possibility to analyze your design, e.g. <a href="https://www.amazon.com/Your-Code-Crime-Scene-Bottlenecks/dp/1680500384">Your Code as a Crime Scene</a> or <a href="https://www.amazon.com/Software-Design-X-Rays-Technical-Behavioral/dp/1680502727">Software Design X-Rays</a>, but they require a bit more effort.</p><p>Still, they might be great next steps, after you can spot a problem with your code either by thinking how to provide full versionability or just by deleting some parts of the code.</p><h3 id="start-with-immutable-code-constraint"><a href="#start-with-immutable-code-constraint" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Start with immutable code constraint</h3><p>Next time, do an exercise.</p><p>Use the fairy of immutable code approach and think that you <strong>cannot modify</strong> existing code.</p><p>Introduce feature toggling as the first step and see how much effort is required to achieve complete versionability (complete = all code related to a given functionality).</p><p>Is it itchy?</p><p>Is it painful?</p><p>Congratulations, you found things to improve!</p><h3 id="same-sht-different-name"><a href="#same-sht-different-name" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Same sh*t, different name</h3><p>Did I invent something new? Nope, I am again standing on the shoulders of giants.</p><p>Modularity, encapsulation, right abstraction, high cohesion and low coupling (I like to call it &quot;proper coupling&quot;) aren&#x27;t new.</p><p>But I don&#x27;t think there is a faster way to get feedback about your design. By deleting some parts of your code you don&#x27;t need to write anything new, like tests (either verification or specification ones). It can be a simple and cheap litmus test to understand where are you in terms of modularity/cohesion spectrum.</p><p>It takes time to reflect on the information acquired, of course.</p><h3 id="be-your-own-hero"><a href="#be-your-own-hero" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Be your own hero</h3><p>Should you use &quot;immutable code&quot; approach for every development work you do? Yes, it is a dogma. You need to comply.</p><p>Should you always start with providing &quot;feature toggle&quot;, even for a small feature? Yes my zealot.</p><p>Of course, I am joking. Do whatever is working for you and apply any tool or approach with the doubtful mindset.</p><p>I think a simple heuristic might be helpful:</p><ul><li><p>Are you introducing a small change, that isn&#x27;t risky? Just go with the &quot;feature branching&quot; (git) approach by just changing the existing code.</p></li><li><p>Do you want to integrate quickly and get feedback sooner? Try applying branching in the code with &quot;if&quot;, either by hiding new (possibly broken and unfinished) functionality or choosing between &quot;old&quot; and &quot;next&quot; version.</p></li><li><p>Are you working with core, critical path of your system? Use &quot;immutable code&quot; approach and copy all code related to entire feature, introduce change there.</p><p>-&gt; You can&#x27;t get it so easily? You discovered something about your design. Use this insight. Try to move towards complete versionability, but assess how much effort is required.</p></li><li><p>Doing some new, cool stuff? Start with providing feature toggle that will enable versioning entire functionality. This is a decent intro to high cohesion, proper coupling.</p></li></ul><p>Please remember - take what is useful, discard what doesn&#x27;t bring any value.</p><p>Starting with &quot;feature toggle&quot;-first mindset might call for the discipline, but it increases the probability of getting the reward, the holy grail of software design - high cohesion, proper coupling.</p>]]></content:encoded>
    <pubDate>Sun, 04 Sep 2022 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>programming</category><category>paradigms</category><category>tdd</category><category>ddd</category><category>test-driven development</category><category>learning</category><category>design</category><category>feature toggling</category><category>coupling</category><category>cohesion</category><category>hideability</category><category>modularity</category><category>models</category><category>architecture</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/the-ambiguity-of-tdd</guid>
    <title>&quot;The ambiguity&quot; of TDD</title>
    <link>https://talesfrom.dev/blog/the-ambiguity-of-tdd</link>
    <description>Why it really matters how you think of your tests?</description>
    <content:encoded><![CDATA[<h3 id="what-the-hell-are-you-talking-about"><a href="#what-the-hell-are-you-talking-about" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What the hell are you talking about?</h3><p>I was really thinking about giving this post the following title: &quot;TDD consultants hate him! Learn this simple trick to become TDD champion!&quot;, because I love permanent confusion (thanks <a href="https://en.wikipedia.org/wiki/Koan">Zen Koans</a>!). The other perspective is well-known, cliche clickbait which we all hate. But! To the point.</p><p>Recently, there were a lot of discussions in the fellow software craftsmanship community about TDD and testing in general. I really liked all the perspectives presented, both from the warlords of industry standards and from folks who are starting their journey.</p><p>There are various brilliant &quot;tales&quot; (I mean - threads) about TDD, like <a href="https://buttondown.email/hillelwayne/archive/i-have-complicated-feelings-about-tdd-8403/">this</a>, <a href="https://twitter.com/GeePawHill/status/1556825728326553600">that</a> or <a href="https://twitter.com/allenholub/status/1560743039437393921">that</a>, conducted by the community titans. You can read and absorb their experiences, distilled into the genious-like conclusions.</p><p>As you, dear reader, probably noticed from previous posts, I like to play with the language, explore metaphors and think of how one can think of X (isn&#x27;t it called metathinking? 🤔). Hence I would like to explore &quot;the ambiguity&quot; of TDD.</p><p>What &quot;ambiguity&quot; am I referring to? Am I attacking the golden, precious practice for creating software?</p><p>Let&#x27;s see!</p><h3 id="what-is-the-essence-of-domain-driven-design"><a href="#what-is-the-essence-of-domain-driven-design" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What is the essence of <em>Domain-Driven Design</em>?</h3><p>What DDD practice teaches us, is the importance of the communication and collaboration between developers and domain experts.</p><p>Both those activites are based on the language. Not every language, but <strong>the right</strong> language. What does it mean <em>right</em> in this context?</p><p>I got dazzled by the tactical building blocks of DDD. The essence lives somewhere else and is the root of the entire practice - which starts directly in the language we use.</p><p>The language has its meaning, and the meaning lives in the particular context, that is driven by a set of rules.</p><p>It is enormously relevant to be precise in your words whether you express something in the code, when you name your resources in one of the cloud vendors or, especially, when you exchange thoughts with other human being by having a discussion.</p><p>We are always influenced by The King of all Kings, The Context and its knights - different perspectives.</p><p>An example? Let&#x27;s take a concept of the &quot;car&quot;. Depending on the perspective, it can be used or it can be a subject of various activites. What are exemplary contexts?</p><ul><li>repairing</li><li>selling</li><li>transfering (logistics)</li><li>marketing/branding</li><li>etc.</li></ul><p>One word, many meanings.</p><h3 id="how-does-it-relate-to-tdd"><a href="#how-does-it-relate-to-tdd" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>How does it relate to TDD?!</h3><p>We talked about the language used so let&#x27;s work on some definitions.</p><p>The definition from <a href="https://en.wikipedia.org/wiki/Test-driven_development">Wiki</a>:</p><blockquote><p>Test-driven development (TDD) is a software development process relying on software requirements being converted to <strong>test</strong> cases before software is fully developed</p></blockquote><p>Another definition taken from an arbitrary <a href="https://www.boldare.com/blog/test-driven-development-tdd-definition-benefits/">page</a>:</p><blockquote><p>Test-driven development (TDD for short) is a programming approach in which developers write production code in response to a <strong>test</strong> case; as opposed to the traditional process where code is written first, and relevant test cases are created later.</p></blockquote><p>Both given definitions, but also many others, put the word &quot;test&quot; in the central place. As if this was the most important part of the entire practice. Because it is, isn&#x27;t it?</p><h3 id="testing-units"><a href="#testing-units" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Testing units?</h3><p>Unit tests are the means for practicing TDD. The more consultants you ask, the more definitions of the unit you will get, but it is not the point I want to draw attention at.</p><p>No doubt that there are various patterns, heuristics and tips how to make unit tests effective, efficient, maintanable, readable (let&#x27;s take Kent Beck&#x27;s <a href="https://kentbeck.github.io/TestDesiderata/">&quot;Test Desiderata&quot;</a> as an example).</p><p>But what does the word <em>test</em> actually mean in this context?</p><h3 id="the-ambiguity"><a href="#the-ambiguity" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;The ambiguity&quot;</h3><p>I misunderstood TDD for a long time. Mostly because of &quot;the ambiguity&quot;.</p><p>It&#x27;s well-known &quot;anti-practice&quot; to write your <strong>tests cases</strong> after writing your code. You are losing the &quot;design&quot; trait of the tests.</p><p>On the other hand, everyone knows (doesn&#x27;t matter if it comes from practice or &quot;theory&quot;) that starting from the test cases helps your design. It means that writing your <strong>tests cases</strong> before writing your code helps your components to acquire desired properties like loose coupling, single responsibility, etc.</p><p>This means that in one context (when writing <strong>before</strong>) &quot;tests&quot; help achieving &quot;better design&quot;, and in another context (when writing <strong>after</strong>) &quot;tests&quot; don&#x27;t contribute to &quot;better design&quot;.</p><p>Are we really talking about the same <strong>tests</strong>?</p><p>I firmly believe this is the source point of confusion. We mixed up the domains, the problems spaces, attempted to be solved by tests. We mashed up the contexts!</p><h3 id="what-do-you-want-me-to-do"><a href="#what-do-you-want-me-to-do" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;What do you want me to do?&quot;</h3><p>Imagine you start with a blank tab in your favorite IDE. You stare at it and you think how to write your class, function or type - pick whatever you want.</p><p>Either you start from <em>tests</em> (I put the accent here to indicate that this word has a particular meaning in the context I would soon summon) or not, you <strong>specify</strong> how it needs to work. Implicitly it is done in your head, explicitly it might be done in the code, by expressing it using <strong>test</strong>.</p><p>In this particular context, our &quot;test&quot; friend is just a tool for automating <strong>the specification</strong> of what needs to be achieved.</p><p>So apparently, we used the word &quot;test&quot; in the context of the specifications. It is a mental shortcut to say that the test is the specification.</p><p>Could the specification be somewhere else?</p><p>In one of the previous <a href="blog/conversation-driven-design">posts</a>, I explored the metaphor of using conversation to facilitate the design activities. When we specify what our unit (whatever it is) should do, our test converses with us using colors:</p><div class="flex justify-center items-center flex-col"><span style="color:green">&quot;your code works according to the specification&quot;</span><p>OR</p><span style="color:red">&quot;your code does not work according to the specification&quot;</span></div><p>So, as our test is &quot;speaking&quot; to us, couldn&#x27;t we take one of our friends from the team, ask to sit next to us and test the piece of software we wrote every time we make a change? It will be tedious as hell, boring and patience-demanding activity, but he or she will give similar feedback: <span style="color:green">&quot;works&quot;</span> or <span style="color:red">&quot;doesn&#x27;t work&quot;</span>.</p><p>This brings us to the conclusion that our tests can run in the contexts of specification, meaning we arrive at the station &quot;Test-Driven Specification&quot;.</p><p>Thus, this is the biggest &quot;trick&quot; I would sell to myself from the past - when you write your &quot;tests&quot; before your code, you specify.</p><p>Contrary, monotonous, exhausitve practice of getting your colleague&#x27;s helphand would become &quot;Human-Driven Specification&quot;.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>When you write your &quot;tests&quot; before your code, you specify.</p></div></div></div><p>I am quite convinced that we need higher precision when we want to express something from this context. For example, instead of saying &quot;I am writing a test for this class A&quot; we should use &quot;I am writing a specification of this class A&quot;</p><h3 id="what-would-you-like-to-verify"><a href="#what-would-you-like-to-verify" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;What would you like to verify?&quot;</h3><p>Let&#x27;s bring a hypothetical situation from real-life.</p><p>You received a support ticket in one of the tools your company uses.</p><p>There&#x27;s a bug in production.</p><p>No doubt.</p><p>You got details how to reproduce it. Immediately you open application or Swagger API, you reproduce steps and boom - there&#x27;s inconsistency or exception thrown. Pick whatever you want.</p><p>So what we are actually doing? Are we specifying?</p><p>Reproducing this bug over and over manually is similar to &quot;Human-Driven Specification&quot;, although now you are not &quot;specifying&quot; what it should do. It&#x27;s more like a &quot;Human-Driven Verification&quot;, isn&#x27;t it?</p><p>Now we are in the context of <strong>verification</strong>. We could set up automated test to prove that particular part of the system <span style="color:green">&quot;works&quot;</span> or <span style="color:red">&quot;doesn&#x27;t work&quot;</span>. But this is different &quot;works&quot;/&quot;doesn&#x27;t work&quot; than ones from <a href="#what-do-you-want-me-to-do">&quot;What you want me to do?&quot;</a>.</p><p>Call this &quot;test&quot; a regression test or whatever - it&#x27;s intention is completely different than &quot;specification&quot;. It would live to verify or to prove whether results are the ones we expect.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>When you write your &quot;tests&quot; after your code, you verify.</p></div></div></div><p>Is it wrong that we wrote this test <strong>after</strong> we producted the code that makes money for your company? Nope, because the context is different. This test expresses the &quot;Test-Driven Verification&quot; perspective.</p><p>In his famous quote, Edsger W. Dijkstra states:</p><blockquote><p>“Program testing can be used to show the presence of bugs, but never to show their absence!”</p></blockquote><p>I think it fits very well into the context of <strong>verification</strong>, but not exactly to the context of <strong>specification</strong>.</p><h3 id="what-is-the-responsiblity-of-tdd"><a href="#what-is-the-responsiblity-of-tdd" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What is the responsiblity of TDD?</h3><p>I think that both contexts have their place in the development cycle. One doesn&#x27;t exist without its counterpart and together create something greater.</p><p>Almost as in the systems thinking &quot;mantra&quot;: &quot;a system is something more than its parts&quot;.</p><p><strong>Specification</strong> is oriented towards design, maintainability, loose coupling, evolvability - where subjects could be &quot;things&quot;, &quot;subsystems&quot; or &quot;components&quot;.</p><p><strong>Verification</strong> is oriented towards correctness, usefulness, value-bringing - where subjects could be &quot;users&quot;, &quot;customers&quot;.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>When you write your &quot;tests&quot; to prove the value it gives to end recipients, you verify too.</p></div></div></div><p>So actually, TDD, as the practice of writing &quot;tests&quot; <strong>before</strong> writing your code, is about <strong>specification</strong>. It facilitates &quot;good&quot; design, etc.</p><p>What about verification? Would it be actual responsibility of TDD?</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>Is <strong>verification</strong> a responsibility of TDD?</p></div></div></div><p>Thanks to the &quot;single responsiblity&quot; principle, we know that one shouldn&#x27;t put two responsiblities on the shoulders of a single &quot;guy&quot;.</p><h3 id="how-does-it-look-from-outside"><a href="#how-does-it-look-from-outside" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>How does it look from outside?</h3><p>Who is responsible for &quot;verification&quot;, if not TDD?</p><p>The closest asignee would be so-called &quot;Outside-In&quot; approach, in which we start from the &quot;most outer&quot; level, having in mind what results we expect to get when using this thingy.</p><p>Another thought is Behavior-Driven Development (BDD), concentrating on &quot;business&quot; value, the visible results of using the given system/component.</p><p>Combining those two &quot;responsiblities&quot;, we have a perfect mixture covering two contexts. <strong>Verification</strong> guy takes care of the business value and <strong>Specification</strong> fellow makes sure that the design is balanced in terms of all the good traits of software engineering practices. Almost like in <a href="https://talesfrom.dev/blog/organization-driven-design">Organization</a>, they are organizing each other to achieve the bigger goal.</p><p>I know that I am just scratching the surface of a huuuge topic, either when mentioning BDD or Outside-In approach, but I think the point is clear - TDD itself is just a &quot;side&quot; of a Ying-Yang process.</p><h3 id="ok-dude-what-now"><a href="#ok-dude-what-now" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Ok dude, what now?</h3><p>Am I expecting all professionals to stop using TDD acronym and start using &quot;Test-Driven Specification&quot;?</p><p>Would BDD become &quot;Test-Driven Verification&quot;?</p><p>Of course! I am expecting those things to happen. I would love to become an IT influencer, software engineering celebrity having zealots gathering around (acolytes aren&#x27;t bad, right?).</p><p>Ok, enough jokes. It helped (and still helps) challenging the way I think about the software, the patterns and methodologies.</p><p>This would be a single advice I would give to my &quot;younger&quot; self from the past, when starting the career. The fundamentals are the most difficult to grasp and I believe the understanding comes after a longer period of time.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Test-Driven Development is not about tests themselves.</p>
<p>It is either about <strong>verification</strong> or <strong>specification</strong> using <em>tests</em>.</p></div></div></div><p>Next time when you will be faced with a need to write a piece of code, ask yourself this question:</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>Am I testing to verify if it works correctly or to specify what it should do?</p></div></div></div><p>Have a great testing (whatever it means in your current context)!</p>]]></content:encoded>
    <pubDate>Mon, 22 Aug 2022 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>programming</category><category>paradigms</category><category>domain-driven design</category><category>tdd</category><category>ddd</category><category>test-driven development</category><category>language</category><category>learning</category><category>metaphors</category><category>models</category><category>architecture</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/organization-driven-design</guid>
    <title>&quot;Organization-Driven Design&quot;</title>
    <link>https://talesfrom.dev/blog/organization-driven-design</link>
    <description>Exploring a metaphor about how we can think of software components</description>
    <content:encoded><![CDATA[<h3 id="what-metaphor-am-i-talking-about"><a href="#what-metaphor-am-i-talking-about" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What metaphor am I talking about?</h3><p>Recently, I released my mind from rational leash which led to exploring how we could think of software design - I am talking about <a href="https://talesfrom.dev/blog/conversation-driven-design">Conversation-Driven Design</a> blog post.</p><p>The conclusion was as follows: we could utilize metaphor (or model) of people talking to each other in order to design interactions, responsibilty assignment and do the verification if it all makes sense. I finalized that blogpost with:</p><blockquote><p>I think it might get even more interesting when we would &quot;summon&quot; a group of such imaginary people and call them a &quot;company&quot; - how would they interact to achieve bigger goal like some of their domain capabilities?</p></blockquote><p>When using a proper mental model (as in this example - conversation as a model for software design), our language changes, we are capable of utilizing different concepts and terms.</p><p>Let&#x27;s explore the metaphor!</p><h3 id="objects-are-like-humans"><a href="#objects-are-like-humans" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Objects are like humans?</h3><p>Imagine we have two objects: A and B.</p><div class="flex justify-center items-center flex-col"><div><img class="max-h-[10rem]" src="https://talesfrom.dev/static/images/two-objects.png"/></div><div>A conversation</div></div><p>For the needs of this blog post, we already assumed that we can talk to objects (weird, isn&#x27;t it?) and objects can talk to each other, almost as if they have a conversation. To make them looking a bit more humane-like, let&#x27;s change their outfit.</p><div class="flex justify-center items-center flex-col"><div><img class="max-h-[20rem]" src="https://talesfrom.dev/static/images/two-people.png"/></div><div>A conversation</div></div><p>Much better. There is some work that A needs to get done, but only B knows how to achieve it. So we can say that B is a kind of <em>expert</em> on the topic that A wants to get the work done.</p><p>Let&#x27;s add additional constraint - because B is the expert, he isn&#x27;t that much interested in handling some requests from unknown parties. He just wants to get his job done where expertise is required. So the constraint is that A cannot speak to B.</p><p>How we can prevent from those guys talking to each other?</p><h3 id="is-something-missing"><a href="#is-something-missing" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Is something missing?</h3><p>Of course, our guys are floating in some ungrounded space and we can&#x27;t say where they are - in the shopping mall, in the university or maybe on the beach?</p><p>Let&#x27;s imagine that guy A comes to a building where B is working. Now, how we can prevent person A talking to person b, knowing that they are within a building?</p><div class="flex justify-center items-center flex-col"><div><img class="max-h-[20rem]" src="https://talesfrom.dev/static/images/two-people-missing-boundary.png"/></div><div>How to prevent them speaking?</div></div><p>Ok, we put them in the context of the workplace so might it be that there&#x27;s a wall between them?</p><div class="flex justify-center items-center flex-col"><div><img class="max-h-[20rem]" src="https://talesfrom.dev/static/images/two-people-a-wall.png"/></div><div>A wall.</div></div><p>Fine. There is a wall. A physical obstacle that prevents them from talking. A single wall, within a workplace might look weird so let&#x27;s think - if we take a couple of walls, what concept is created?</p><h3 id="rooms"><a href="#rooms" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Rooms</h3><p>The first thing that comes to my mind is a room. An empty space that is organized by humans, related to their needs. It is a physical boundary that might stop unwanted parties to enter, e.g. doors preventing from entering teenager&#x27;s room.</p><div class="flex justify-center items-center flex-col"><div><img class="max-h-[20rem]" src="https://talesfrom.dev/static/images/two-people-room.png"/></div><div>Rooms</div></div><p>But don&#x27;t forget - dude A has a work to do and the only person who knows how to do so is expert B. Let&#x27;s assign them some additional roles.</p><p>Imagine that guy A is a customer that enters to the workplace and requests a service.</p><p>On the other hand, B is an expert that knows how to do required steps of the skill-requiring work. And he doesn&#x27;t care about handling the requests.</p><p>Additionally, B&#x27;s &quot;workroom&quot; is full of equipment and he won&#x27;t like to have other people there that could break some appliances.</p><p>What to do now?</p><div class="flex justify-center items-center flex-col"><div><img class="max-h-[20rem]" src="https://talesfrom.dev/static/images/a-service.png"/></div><div>Servicing a customer</div></div><h3 id="an-open-position"><a href="#an-open-position" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>An open position!</h3><p>Probably B affords hiring a colleague that will handle &quot;the boring&quot; stuff: handling client requests and providing a respective details what they would like to do. Please warmly welcome C - a consultant.</p><div class="flex justify-center items-center flex-col"><div><img class="max-h-[20rem]" src="https://talesfrom.dev/static/images/three-people-service.png"/></div><div>A consultant handling the request</div></div><p>As a reminder: <span style="color:#087f5b">arrows</span> show the &quot;conversation&quot; direction.</p><p>That&#x27;s funny, the language we are using in our small example, while exploring the metaphor, looks quite similar to how we are talking about our software components?! (maybe not the consultant 😉)</p><p>If you follow me (I hope so, because I don&#x27;t have any eye-tracking components installed - yet!), we build up an interesting realm here. Our client can&#x27;t bypass the consultant to reach the domain expert. The expert is safely doing his precious work in his room.</p><p>How would we call both the consultant and the expert?</p><p>A group?</p><p>A team?</p><p>A gang?</p><p>A guild?</p><p>Once, I&#x27;ve heard that in order to work together to achieve a bigger goal, people need to organize themselves. They need to form an organizing unit.</p><h3 id="the-birth-of-organization"><a href="#the-birth-of-organization" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The birth of organization</h3><p>Could we say that our two actors, in our tiny theater, form an organization? I know, teeny-tiny one, but still.</p><p>Do they have a goal to achieve? Yes. The expert want to do his work in the best way, but not being bothered about talking to strangers so he needs to pay a wage to a consultant. Maintaining the equipment, skilling himself means costs. They both need to make profits.</p><p>Do they need to work together? Based on the previous answer it&#x27;s quite clear - it&#x27;s inevitable for them to collaborate if they want to make profit.</p><p>I think we advanced our metaphor quite interestingly - from a conversation between us, humans, and software components, e.g. objects, to an organization, in which people (or objects) are collaborating, fulfilling their responsibilities.</p><p>Just by having a simple example of two objects: business expert B and customer facing consultant C, we are able to &quot;grow&quot; our questions too!</p><ul><li>How consultant is passing the details of work - by going to the &quot;back-office&quot; or by leaving a message for B expert?</li><li>What if customers want to leave a message, not come to the office - will the consultant C handle that or there should be another role?</li><li>What if expert B is overloaded and can&#x27;t work due to excessive amount of workload?</li></ul><p>Our bread and butter activites, as software developers, are similar to: drowning in configuring ORMs, optimizing SQL queries or thinking how to add another boolean flag to our wicked object graph, that both represents data model and domain (sic!) model.</p><p>Where is the time for thinking about the design in such a (silly?) way?!</p><h3 id="what-if-we-scale-our-imaginary-organization"><a href="#what-if-we-scale-our-imaginary-organization" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What if we scale our imaginary organization?</h3><p>Ok, two people in organization isn&#x27;t that convicing. Who the hell hires a consultant when he or she can be a god object, excuse me, the most responsible person in &quot;one-man army&quot;-like company?</p><p>Imagine the following: there is an organization (called &quot;Imaginary&quot;) that provides two kind of services:</p><ol><li>a service for urban planning</li><li>a service for organizing and managing workers, to execute urban changes</li></ol><p>There are three groups working in this organization:</p><ul><li><span style="color:#15aabf">&quot;teal&quot;</span> group - responsible for handing services for urban planning (1)</li><li><span style="color:#868e96">&quot;gray&quot;</span> group - responsible for handling services for workers management (2)</li><li><span style="color:#fab005">&quot;dark orange/light brown&quot;</span> (or whatever color you see) group - responsible for archiving all the respective things about the work done by two other groups</li></ul><div class="flex justify-center items-center flex-col"><div><img class="max-h-[20rem]" src="https://talesfrom.dev/static/images/an-organization-intro.png"/></div><div>An imaginary organization&#x27;s office</div></div><p>There&#x27;s a catch: someone decided that the rooms, in the office, will be organized by the role/function employees were assigned to. Of course this office is weird, because it doesn&#x27;t have any doors (or something for walking between rooms!). Let&#x27;s fix it.</p><div class="flex justify-center items-center flex-col"><div><img class="max-h-[20rem]" src="https://talesfrom.dev/static/images/an-organization-rooms-assignment.png"/></div><div>Office rooms. Arrows denote &quot;who talks to whom&quot;</div></div><p>So we can denote four different rooms, related to a given type of role:</p><ul><li>room <code>P</code> - customer facing experts</li><li>room <code>A</code> - process experts applying a structure to business experts recommendations</li><li>room <code>B</code> - business experts with unique skills</li><li>room <code>D</code> - experts on archiving</li></ul><p>As a reminder, arrows show who is talking to whom.</p><p>People love innovations, so this sounded like a great innovation - distributing people across the rooms based on their knowledge, skills and profession. It might be some ingenious idea that experts in the room <code>A</code> will exchange the thoughts and it will bring a breakthrough? You never know.</p><h3 id="do-i-need-to-talk-with-all-of-them"><a href="#do-i-need-to-talk-with-all-of-them" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Do I need to talk with all of them?&quot;</h3><p>Still, the company has to provide their services.</p><p>The business needs to move forward, thus experts on urban planning (<span style="color:#15aabf">&quot;teal&quot;</span> group), working in the room <code>A</code>, <strong>should</strong> try to speak <strong>only</strong> to their peers. They should focus on their main service. The same applies for other groups in the other rooms.</p><p>But at some point, something happened.</p><p>In the room <code>A</code>, urban planning experts (<span style="color:#15aabf">&quot;teal&quot;</span> group) needed to quickly &quot;fix&quot; some mistake in the plan, and they asked worker management experts (<span style="color:#868e96">&quot;gray&quot;</span> group) to change scheduled workers&#x27; scope of job.</p><p>Soon, it turned out that more &quot;requests for a favor&quot; started forming the habit of this little organization. Such &quot;requests for a favor&quot; are marked as <span style="color:#a61e4d">arrows</span>. I think you know such scenario: &quot;there is a person, who knows a person, that knows a guy, who can help&quot;.</p><p>It sounds almost like a &quot;black market&quot; (I think I learned this metaphor in <a href="https://www.amazon.com/Software-Architect-Elevator-Redefining-Architects/dp/1492077542">&quot;Software Architect Elevator&quot;</a> book. If I am wrong please correct me!)</p><p>Soon, experts across the entire office were exchanging information about details of their work. Poor <span style="color:#fab005">archiver</span> helplessly needs to track all of the work and he is really scared of any audit.</p><div class="flex justify-center items-center flex-col"><div><img class="max-h-[20rem]" src="https://talesfrom.dev/static/images/an-organization-innovation.png"/></div><div>&quot;Black market&quot;-like collaboration</div></div><p>At some point, no employee in this little office is able to do the actual work, because he/she needs to know the details of another employee&#x27;s work.</p><p>Owners are angry, because the business isn&#x27;t performing well, the brilliant idea of organizing the office in the presented way isn&#x27;t performing well too.</p><p>What advice could we give to the owners?</p><h3 id="build-a-friggin-wall"><a href="#build-a-friggin-wall" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Build a friggin&#x27; wall</h3><p>How could we prevent experts from talking to each other so that they are laser-focused on their work?</p><p>I think we already explored the metaphor enough to answer such question: use a physical boundary - <span style="color:#40c057">a wall</span>.</p><p>Let&#x27;s imagine that our recommendation was actually implemented and this is how the office looks like now:</p><div class="flex justify-center items-center flex-col"><div><img class="max-h-[20rem]" src="https://talesfrom.dev/static/images/an-organization-wall.png"/></div><div>A wall and dedicated archives</div></div><p>Additionally, we gave another advice (extra charged, the invoice will be sent by email) - dedicate some of the archives for the urban planning experts&#x27; (<span style="color:#15aabf">&quot;teal&quot;</span> group) work, the rest of available archives are destined for the work of worker management experts (<span style="color:#868e96">&quot;gray&quot;</span> group). We can think of such approach as physical boundary, but withtin a room full of archives.</p><p>This makes <span style="color:#fab005">archiver</span> happy too, because he has everything in place so that in case of audit, he can easily pull information and create a report.</p><h3 id="are-we-done"><a href="#are-we-done" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Are we done?</h3><p>What about rooms <code>P</code> and <code>D</code>? Should we separate them too?</p><p>Turns out that the organization made the new policy - if urban planning experts (<span style="color:#15aabf">&quot;teal&quot;</span> group) want to ask some question or request something from worker management experts (<span style="color:#868e96">&quot;gray&quot;</span> group), they need to go to the customer facing experts of worker management experts (<span style="color:#868e96">&quot;gray&quot;</span> group) to achieve so. And vice versa.</p><p>And about <span style="color:#fab005">archiver</span> - he is only a single guy in the room so it does not make sense to build artificial walls. He manages to keep all archives in this single room.</p><h3 id="please-stop-drilling-this-metaphor"><a href="#please-stop-drilling-this-metaphor" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Please, stop drilling this metaphor!&quot;</h3><p>I hear your voice (do I?) - &quot;where are you going with this metaphor?&quot;.</p><p>Let&#x27;s reveal the hidden agenda I built through the entire tale.</p><p>It is not a coincidence that rooms were annotated with specific letters. Each room is related to a particular layer:</p><ul><li>room <code>P</code> = <code>Presentation</code> layer</li><li>room <code>A</code> = <code>Application</code> layer</li><li>room <code>B</code> - <code>Business</code> layer</li><li>room <code>D</code> - <code>Data</code> layer</li></ul><p>Our little organization was a model of a N-tier architecture (where N is 4 of course).</p><p>You can think of each employee as a class, with a particular role, based on the room (layer) assigned:</p><ul><li>experts in <code>P</code> room might be labelled as <code>Controllers</code></li><li>experts in <code>A</code> room might be labelled as <code>Services</code></li><li>experts in <code>B</code> room might be named <code>Models</code> or <code>Services</code> (something else? Please share your ideas!)</li><li>archiver in <code>D</code> room might be called <code>Repository</code></li></ul><div class="flex justify-center items-center flex-col"><div><img class="max-h-[20rem]" src="https://talesfrom.dev/static/images/an-organization-code.png"/></div><div>A model of an organization?</div></div><p>&quot;Black market&quot;-like collaboration is a typical way of how &quot;systems&quot; evolve when there are no clear and dedicated physical boundaries. Sooner or later every &quot;room&quot; and every &quot;expert&quot; is entangled.</p><p>In case of any change - a change of the structure of rooms, a new employee being onboarded - there is enormous effort, planning and unnecessary acitivities required.</p><p>&quot;Just&quot; by providing a proper boundary, everything can evolve in more organic, self-deteriorating-free fashion.</p><h3 id="i-have-an-idea"><a href="#i-have-an-idea" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;I have an idea!&quot;</h3><p>If you think more about the model we used for how we could think about our software components and systems, it has really interesting properties. Again, we can ask &quot;different&quot; questions - they are different, because they operate on the metaphor&#x27;s plane.</p><p>Here are some examplary questions I came up with:</p><ul><li>What if owners of &quot;Imaginary&quot; company decided to scale up the business by creating offices in other cities? Is it possible?</li><li>What if we want to hire worker management experts, which requires more office space, but keep urban planning experts at the same size?</li><li>What if urban planning experts have highly specific format of archives, whereas worker management experts use documents for archiving?</li><li>What does it mean that offices located in different cities need to communicate?</li></ul><p>Isn&#x27;t it interesting?</p><h3 id="do-you-need-this-model"><a href="#do-you-need-this-model" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Do you need this model?</h3><p>A model is usable within a particular context and it was created for a specific purpose - to provide a solution for some problem. The same applies to the model (or metaphor, I am using them interchangeably) we explored in this blog post.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>A model is usable within a particular context and it was created for a specific purpose - to provide a solution for some problem.</p></div></div></div><p>I think that <code>Organization-Driven Design</code>, as a model for thinking about the design, might be very empowering. We are trained by observing the surrounding reality how companies, employees and people operate, organize and collaborate.</p><p>Should you use it every time you design, e.g. a tiny class? No, probably not. It might be a waste of time.</p><p>Should you use it when you build your next CRUD-like API? Well, this might be pointless.</p><p>It&#x27;s not a tangible practice as TDD or building Value Objects, or Aggregates.</p><p>It can just accelerate the thinking about the design, because we might leverage what we see in our daily basis.</p><p>With this metaphor, you can explore various forms of collaborations, responsibility assignment and how people, mhm, objects should converse with each other.</p><p>Objects? Try to apply this model on the service level. I believe you can find some fascinating insights.</p><p>A bonus: you can try to use such stories to explain to &quot;business people&quot; why you have problems in production (&quot;my expert on archiving is giving information to the wrong people!&quot;).</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>What will happen if you think of your software product/service/architecture as an organization?</p></div></div></div><p>Have fun with modeling!</p>]]></content:encoded>
    <pubDate>Tue, 09 Aug 2022 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>programming</category><category>paradigms</category><category>domain-driven design</category><category>problem-solving</category><category>language</category><category>learning</category><category>metaphors</category><category>models</category><category>architecture</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/modeling-value-objects-in-typescript</guid>
    <title>Modeling Value Objects in TypeScript</title>
    <link>https://talesfrom.dev/blog/modeling-value-objects-in-typescript</link>
    <description>Having fun with encapsulation in TypesScript</description>
    <content:encoded><![CDATA[<div class="bg-slate-600 rounded-xl "><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Attention!</span></div><div class="pb-2 px-3"><div class="break-words"><p>You don&#x27;t want to read my observations about &quot;Value Object&quot; as a concept?</p>
<p>Skip to the <a href="#use-case-modeling-an-email-concept">&quot;meaty&quot;</a> part!</p></div></div></div><h3 id="how-to-be-deceived"><a href="#how-to-be-deceived" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>How to be deceived?</h3><p>I remember the first time I read <a href="https://www.domainlanguage.com/ddd/blue-book/">Blue Book</a> and how easily I put all of the focus on the tactical patterns. It might be that the reason was because I finally &quot;found my methods&quot;. I briefly described it in <a href="https://talesfrom.dev/blog/where-did-my-methods-go">Where did my methods go?</a>.</p><p>Sometimes I believe that dealing with the complexity of the systems gives us, technical people, the rush full of dopamine. We feel dizzy and dazed because we need to understand all of the abstractions, terms, inner workings, etc. Like sugar, this drug is really subtle to reveal.</p><h3 id="value-object"><a href="#value-object" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Value Object</h3><p>That was the first time I met a concept of Value Object. I completely misunderstood its meaning, invaluable perspective it brings. Please bear in mind I don&#x27;t state I understand it and its meaning now 😉.</p><p>Let&#x27;s take a &quot;typical&quot; (I don&#x27;t like this word, but it fits nicely in the current context) definition, or rather <a href="https://docs.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/implement-value-objects#important-characteristics-of-value-objects">traits description</a>.</p><p>Again, this definition by description of its traits sounds very tactical. It speaks with technical jargon. Identity, immutability - they are really nice. Once you tasted immutability it&#x27;s hard to forget (I am looking at you F#!).</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">How we could describe a &quot;Value Object&quot;?</div><div class="pb-2 px-3"><div class="break-words"><ul>
<li>
<p>it has no identity</p>
</li>
<li>
<p>it is immutable</p>
</li>
</ul></div></div></div><p>Don&#x27;t be deceived only by the great properties it has. One day, I suddenly started observing (I hope so at least 😛) its second, deeper nature.</p><h3 id="what-is-the-true-nature-of-value-object"><a href="#what-is-the-true-nature-of-value-object" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>What is the true nature of Value Object?</h3><p>If we leave tactical patterns for a while and go to strategic ones, we land in the realm where the focus is on modeling using a proper language.</p><p>Now we are in the kingdom where The King of All Kings, The Context, is ruling with his strict but fair influence.</p><p>And it gives exactly what you can express with a Value Object - a meaning.</p><p>Suddenly, we can <strong>consciously</strong> materialize concepts and build the language using programming contructs. How cool is that?</p><div class="bg-slate-600 rounded-xl"><div class="bg-slate-800 rounded-t-xl px-2 pt-2 font-bold">What problem does &quot;Value Object&quot; really solve?</div><div class="pb-2 px-3"><div class="break-words"><p>It flavors the code with conceptual meaning from the context it comes from.</p></div></div></div><p>I have a gut feeling that in order to utilize anything, we need to build a language construct (a model?) of it so that we can consciously operate on it (instead of randomly &quot;oh look what just happened&quot;).</p><h3 id="use-case-modeling-an-email-concept"><a href="#use-case-modeling-an-email-concept" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Use case: modeling an email concept</h3><p>Someone can say: &quot;Hey, but we can easily express domain concepts in <strong>Type</strong>Script!&quot;.</p><p>No doubt we can. Question is, is it the right model we are using?</p><p>To the point. I mean, example.</p><p>Let&#x27;s imagine the scenario that suddenly we need to add a functionality that would enable sending emails. Our user types an email address and then we need to process is accordingly. Email has its own <a href="https://datatracker.ietf.org/doc/html/rfc2822#section-3.4.1">specification</a>, but we will simplify it, a bit.</p><p>Our rule we need to ensure is that the email address needs to have <code>@</code> character.</p><p>The most straightforward approach we could imagine is the following:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">export</span> <span class="token keyword">type</span> <span class="token class-name">Email</span> <span class="token operator">=</span> <span class="token builtin">string</span>
</span></code></pre></div></div><div class="bg-slate-600 rounded-xl "><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Attention!</span></div><div class="pb-2 px-3"><div class="break-words"><p>One could ask why I didn&#x27;t use the new TS feature called <a href="https://www.typescriptlang.org/docs/handbook/2/template-literal-types.html">Template Literal Types</a> to properly shape the type, including <code>@</code> in between.</p>
<p>As modeling an email concept is kind of &quot;special&quot;, because it&#x27;s based on <code>string</code>, it would be quite easy to enforce proper structure by using aforementioned feature.</p>
<p>I decided to work with this simple example, because I believe most of the people know how to detect <em>invalid</em> email 😊</p></div></div></div><p>Of course, the capacity of a <code>string</code> is huge so our &quot;model&quot; (yes, it is a model) is very, very liberal.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">import</span> <span class="token punctuation">{</span> Email <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&quot;./email&quot;</span>
</span><span class="code-line"><span class="token keyword">const</span> trulyAnEmail<span class="token operator">:</span> Email <span class="token operator">=</span> <span class="token string">&quot;I am an email&quot;</span>
</span></code></pre></div></div><p>How we can protect our rule? Well, a function:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token function function-variable">isValidEmail</span> <span class="token operator">=</span> <span class="token punctuation">(</span>possiblyAnEmail<span class="token operator">:</span> Email<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> 
</span><span class="code-line">    <span class="token operator">!</span><span class="token punctuation">(</span>possiblyAnEmail<span class="token punctuation">.</span><span class="token function">indexOf</span><span class="token punctuation">(</span><span class="token string">&quot;@&quot;</span><span class="token punctuation">)</span> <span class="token operator">===</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span>
</span><span class="code-line">
</span></code></pre></div></div><p>The problem (of course!) is that those two things are separated, even though living in the same file, i.e. <code>email.ts</code>. Nothing stops us from not calling <code>isValidEmail</code> function.</p><p>How to tackle it? We could of course put an object wrapper around it, like that:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">Email</span> <span class="token operator">=</span> <span class="token punctuation">{</span> value<span class="token operator">:</span> <span class="token builtin">string</span> <span class="token punctuation">}</span>
</span></code></pre></div></div><p>But still nothing prevents us from creating a new instance without checking its validity. If we call something an &quot;email&quot;, it should be it!</p><h3 id="functional-oriented-encapsulation"><a href="#functional-oriented-encapsulation" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Functional-oriented&quot; Encapsulation</h3><p>Cool kids know that this is an example of encapsulation issue. So currently our main problem we want to solve is: <strong>how to properly encapsulate &quot;email&quot; concept?</strong></p><p>Using type aliases feels very &quot;functional&quot;, because it&#x27;s quite natural to create those types as keeping only data and then declare functions that operate on those types (maybe it is only natural to me? 😛)</p><p>In languages like F#, we could easily declare the type within a module, but make its &quot;constructor&quot; private, meaning that outside the module we can only use it, e.g. in function signature, but not create a value with such type.</p><p>Let&#x27;s take an example:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="code-highlight language-fsharp"><span class="code-line"><span class="token comment">// Email.fs</span>
</span><span class="code-line"><span class="token keyword">module</span> Email <span class="token operator">=</span>
</span><span class="code-line">    <span class="token keyword">type</span> <span class="token class-name">Email</span> <span class="token operator">=</span> <span class="token keyword">private</span> Email <span class="token keyword">of</span> email<span class="token punctuation">:</span> <span class="token class-name">string</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">let</span> create <span class="token punctuation">(</span>possiblyAnEmail<span class="token punctuation">:</span> <span class="token class-name">string</span><span class="token punctuation">)</span> <span class="token operator">=</span>
</span><span class="code-line">        <span class="token keyword">if</span> possiblyAnEmail<span class="token punctuation">.</span><span class="token function">Contains</span><span class="token punctuation">(</span><span class="token string">&quot;@&quot;</span><span class="token punctuation">)</span>
</span><span class="code-line">            <span class="token keyword">then</span> Email possiblyAnEmail
</span><span class="code-line">            <span class="token keyword">else</span> failwith <span class="token string">&quot;Not an email :-(&quot;</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token comment">//SomeOtherFile.fs</span>
</span><span class="code-line"><span class="token keyword">open</span> Email <span class="token comment">// use the module `Email`</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">let</span> anEmail<span class="token punctuation">:</span> <span class="token class-name">Email</span> <span class="token operator">=</span> Email <span class="token string">&quot;I fooled you!&quot;</span> <span class="token comment">// bzzzzt, compile time error!</span>
</span></code></pre></div></div><p>Unfortunately, as far as I know TypeScript (or JavaScript?) modules do not support accesibility modifiers in the way we want now:</p><ul><li>declare a type and export it (make it read-only without being able to instantiate it)</li><li>you can freely instantiate that within that module (or file)</li></ul><p>Could we try to use OO way to encapsulate this concept?</p><h3 id="exaggerated-object-oriented-encapsulation"><a href="#exaggerated-object-oriented-encapsulation" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Exaggerated &quot;Object-oriented&quot; Encapsulation</h3><p>How one does OO encapsulation? Of course, using a <code>class</code>.</p><p>Let&#x27;s try to model it iteratively.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token comment">// initial-oo-email.ts</span>
</span><span class="code-line"><span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">Email</span> <span class="token punctuation">{</span>
</span><span class="code-line">  <span class="token keyword">private</span> value<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span>
</span><span class="code-line">  <span class="token keyword">readonly</span> isValid<span class="token operator">:</span> <span class="token builtin">boolean</span><span class="token punctuation">;</span>
</span><span class="code-line">  <span class="token keyword">readonly</span> errorMessage<span class="token operator">?</span><span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span>
</span><span class="code-line">  <span class="token function">constructor</span><span class="token punctuation">(</span>value<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">this</span><span class="token punctuation">.</span>value <span class="token operator">=</span> value<span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token keyword">this</span><span class="token punctuation">.</span>isValid <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">isValidEmail</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token keyword">this</span><span class="token punctuation">.</span>isValid<span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">      <span class="token keyword">this</span><span class="token punctuation">.</span>errorMessage <span class="token operator">=</span> <span class="token template-string"><span class="token string template-punctuation">`</span><span class="token string">Oops, &quot;</span><span class="token interpolation"><span class="token punctuation interpolation-punctuation">${</span>value<span class="token punctuation interpolation-punctuation">}</span></span><span class="token string">&quot; is not a true email :-(</span><span class="token string template-punctuation">`</span></span><span class="token punctuation">;</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">  <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">  <span class="token keyword">private</span> <span class="token function">isValidEmail</span><span class="token punctuation">(</span>possiblyAnEmail<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">return</span> <span class="token operator">!</span><span class="token punctuation">(</span>possiblyAnEmail<span class="token punctuation">.</span><span class="token function">indexOf</span><span class="token punctuation">(</span><span class="token string">&#x27;@&#x27;</span><span class="token punctuation">)</span> <span class="token operator">===</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">  <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">
</span></code></pre></div></div><p>No-brainer usage:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token comment">// initial-oo-index.ts</span>
</span><span class="code-line"><span class="token keyword">import</span> <span class="token punctuation">{</span> Email <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&#x27;./initial-oo-email&#x27;</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">const</span> invalidEmail <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Email</span><span class="token punctuation">(</span><span class="token string">&#x27;I am an email&#x27;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token keyword">const</span> validEmail <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Email</span><span class="token punctuation">(</span><span class="token string">&#x27;john@johnny.com&#x27;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>invalidEmail<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Email {value: &quot;I am an email&quot;, isValid: false}</span>
</span><span class="code-line"><span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>validEmail<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Email {value: &quot;john@johnny.com&quot;, isValid: true}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">const</span> youCantInitializeMe<span class="token operator">:</span> Email <span class="token operator">=</span> <span class="token punctuation">{</span>
</span><span class="code-line">  value<span class="token operator">:</span> <span class="token string">&#x27;I am not an email&#x27;</span><span class="token punctuation">,</span>
</span><span class="code-line">  isValid<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
</span><span class="code-line"><span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token comment">// bzzzzt, value is my private field!</span>
</span></code></pre></div></div><p>Yes, I made this example a bit exaggerated, because <code>Email</code> might be misleading - we can create an instance and there check if it is actually valid by checking its <code>isValid</code> property.</p><p>But...Have you ever seen an email with &quot;a label&quot; sticking from it with text informing whether it is valid or not?</p><p>Nope, I assume you look at the email and you know if it is either valid or invalid. Thus we name them distinctively.</p><p>In other words, when we create an instance of the email, we want to be sure that we are talking about valid email, else its invalid.</p><h3 id="object-oriented-encapsulation"><a href="#object-oriented-encapsulation" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Object-oriented&quot; Encapsulation</h3><p>Let&#x27;s again use the main building block of OO - <code>class</code>, but now a bit differently.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token comment">// email-goto.ts</span>
</span><span class="code-line"><span class="token keyword">const</span> <span class="token function function-variable">isValidEmail</span> <span class="token operator">=</span> <span class="token punctuation">(</span>possiblyAnEmail<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
</span><span class="code-line">  <span class="token keyword">return</span> <span class="token operator">!</span><span class="token punctuation">(</span>possiblyAnEmail<span class="token punctuation">.</span><span class="token function">indexOf</span><span class="token punctuation">(</span><span class="token string">&#x27;@&#x27;</span><span class="token punctuation">)</span> <span class="token operator">===</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">Email</span> <span class="token punctuation">{</span>
</span><span class="code-line">  <span class="token keyword">private</span> value<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span>
</span><span class="code-line">  <span class="token keyword">private</span> <span class="token function">constructor</span><span class="token punctuation">(</span>value<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">this</span><span class="token punctuation">.</span>value <span class="token operator">=</span> value<span class="token punctuation">;</span>
</span><span class="code-line">  <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">  <span class="token keyword">static</span> <span class="token function">from</span><span class="token punctuation">(</span>value<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token operator">:</span> Email <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">isValidEmail</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Email</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span><span class="token template-string"><span class="token string template-punctuation">`</span><span class="token string">Oops, &quot;</span><span class="token interpolation"><span class="token punctuation interpolation-punctuation">${</span>value<span class="token punctuation interpolation-punctuation">}</span></span><span class="token string">&quot; is not a true email :-(</span><span class="token string template-punctuation">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line">  <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>Does it solve our problem mentioned at the beginning of <a href="#functional-oriented-encapsulation">&quot;Functional-oriented&quot; Encapsulation?</a>?</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token comment">// oo-goto-index.ts</span>
</span><span class="code-line"><span class="token keyword">import</span> <span class="token punctuation">{</span> Email <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&#x27;./email-goto&#x27;</span><span class="token punctuation">;</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">try</span> <span class="token punctuation">{</span>
</span><span class="code-line">  <span class="token keyword">const</span> invalidEmail <span class="token operator">=</span> Email<span class="token punctuation">.</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token string">&#x27;I am an email&#x27;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">  <span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>e<span class="token punctuation">.</span>message<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Oops, &quot;I am an email&quot; is not a true email :-(</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">const</span> validEmail <span class="token operator">=</span> Email<span class="token punctuation">.</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token string">&#x27;john@johnny.com&#x27;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line"><span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>validEmail<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Email {value: &quot;john@johnny.com&quot;}</span>
</span></code></pre></div></div><p>That&#x27;s really nice. We have exactly what we wanted to get. We are able to get either invalid or valid email. Sweet.</p><p>Let&#x27;s talk briefly about the thrown <code>Error</code>. As it is common practice for other languages (like C#, Java) to use exceptions as control flow mechanisms, I think we can utilize the power of TS types and provide more controlled solution.</p><p>Global error handling might (and probably will) catch it flawlessly, but it feels &quot;GOTO&quot;-ish, when we suddenly jump across multiple layers of our code. What we could do?</p><h3 id="listen-to-the-language"><a href="#listen-to-the-language" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Listen to the language</h3><p>I intentionally concluded that &quot;we are able to get either <strong>invalid</strong> or <strong>valid</strong> email&quot;. Paying attention to this subtle terminology, let&#x27;s model those cases accordingly.</p><div class="bg-slate-600 rounded-xl "><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Attention!</span></div><div class="pb-2 px-3"><div class="break-words"><p>Some parts of the code might get a bit overwhelming.</p>
<p>From now on such code blocks will appear as explandable sections marked with 💻 emoji.</p></div></div></div><p>Refactor time!</p><details><summary>💻 Show refactored code! 💻</summary><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token comment">// email.ts</span>
</span><span class="code-line"><span class="token keyword">const</span> <span class="token function function-variable">isValidEmail</span> <span class="token operator">=</span> <span class="token punctuation">(</span>possiblyAnEmail<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
</span><span class="code-line">  <span class="token keyword">return</span> <span class="token operator">!</span><span class="token punctuation">(</span>possiblyAnEmail<span class="token punctuation">.</span><span class="token function">indexOf</span><span class="token punctuation">(</span><span class="token string">&#x27;@&#x27;</span><span class="token punctuation">)</span> <span class="token operator">===</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token comment">// new!</span>
</span><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">ValidEmail</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
</span><span class="code-line">  type<span class="token operator">:</span> <span class="token string">&#x27;VALID_EMAIL&#x27;</span>
</span><span class="code-line">  context<span class="token operator">:</span> <span class="token punctuation">{</span>
</span><span class="code-line">    email<span class="token operator">:</span> Email
</span><span class="code-line">  <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token comment">// new!</span>
</span><span class="code-line"><span class="token keyword">const</span> validEmailAs <span class="token operator">=</span> <span class="token punctuation">(</span>email<span class="token operator">:</span> Email<span class="token punctuation">)</span><span class="token operator">:</span> ValidEmail <span class="token operator">=&gt;</span> <span class="token punctuation">(</span><span class="token punctuation">{</span>
</span><span class="code-line">  type<span class="token operator">:</span> <span class="token string">&#x27;VALID_EMAIL&#x27;</span><span class="token punctuation">,</span>
</span><span class="code-line">  context<span class="token operator">:</span> <span class="token punctuation">{</span> email <span class="token punctuation">}</span><span class="token punctuation">,</span>
</span><span class="code-line"><span class="token punctuation">}</span><span class="token punctuation">)</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token comment">// new!</span>
</span><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">InvalidEmail</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
</span><span class="code-line">  type<span class="token operator">:</span> <span class="token string">&#x27;INVALID_EMAIL&#x27;</span>
</span><span class="code-line">  context<span class="token operator">:</span> <span class="token punctuation">{</span>
</span><span class="code-line">    errorMessage<span class="token operator">:</span> <span class="token builtin">string</span>
</span><span class="code-line">  <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token comment">//new!</span>
</span><span class="code-line"><span class="token keyword">const</span> invalidEmailFrom <span class="token operator">=</span> <span class="token punctuation">(</span>value<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token operator">:</span> InvalidEmail <span class="token operator">=&gt;</span> <span class="token punctuation">(</span><span class="token punctuation">{</span>
</span><span class="code-line">  type<span class="token operator">:</span> <span class="token string">&#x27;INVALID_EMAIL&#x27;</span><span class="token punctuation">,</span>
</span><span class="code-line">  context<span class="token operator">:</span> <span class="token punctuation">{</span> errorMessage<span class="token operator">:</span> <span class="token template-string"><span class="token string template-punctuation">`</span><span class="token string">Oops, &quot;</span><span class="token interpolation"><span class="token punctuation interpolation-punctuation">${</span>value<span class="token punctuation interpolation-punctuation">}</span></span><span class="token string">&quot; is not a true email :-(</span><span class="token string template-punctuation">`</span></span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
</span><span class="code-line"><span class="token punctuation">}</span><span class="token punctuation">)</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">Email</span> <span class="token punctuation">{</span>
</span><span class="code-line">  <span class="token keyword">private</span> value<span class="token operator">:</span> <span class="token builtin">string</span>
</span><span class="code-line">  <span class="token keyword">private</span> <span class="token function">constructor</span><span class="token punctuation">(</span>value<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">this</span><span class="token punctuation">.</span>value <span class="token operator">=</span> value
</span><span class="code-line">  <span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line">  <span class="token keyword">static</span> <span class="token function">from</span><span class="token punctuation">(</span>value<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token operator">:</span> InvalidEmail <span class="token operator">|</span> ValidEmail <span class="token punctuation">{</span> <span class="token comment">// &lt;=== new return type!</span>
</span><span class="code-line">    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">isValidEmail</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token function">validEmailAs</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Email</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class="code-line">
</span><span class="code-line">    <span class="token keyword">return</span> <span class="token function">invalidEmailFrom</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span>
</span><span class="code-line">  <span class="token punctuation">}</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div></details><p>We are trying to speak with the language of our small domain and we provided new language constructs inside of our code.</p><p>Now the caller has the power (and the responsibility that comes with this power 😉):</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token comment">// oo-index.ts</span>
</span><span class="code-line"><span class="token keyword">import</span> <span class="token punctuation">{</span> Email <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&#x27;./email&#x27;</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">const</span> invalidEmail <span class="token operator">=</span> Email<span class="token punctuation">.</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token string">&#x27;I am an email&#x27;</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>invalidEmail<span class="token punctuation">)</span> <span class="token comment">// { type: &quot;INVALID_EMAIL&quot;, context: { errorMessage: &quot;Oops, &quot;I am an email&quot; is not a true email :-(&quot; }}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">const</span> validEmail <span class="token operator">=</span> Email<span class="token punctuation">.</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token string">&#x27;john@johnny.com&#x27;</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>validEmail<span class="token punctuation">)</span> <span class="token comment">// { type: &quot;VALID_EMAIL&quot;, context: { email: &quot;john@johnny.com&quot; } }</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">const</span> youCantInitializeMe<span class="token operator">:</span> Email <span class="token operator">=</span> <span class="token punctuation">{</span>
</span><span class="code-line">  value<span class="token operator">:</span> <span class="token string">&#x27;I am not an email&#x27;</span><span class="token punctuation">,</span>
</span><span class="code-line"><span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token comment">// bzzzzt, value is my private field!</span>
</span></code></pre></div></div><p>It looks fantastic. Now we could embed only valid email type in our complex sending function.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token comment">// oo-index.ts</span>
</span><span class="code-line"><span class="token keyword">function</span> <span class="token function">sendingEmailTo</span><span class="token punctuation">(</span>validEmail<span class="token operator">:</span> ValidEmail<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// bzzzzt, no `ValidEmail` type available!</span>
</span><span class="code-line">    <span class="token comment">// complex code</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre></div></div><p>We put a constraint in the <code>sendingEmailTo</code> function telling the reader that it can be used <strong>only</strong> with <code>ValidEmail</code>. That&#x27;s pretty neat, isn&#x27;t it?</p><p>This constraint is checked in compile-time! Oh, btw. our code doesn&#x27;t compile.</p><p>We didn&#x27;t export <code>ValidEmail</code> nor <code>InvalidEmail</code> types purposefully so that no one is able to &quot;cheat&quot; and create it outside of the module.</p><p>Still that&#x27;s pretty easy if you know how to extract the type from the union type.</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token comment">// oo-index.ts</span>
</span><span class="code-line"><span class="token keyword">type</span> <span class="token class-name">ValidEmail</span> <span class="token operator">=</span> Extract<span class="token operator">&lt;</span>ReturnType<span class="token operator">&lt;</span><span class="token keyword">typeof</span> Email<span class="token punctuation">[</span><span class="token string">&quot;from&quot;</span><span class="token punctuation">]</span><span class="token operator">&gt;</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> type<span class="token operator">:</span> <span class="token string">&quot;VALID_EMAIL&quot;</span> <span class="token punctuation">}</span><span class="token operator">&gt;</span>
</span></code></pre></div></div><p>On the other hand, exposing those types should be rather safe (in this particular context).</p><h3 id="functional-oriented-encapsulation---revisited"><a href="#functional-oriented-encapsulation---revisited" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>&quot;Functional-oriented&quot; Encapsulation - revisited!</h3><p>Ok, fine. We are able to model Value Objects as OO-style classes, but is &quot;Functional way&quot; lost? Should we abandon it saying it&#x27;s impossible?!</p><p>Fortunately, there are geniuses in this world. Thanks to <a href="https://twitter.com/MichaelArnaldi/status/1549689395665575936">Michael Arnaldi</a> I learned that there&#x27;s hope - non-exported property approach!</p><p>Turns out it is well-established concept called <code>Opaque</code> or <code>Branded</code> types. Let&#x27;s jump into usage to understand what might be the cause of those names.</p><h3 id="email-domain-modeling-made-functional"><a href="#email-domain-modeling-made-functional" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Email &quot;domain&quot; modeling made &quot;functional&quot;</h3><p>In order to achieve what was suggested by Michael, we need to utilize <code>Symbol</code> primitive. It has very unique property - it is guaranteed it will be unique. You can find more details <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol">here</a>.</p><p>Let&#x27;s write some code!</p><div class="bg-slate-600 rounded-xl "><div class="bg-yellow-500 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Attention!</span></div><div class="pb-2 px-3"><div class="break-words"><p>I didn&#x27;t put the code that will be similar to what we saw in OO-style, namely:</p>
<ul>
<li><code>ValidEmail</code> type</li>
<li><code>validEmailAs</code> function</li>
<li><code>InvalidEmail</code> type</li>
<li><code>invalidEmailFrom</code> function</li>
<li><code>isValidEmail</code> function</li>
</ul>
<p>Imagine they are available somewhere in the <code>branded-email.ts</code> file 😉</p></div></div></div><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token comment">// let&#x27;s assume we have `isValidEmail`, `validEmailAs` and `invalidEmailFrom` functions, `ValidEmail` and `InvalidEmail` types available</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token comment">// branded-email.ts</span>
</span><span class="code-line"><span class="token keyword">const</span> _emailBrand<span class="token operator">:</span> unique <span class="token builtin">symbol</span> <span class="token operator">=</span> <span class="token function">Symbol</span><span class="token punctuation">(</span><span class="token string">&quot;EMAIL&quot;</span><span class="token punctuation">)</span> <span class="token comment">// NOTE WE ARE NOT EXPORTING IT!</span>
</span><span class="code-line"><span class="token keyword">export</span> <span class="token keyword">type</span> <span class="token class-name">Email</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword">readonly</span> <span class="token punctuation">[</span>_emailBrand<span class="token punctuation">]</span><span class="token operator">:</span> <span class="token keyword">typeof</span> _emailBrand<span class="token punctuation">,</span>
</span><span class="code-line">    <span class="token keyword">readonly</span> value<span class="token operator">:</span> <span class="token builtin">string</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">export</span> <span class="token keyword">const</span> from <span class="token operator">=</span> <span class="token punctuation">(</span>possiblyAnEmail<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token operator">:</span> ValidEmail <span class="token operator">|</span> InvalidEmail <span class="token operator">=&gt;</span> 
</span><span class="code-line">    <span class="token function">isValidEmail</span><span class="token punctuation">(</span><span class="token builtin">string</span><span class="token punctuation">)</span><span class="token operator">?</span>
</span><span class="code-line">        <span class="token function">validEmailAs</span><span class="token punctuation">(</span><span class="token punctuation">{</span> 
</span><span class="code-line">            <span class="token punctuation">[</span>_emailBrand<span class="token punctuation">]</span><span class="token operator">:</span> _emailBrand<span class="token punctuation">,</span>
</span><span class="code-line">            value<span class="token operator">:</span> possiblyAnEmail 
</span><span class="code-line">        <span class="token punctuation">}</span><span class="token punctuation">)</span>
</span><span class="code-line">        <span class="token operator">:</span> <span class="token function">invalidEmailFrom</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span>
</span></code></pre></div></div><p>And its usage:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token comment">//non-module-index.ts</span>
</span><span class="code-line"><span class="token keyword">import</span> <span class="token punctuation">{</span> from<span class="token punctuation">,</span> Email <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&quot;./branded-email&quot;</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">const</span> invalidEmailFromBranded <span class="token operator">=</span> <span class="token function">from</span><span class="token punctuation">(</span><span class="token string">&#x27;I am an email&#x27;</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>invalidEmailFromBranded<span class="token punctuation">)</span> <span class="token comment">// { type: &quot;INVALID_EMAIL&quot;, context: { errorMessage: &quot;Oops, &quot;I am an email&quot; is not a true email :-(&quot; }}</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">const</span> validEmailFromBranded <span class="token operator">=</span> <span class="token function">from</span><span class="token punctuation">(</span><span class="token string">&#x27;john@johnny.com&#x27;</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>validEmailFromBranded<span class="token punctuation">)</span> <span class="token comment">// { type: &quot;VALID_EMAIL&quot;, context: { email: &quot;john@johnny.com&quot; } }</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">const</span> youCantInitializeMe<span class="token operator">:</span> Email <span class="token operator">=</span> <span class="token punctuation">{</span>
</span><span class="code-line">    value<span class="token operator">:</span> <span class="token string">&quot;I am not an email&quot;</span>
</span><span class="code-line"><span class="token punctuation">}</span> <span class="token comment">// bzzzzt, you need to have a symbol to initialize me!</span>
</span></code></pre></div></div><p>Well, at least it works. One might say that this is huge disadvantage of Functional Programming - functions floating here, floating there. Our lovely <code>from</code> function is a great example.</p><p>It gives no context, and as we know, The Context is the king of kings.</p><p>Can we do better? Just use module &quot;notation&quot;!</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-ts code-highlight"><span class="code-line"><span class="token comment">// module-index.ts</span>
</span><span class="code-line"><span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> Email <span class="token keyword">from</span> <span class="token string">&#x27;./branded-email&#x27;</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">const</span> invalidEmailFromBranded <span class="token operator">=</span> Email<span class="token punctuation">.</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token string">&#x27;I am an email&#x27;</span><span class="token punctuation">)</span> <span class="token comment">// { type: &quot;INVALID_EMAIL&quot;, context: { errorMessage: &quot;Oops, &quot;I am an email&quot; is not a true email :-(&quot; }}</span>
</span><span class="code-line"><span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>invalidEmailFromBranded<span class="token punctuation">)</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">const</span> validEmailFromBranded <span class="token operator">=</span> Email<span class="token punctuation">.</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token string">&#x27;john@johnny.com&#x27;</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>validEmailFromBranded<span class="token punctuation">)</span> <span class="token comment">// { type: &quot;VALID_EMAIL&quot;, context: { email: &quot;john@johnny.com&quot; } }</span>
</span><span class="code-line">
</span><span class="code-line"><span class="token keyword">const</span> youCantInitializeMe<span class="token operator">:</span> Email<span class="token punctuation">.</span>Email <span class="token operator">=</span> <span class="token punctuation">{</span>
</span><span class="code-line">    value<span class="token operator">:</span> <span class="token string">&quot;I am not an email&quot;</span>
</span><span class="code-line"><span class="token punctuation">}</span> <span class="token comment">// bzzzzt, you need to have a symbol to initialize me!</span>
</span></code></pre></div></div><h3 id="modeling-with-encapsulation-functional-oriented-vs-object-oriented"><a href="#modeling-with-encapsulation-functional-oriented-vs-object-oriented" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Modeling with encapsulation: &quot;Functional-oriented&quot; vs &quot;Object-oriented&quot;?</h3><p>It might be a matter of preference which of those approaches is &quot;better&quot; (whatever it means in this context).</p><p>One interesting observation came from this little experiment - OO-style <code>Email.from</code> looks really similar to FP-style module-based <code>Email.from</code>.</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>Use modules when working with functions so that they are not floating around deattached from their context!</p></div></div></div><p>This might be counter-intuitive, especially when you need to grab one, tiny function, which is a valid point. Soon, it might call friends and there would be an army of &quot;little&quot; functions with no context attached.</p><p>I would say it doesn&#x27;t matter that much which &quot;style&quot; you actually use. As long as you model a given concept precisely enough in the context in which it &quot;lives&quot;, then you are already the winner.</p><p>On the other hand, I feel that functional languages are a bit further in modeling, because of their Sum and Product types, that enable you to OR-ing and AND-ing (check <a href="https://pragprog.com/titles/swdddf/domain-modeling-made-functional/">Domain Modeling Made Functional</a> for further details, because it&#x27;s explains it with a great metaphor!).</p><div class="bg-slate-600 rounded-xl"><div class="bg-green-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Conclusion 🔍</span></div><div class="pb-2 px-3"><div class="break-words"><p>When modeling, pay attention to the language used - words, terms, concepts - and materialize them using types.</p></div></div></div><p>For example, in F# (and TS too!) I really feel encouraged to properly express various terms and concepts like <code>InvalidEmail</code> and <code>ValidEmail</code>.</p><p>As a last step in our exercise, knowing all we&#x27;ve seen, here&#x27;s the question:</p><div class="bg-slate-600 rounded-xl"><div class="bg-violet-700 rounded-t-xl px-2 pt-2 font-bold text-black"><span>Question 🤔</span></div><div class="pb-2 px-3"><div class="break-words"><p>How could we model a forbidden email which must be valid one, but its domain is not in the &quot;allowed&quot; domains collection?</p></div></div></div><h3 id="all-code-examples"><a href="#all-code-examples" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>All code examples</h3><p>If you want to play with the code examples we went through during our little journey, you can find them <a href="https://stackblitz.com/edit/modeling-value-objects-in-typescript?devToolsHeight=100&amp;file=index.ts">here</a>.</p><p>Main file is <code>index.ts</code> and then it loads sub-main modules. Each refers to a separate step in our experiment. You can comment/uncomment each of the <code>import</code> to see the effects.</p>]]></content:encoded>
    <pubDate>Sun, 31 Jul 2022 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>programming</category><category>paradigms</category><category>domain-driven design</category><category>problem-solving</category><category>language</category><category>learning</category><category>typescript</category><category>encapsulation</category><category>value objects</category><category>code</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/conversation-driven-design</guid>
    <title>Conversation-Driven Design</title>
    <link>https://talesfrom.dev/blog/conversation-driven-design</link>
    <description>The metaphor of how to perceive the system (or its parts) you are building</description>
    <content:encoded><![CDATA[<h3 id="how-to-send-a-package"><a href="#how-to-send-a-package" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>How to send a package?</h3><p>Let&#x27;s imagine you have a strong need to send a package with some valuable goods to a friend of yours that is located in another city. You either order a delivery man to come to your place and pick it up or you go to the parcel shipment place.</p><p>Let&#x27;s add some interesting conditions to this scenario. An assumption is that there&#x27;s no other delivery companies in neighborhood and you are somehow forced to pick this particular one.</p><p>Additionally, their modern looking sexy SPA web app is facing some issues (maybe they are handling gazillion customers at the time and their k8s cluster struggles? Who knows?!). You must fill in the details manually (😨).</p><p>Due to those reasons you decide to select the second option. You enter that facility and the first thought is to find an individual that can help you.</p><p>Almost immediately you are approached by an employee and the conversation starts innocently:</p> <div class="italic bg-slate-600 rounded-xl p-2"><p>- Hi! How can I help you? - the employee asks.</p> <p>- Hello! I would like to deliver this package - you raise your hands, holding a parcel, a bit higher - I already filled in the form. - you show your handwriting - Can you check if it&#x27;s fine?</p> <p>- Yes, let me take a look.</p> <p>~ The employee checks the form and the delivery letter. ~ </p><p>- Hmm, seems like you mistakenly swapped address cell and phone cell. Also postal code isn&#x27;t filled in correctly. </p><p>~ You frown your eyebrows a bit, but continue the dialogue. ~ </p><p>- What&#x27;s wrong with the postal code? - you asks politely. </p><p>- Oh, sorry for not being explicit! You forgot the &quot;-&quot; in between the numbers*.</p><div>-------------------</div><p class="text-xs">* in Poland postal codes are in the format of XY-ABC</p></div><p>You got your delivery form corrected thanks to the validation you received from the employee. In couple of minutes you finalized a request to deliver your package.</p><h3 id="packages-what-is-it-all-about"><a href="#packages-what-is-it-all-about" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Packages? What is it all about?</h3><p>Why the heck I bother you with such a dull story that you could (and probably did) experience in your lifetime?</p><p>Let&#x27;s end writing our lovely courier story and use the theme of sending parcel further on.</p><p>Imagine you are designing a similar customer facing capability - validating a delivery form.</p><p>It doesn&#x27;t seem complicated, because it&#x27;s &quot;just&quot; reading some form values, (maybe) sending them to the server and actually getting a response, isn&#x27;t it?</p><p>Wait. What language was used in the conversation with the imaginary employee of the delivery facility?</p><p>Of course, nothing alike &quot;server&quot;, &quot;form values&quot;, &quot;sending&quot;, etc. None of us would dare to ask those questions when speaking to the human being, trying to resopnd to the request of delivering a package, right?</p><p>Probably (I hope so!) you know where my thoughts are flowing.</p><h3 id="model-out-loud"><a href="#model-out-loud" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Model Out Loud</h3><p>In the Blue Book - the Blue Bible of DDD - Eric started the subsection &quot;Modeling Out Loud&quot; with the following words:</p><blockquote><p>The detachment of speech from other forms of communication is a particuarly great loss because we humans have a genius for spoken language.</p></blockquote><p>This is a great introduction to the concept of <strong>ubiquitous language</strong>.</p><p>But this subsection pinpoints interesting property of human abilities to comperhend the complexity of a given topic.</p><p>He then continues:</p><blockquote><p>One of the best ways to refine a model is to explore with speech, trying out loud various constructs from possible model variations.</p></blockquote><p>This might seem as a counter-intuitive advice, because we, the professionals, are using drawings and eye-based tools to work on our models. Highly visual information reception.</p><p>One picture is worth 1024 words, isn&#x27;t it?</p><p>It might be true, but there&#x27;s something with the auditory traits of modeling.</p><p>In the modern world most people know that we, as a human race, use storytelling to convey important values, inspire other people and sell the ideas while standing in the front of other individuals.</p><p>As the first primates used grunts and snarls to tell a story of strange berries that put uncle Barry to death, we do similar activites, but in various scenarios and with different scale.</p><p>That&#x27;s also pointed out by the Author of the Blue Book:</p><blockquote><p>In fact, our brains seem to be somewhat specialized for dealing with complexity in spoken language.</p></blockquote><h3 id="human---auditory-validator-included"><a href="#human---auditory-validator-included" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Human - Auditory Validator Included</h3><p>It all &quot;feels&quot; that if something sounds bad or unnatural - we sense it. We don&#x27;t need to be our native language teacher to catch inconsistencies in the used language.</p><p>I am not a language scientist, neither a researcher, but the common sense tells me that the evolution of the speech didn&#x27;t happen during single night and there are a lot of trial and errors to make our auditory skills on the level we have it now.</p><p>Why not utilizing it?</p><p>The conclusion of the subsection, done by Eric, is:</p><blockquote><p>Play with the model as you talk about the system. Describe scenarios out loud using the elements and <strong>interactions</strong> of the model, combining concepts in ways allowed by the model. <strong>Find easier ways to say what you need to say</strong>. (...)</p></blockquote><p>Saying it out loud. Expressing the use cases, scenarios and <strong>interactions</strong> almost as if we would tell the story.</p><p>But wait, what is the goal of speaking?</p><h3 id="talking-as-a-tool"><a href="#talking-as-a-tool" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Talking as a tool?</h3><p>We evolved to interact, to talk to each other. Talking to other human beings is therapeutic - we need to talk to other people for so many various reasons - to express, to moan, to share, to validate our point of view, etc.</p><p>As the Author of the Blue Book emphasized - saying things out loud might be really powerful technique.</p><p>But then - saying to whom? To yourself? Or telling out loud so that your peers can hear that?</p><p>Let&#x27;s get back to our domain of sending parcels. It&#x27;s somehow natural to think of technical terms about validation of delivery form.</p><p>What would happen if we imagine that we are actually <strong>talking</strong> to a person who does such validation, if there was no internet? You know, a conversation as in the good, old days when there was no Messenger, Signal and WhatsApp.</p><h3 id="conversation---a-model-for-modeling"><a href="#conversation---a-model-for-modeling" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Conversation - a model for modeling</h3><p>Thinking of your software constructs as they would be individuals you can talk to might bring interesting properties. And what I love the most: interesting <strong>questions</strong>. Pretending your are talking to such imaginary person:</p><ul><li>What questions would you ask?</li><li>What information this person needs to answer your question?</li><li>What language would that person use?</li><li>What concepts would be juggled over during such conversation?</li><li>What questions would be rejected by that person?</li><li>Which requests would be denied due to lack of related responsiblity?</li><li>If that person doesn&#x27;t use desired terms, should you teach this person with those words?</li></ul><p>And, thanks to human development, we are quite good at conversing. It means we might use our abilities to design proper interactions, sense how a natural dialogue might look like.</p><h3 id="use-case-1-talking-to-an-sensitive-information-validation-expert"><a href="#use-case-1-talking-to-an-sensitive-information-validation-expert" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Use case #1: talking to an sensitive information validation expert.</h3><p>Let&#x27;s take another use case.</p><p>Recently I had a chance to work with a little capability for validating some sensitive information. Let&#x27;s say they were stored in some file.</p><p>Technically speaking, there was a method accepting a list of keys (their values are targets for validation) and the path to the file. Surprisingly, the return type was <code>bool</code>.</p><p>Imagine that this software construct is a validation expert. How such conversation would look like?</p><div class="italic bg-slate-600 rounded-xl p-2"><p>- Hi! I have this file - I showed it - and here are lists of keys. Could you do me a favor and validate underlying values?</p> <p>- Wrong.</p> <p>~ Awkward moment. ~</p> <p>- Haha, nice joke! But really, could you take a look on those keys and tell me whether related values are valid?</p> <p>- Wrong.</p></div><p>I feel that we wouldn&#x27;t talk any further...</p><p>Then, how would an <em>ideal</em> dialogue look like?</p><div class="italic bg-slate-600 rounded-xl p-2"><p>- Hi! I have this file - I showed it - and here are lists of keys. Could you do me a favor and validate underlying values?</p> <p>- Sorry, but values under keys A and B are in the wrong format. The desired format is XYZ.</p> <p>* Immediately fixing the format issues. *</p> <p>- Could you check it again?</p> <p>- Yes, that looks ok.</p></div><p>Such conversation would lead us into a proper solution: taking into account we can use F# types, such &quot;software validating expert&quot; could return <code>Result&lt;(), ValidationErrorMessages&gt;</code>.</p><p>Or maybe we should teach it the right language - <code>SensitiveDetailsValidationResult</code>?</p><h3 id="use-case-2-talking-to-an-e-mail"><a href="#use-case-2-talking-to-an-e-mail" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Use case #2: talking to an e-mail</h3><p>I hear you: &quot;Hey, how the hell I am supposed to talk to AN EMAIL?!&quot;</p><p>Yes, that might be tough experience, especially that e-mails are not that talkative these days.</p><p>In various implementations, a concept of an e-mail is represented as <code>string</code>. Why to overcomplicate things, right?</p><p>Let&#x27;s go further and apply our metaphor of conversing with an expert - this time with &quot;e-mail&quot; expert, the tamer of the chars:</p><div class="italic bg-slate-600 rounded-xl p-2"><p>- Hi! I became an owner of the collection of such characters - I present the characters to this guy - could you tell me if this is valid e-mail?</p> <p>- Sorry, I can tell you if it&#x27;s empty or null. Maybe you want to know if they are all digits?</p> <p>* I breath loudly *</p> <p>- As far as I recall, email should contain an &quot;@&quot; char, etc. You should know that - you are an expert!</p> <p>- Do you want to find a substring?</p></div><p>For sure this conversation won&#x27;t have happy ending and we would find some other person that would become profficient in working with <code>string</code> &quot;e-mail&quot; expert - maybe <code>EmailUtils</code> or <code>EmailManager</code>?</p><p>How would you model such conversation, where the expert knows the language of the email validation domain?</p><h3 id="use-case-3-talking-to-a-dialogue-presentation-expert"><a href="#use-case-3-talking-to-a-dialogue-presentation-expert" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Use case #3: talking to a dialogue presentation expert</h3><p>When I started working on this blogpost, I was wondering how to present a dialogue card.</p><p>Nothing fancy, really. Just to make sure that it is visually distinguishable from the &quot;regular text&quot;. I started embedding the first dialogue from <a href="#how-to-send-a-package">How to send a package?</a> in the following form:</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-jsx code-highlight"><span class="code-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>italic bg-slate-600 rounded-xl p-2<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token plain-text">
</span></span><span class="code-line"><span class="token plain-text">    </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">&gt;</span></span><span class="token plain-text">- Hi! How can I help you? - the employee asks.</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">&gt;</span></span><span class="token plain-text">
</span></span><span class="code-line"><span class="token plain-text">    </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">&gt;</span></span><span class="token plain-text">- Hello! I would like to deliver this package - you raise your hands, holding a parcel, a bit higher - I already filled in the form. - you show your handwriting - Can you check if it&#x27;s fine?</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">&gt;</span></span><span class="token plain-text">
</span></span><span class="code-line"><span class="token plain-text">    </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">&gt;</span></span><span class="token plain-text">- Yes, let me take a look.</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">&gt;</span></span><span class="token plain-text">
</span></span><span class="code-line"><span class="token plain-text">    </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">&gt;</span></span><span class="token plain-text"> ~ The employee checks the form and the delivery letter. ~ </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">&gt;</span></span><span class="token plain-text">
</span></span><span class="code-line"><span class="token plain-text">    </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">&gt;</span></span><span class="token plain-text">- Hmm, seems like you mistakenly swapped address cell and phone cell. Also postal code isn&#x27;t filled in correctly. </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">&gt;</span></span><span class="token plain-text">
</span></span><span class="code-line"><span class="token plain-text">    </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">&gt;</span></span><span class="token plain-text"> ~ You frown your eyebrows a bit, but continue the dialogue. ~ </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">&gt;</span></span><span class="token plain-text">
</span></span><span class="code-line"><span class="token plain-text">    </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">&gt;</span></span><span class="token plain-text">- What&#x27;s wrong with the postal code? - you asks politely. </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">&gt;</span></span><span class="token plain-text">
</span></span><span class="code-line"><span class="token plain-text">    </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">&gt;</span></span><span class="token plain-text">- Oh, sorry for not being explicit! You forgot the &quot;-&quot; in between the numbers*.</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">&gt;</span></span><span class="token plain-text">
</span></span><span class="code-line"><span class="token plain-text">    </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span><span class="token punctuation">&gt;</span></span><span class="token plain-text">-------------------</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><span class="token plain-text">
</span></span><span class="code-line"><span class="token plain-text">    </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>text-xs<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token plain-text">* in Poland postal codes are in the format of XY-ABC</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">&gt;</span></span><span class="token plain-text">
</span></span><span class="code-line"><span class="token plain-text"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
</span></code></pre></div></div><p>In the first seconds, it felt &quot;correct&quot;, but as I was using &quot;a conversation as a modelilng tool&quot;, I asked myself &quot;how would a conversation with such presentation expert look like?&quot;</p><div class="italic bg-slate-600 rounded-xl p-2"><p>- Hi! I want to display a dialogue with some specific background traits where each line needs to be placed in the sequence. Could you help me with this?</p> <p>- Sure! I take a <code>div</code> for dialogue and <code>p</code> elements for lines - this would work like a charm.</p> <p>- But you know how to display a chat, right?</p> <p>- Haha, no worries kid! I am an expert in displaying chats!</p></div><p>At least he would solve the riddle, right?</p><p>I stopped there and thought of another model: how would &quot;real&quot; dialogue presentation expert talk to me?</p><div class="italic bg-slate-600 rounded-xl p-2"><p>- Hi! I want to display a dialogue with some specific background traits where each line needs to be placed in the sequence. Could you give me a helphand?</p> <p>- Sure! Just take a <code>Dialogue</code> and put a bunch of <code>Dialogue.Line</code>s inside of it. It should do the work.</p> <p>- What about the side notices?</p> <p>- Specify them when you start your <code>Dialogue</code>.</p></div><p>What might be a potential result of such conversation?</p><div class="relative"><div class="max-h-[30rem] flex overflow-y-auto themed-scrollbar"><pre class="w-full themed-scrollbar"><code class="language-jsx code-highlight"><span class="code-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">Dialogue</span></span> <span class="token attr-name">notices</span><span class="token language-javascript script"><span class="token punctuation script-punctuation">=</span><span class="token punctuation">{</span><span class="token punctuation">[</span>
</span></span></span><span class="code-line"><span class="token tag"><span class="token language-javascript script">    <span class="token string">&quot;* in Poland postal codes are in the format of XY-ABC&quot;</span>
</span></span></span><span class="code-line"><span class="token tag"><span class="token language-javascript script"><span class="token punctuation">]</span><span class="token punctuation">}</span></span><span class="token punctuation">&gt;</span></span><span class="token plain-text">
</span></span><span class="code-line"><span class="token plain-text">    </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">Dialogue.Line</span></span><span class="token punctuation">&gt;</span></span><span class="token plain-text">- Hi! How can I help you? - the employee asks.</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token class-name">Dialogue.Line</span></span><span class="token punctuation">&gt;</span></span><span class="token plain-text">
</span></span><span class="code-line"><span class="token plain-text">    </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">Dialogue.Line</span></span><span class="token punctuation">&gt;</span></span><span class="token plain-text">- Hello! I would like to deliver this package - you raise your hands, holding a parcel, a bit higher - I already filled in the form. - you show your handwriting - Can you check if it&#x27;s fine?</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token class-name">Dialogue.Line</span></span><span class="token punctuation">&gt;</span></span><span class="token plain-text">
</span></span><span class="code-line"><span class="token plain-text">    </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">Dialogue.Line</span></span><span class="token punctuation">&gt;</span></span><span class="token plain-text">- Yes, let me take a look.</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token class-name">Dialogue.Line</span></span><span class="token punctuation">&gt;</span></span><span class="token plain-text">
</span></span><span class="code-line"><span class="token plain-text">    </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">Dialogue.Line</span></span><span class="token punctuation">&gt;</span></span><span class="token plain-text"> ~ The employee checks the form and the delivery letter. ~ </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token class-name">Dialogue.Line</span></span><span class="token punctuation">&gt;</span></span><span class="token plain-text">
</span></span><span class="code-line"><span class="token plain-text">    </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">Dialogue.Line</span></span><span class="token punctuation">&gt;</span></span><span class="token plain-text">- Hmm, seems like you mistakenly swapped address cell and phone cell. Also postal code isn&#x27;t filled in correctly. </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token class-name">Dialogue.Line</span></span><span class="token punctuation">&gt;</span></span><span class="token plain-text">
</span></span><span class="code-line"><span class="token plain-text">    </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">Dialogue.Line</span></span><span class="token punctuation">&gt;</span></span><span class="token plain-text"> ~ You frown your eyebrows a bit, but continue the dialogue. ~ </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token class-name">Dialogue.Line</span></span><span class="token punctuation">&gt;</span></span><span class="token plain-text">
</span></span><span class="code-line"><span class="token plain-text">    </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">Dialogue.Line</span></span><span class="token punctuation">&gt;</span></span><span class="token plain-text">- What&#x27;s wrong with the postal code? - you asks politely. </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token class-name">Dialogue.Line</span></span><span class="token punctuation">&gt;</span></span><span class="token plain-text">
</span></span><span class="code-line"><span class="token plain-text">    </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">Dialogue.Line</span></span><span class="token punctuation">&gt;</span></span><span class="token plain-text">- Oh, sorry for not being explicit! You forgot the &quot;-&quot; in between the numbers*.</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token class-name">Dialogue.Line</span></span><span class="token punctuation">&gt;</span></span><span class="token plain-text">
</span></span><span class="code-line"><span class="token plain-text"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token class-name">Dialogue</span></span><span class="token punctuation">&gt;</span></span>
</span></code></pre></div></div><h3 id="leaving-technical-terms-aside"><a href="#leaving-technical-terms-aside" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Leaving technical terms aside</h3><p>Moving away from technical language and approaching conversation-like design might have interesting benefits, since we really know how to interact with other people.</p><p>What if we go a bit further with out metaphor - and introduce another imaginary person to our conversation?</p><p>We would be able to talk to them both at the same time and it might be that they, e.g. would argue that something is only within the area of responsiblity of the first interlocutor?</p><p>This metaphor isn&#x27;t limited to local software constructs like classes, functions or types - could we go even further and model conversation between services?</p><p>Pretending that services are people doing various operations, how would their discussion look like?</p><p>Let&#x27;s play with this metaphor more and use more concepts from &quot;conversation&quot; domain!</p><p>As we model our software constructs with people talking to each other, here are next questions we could think of:</p><ul><li>What would mean that &quot;person A sends an email to person B&quot;?</li><li>What would mean that &quot;person C calls person D directly&quot;?</li><li>What would mean that &quot;person D didn&#x27;t pick up the phone?&quot;</li></ul><h3 id="the-metaphor"><a href="#the-metaphor" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>The metaphor</h3><p>One might say that such approach is silly, overstretched and exaggerated - &quot;who has time for that?&quot;</p><p>It is probably like with other models - intially they seem dubious and unusable. As Mr. Box stated:</p><blockquote><p>All models are wrong (<em>imperfect</em> - my understanding). But some of them are useful.</p></blockquote><p>Metaphors (which are in fact mental models), we are using for various aspects of our lives, really matter. They bring different sets of concepts, primitives, terms and meanings. We are faced with manifold of abstractions that are related to metaphors we are choosing.</p><p>Once, I read that the metaphors separate winners from losers. I doubt that someone could be a winner when it comes to designing a system/a class/a function/a module/etc.</p><p>Nevertheless, having another mental model in your pocket, while you are designing the interaction with your software constructs, might bring new perspectives on how they look like and work.</p><p>I think it might get even more interesting when we would &quot;summon&quot; a group of such imaginary people and call them a &quot;company&quot; - how would they interact to achieve bigger goal like some of their domain capabilities?</p>]]></content:encoded>
    <pubDate>Mon, 25 Jul 2022 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>programming</category><category>paradigms</category><category>domain-driven design</category><category>problem-solving</category><category>language</category><category>learning</category><category>metaphors</category><category>models</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/essentially-bounded-accidentally-unlimited</guid>
    <title>Essentially bounded, Accidentally unlimited</title>
    <link>https://talesfrom.dev/blog/essentially-bounded-accidentally-unlimited</link>
    <description>An observation on the missing piece of problem solving</description>
    
    <pubDate>Mon, 18 Jul 2022 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>programming</category><category>paradigms</category><category>domain-driven design</category><category>problem-solving</category><category>education</category><category>learning</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/where-did-my-methods-go</guid>
    <title>Where did my methods go?</title>
    <link>https://talesfrom.dev/blog/where-did-my-methods-go</link>
    <description>How I discovered Functional Programming and re-discovered Object-Oriented Programming</description>
    
    <pubDate>Tue, 28 Jun 2022 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>oop</category><category>fp</category><category>object-oriented</category><category>functional</category><category>programming</category><category>languages</category><category>paradigms</category><category>domain-driven design</category>
  </item>

  <item>
    <guid>https://talesfrom.dev/blog/hello-world</guid>
    <title>Hello world!</title>
    <link>https://talesfrom.dev/blog/hello-world</link>
    <description>How to spin up Kubernetes cluster and deploy Graph Neural Network</description>
    <content:encoded><![CDATA[<h2 id="introduction"><a href="#introduction" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Introduction</h2><p>In this post I will show you how to spin up Kubernetes cluster, deploy Graph Neural Network model to predict Monoidal nature of your soul in order...No, no. Wait a sec.</p><h2 id="true-introduction"><a href="#true-introduction" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>True Introduction</h2><p>Day by day we are getting lost in the phletora of mental models that are stealing our attention from the core, from the essence.</p><p>And essentially what I really wanted to do in this first post is to just say: hello world.</p><p>I don&#x27;t know (yet) where this blog will lead to, but I would really like to spend some time for materializing and externalizing my thoughts so that I am getting beaten by the feedback I will get so that, almost like Prince Vegeta from Dragon Ball series, I will become stronger and...Communicate better?</p><h2 id="read-to-find-new-ideas-write-to-understand-them"><a href="#read-to-find-new-ideas-write-to-understand-them" aria-hidden="true" tabindex="-1"><span class="icon icon-link"></span></a>Read to find new ideas. Write to understand them.</h2><p>I found <a href="https://twitter.com/EricJorgenson/status/1118699602780262402">this</a> tweet today and it stopped me for a while from brainless scrolling through twitter infinite feed. It is simple in its nature, but deep in the meaning.</p><p>It made me thinking about all the great resources about coding, examples, projects that I see, browse, explore and learn from. Am I actually understanding them or just...Reading?</p><p>I would really like to be a bleeding-edge code producer, example-giver and line-breaker. Somehow, under my skin, I feel that we are making cycles - frameworks are changing, languages come and stay (or go?), but I think we should talk more about the ideas, more about the models and patterns we use on our daily basis.</p><p>With this philosophical accent, let&#x27;s end it.</p>]]></content:encoded>
    <pubDate>Tue, 21 Jun 2022 00:00:00 GMT</pubDate>
    <dc:creator><![CDATA[Damian Płaza]]></dc:creator>
    <category>first</category><category>introduction</category><category>new</category>
  </item>

    </channel>
  </rss>
